1727da7e7SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2727da7e7SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 33a8779fbSJames Wright // 4727da7e7SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 53a8779fbSJames Wright // 6727da7e7SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 73a8779fbSJames Wright 83a8779fbSJames Wright /// @file 93a8779fbSJames Wright /// Operator for Navier-Stokes example using PETSc 103a8779fbSJames Wright 113a8779fbSJames Wright #ifndef newtonian_h 123a8779fbSJames Wright #define newtonian_h 133a8779fbSJames Wright 143a8779fbSJames Wright #include <ceed.h> 15d0cce58aSJeremy L Thompson #include <math.h> 167b530f2aSAdelekeBankole #include <stdlib.h> 172b916ea7SJeremy L Thompson 18475b2820SJames Wright #include "newtonian_state.h" 19d0cce58aSJeremy L Thompson #include "newtonian_types.h" 20d1b9ef12SLeila Ghaffari #include "stabilization.h" 21d0cce58aSJeremy L Thompson #include "utils.h" 22bb8a0c61SJames Wright 23bb8a0c61SJames Wright // ***************************************************************************** 243a8779fbSJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 253a8779fbSJames Wright // ***************************************************************************** 262b916ea7SJeremy L Thompson CEED_QFUNCTION(ICsNewtonianIG)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 273a8779fbSJames Wright // Inputs 283a8779fbSJames Wright const CeedScalar(*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 293a8779fbSJames Wright 303a8779fbSJames Wright // Outputs 313a8779fbSJames Wright CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 323a8779fbSJames Wright 33bb8a0c61SJames Wright // Context 34bb8a0c61SJames Wright const SetupContext context = (SetupContext)ctx; 35bb8a0c61SJames Wright const CeedScalar theta0 = context->theta0; 36bb8a0c61SJames Wright const CeedScalar P0 = context->P0; 37bb8a0c61SJames Wright const CeedScalar cv = context->cv; 38bb8a0c61SJames Wright const CeedScalar cp = context->cp; 39bb8a0c61SJames Wright const CeedScalar *g = context->g; 40bb8a0c61SJames Wright const CeedScalar Rd = cp - cv; 41bb8a0c61SJames Wright 423a8779fbSJames Wright // Quadrature Point Loop 432b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 443a8779fbSJames Wright CeedScalar q[5] = {0.}; 453a8779fbSJames Wright 463a8779fbSJames Wright // Setup 473a8779fbSJames Wright // -- Coordinates 48bb8a0c61SJames Wright const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]}; 49d1b9ef12SLeila Ghaffari const CeedScalar e_potential = -Dot3(g, x); 503a8779fbSJames Wright 513a8779fbSJames Wright // -- Density 52bb8a0c61SJames Wright const CeedScalar rho = P0 / (Rd * theta0); 533a8779fbSJames Wright 543a8779fbSJames Wright // Initial Conditions 553a8779fbSJames Wright q[0] = rho; 563a8779fbSJames Wright q[1] = 0.0; 573a8779fbSJames Wright q[2] = 0.0; 583a8779fbSJames Wright q[3] = 0.0; 59bb8a0c61SJames Wright q[4] = rho * (cv * theta0 + e_potential); 603a8779fbSJames Wright 612b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j]; 62d1b9ef12SLeila Ghaffari 633a8779fbSJames Wright } // End of Quadrature Point Loop 643a8779fbSJames Wright return 0; 653a8779fbSJames Wright } 663a8779fbSJames Wright 673a8779fbSJames Wright // ***************************************************************************** 68*04e40bb6SJeremy L Thompson // This QFunction sets a "still" initial condition for generic Newtonian IG problems in primitive variables 69cbe60e31SLeila Ghaffari // ***************************************************************************** 702b916ea7SJeremy L Thompson CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 71cbe60e31SLeila Ghaffari // Outputs 72cbe60e31SLeila Ghaffari CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 73cbe60e31SLeila Ghaffari 74cbe60e31SLeila Ghaffari // Context 75cbe60e31SLeila Ghaffari const SetupContext context = (SetupContext)ctx; 76cbe60e31SLeila Ghaffari const CeedScalar theta0 = context->theta0; 77cbe60e31SLeila Ghaffari const CeedScalar P0 = context->P0; 78cbe60e31SLeila Ghaffari 79cbe60e31SLeila Ghaffari // Quadrature Point Loop 802b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 81cbe60e31SLeila Ghaffari CeedScalar q[5] = {0.}; 82cbe60e31SLeila Ghaffari 83cbe60e31SLeila Ghaffari // Initial Conditions 84cbe60e31SLeila Ghaffari q[0] = P0; 85cbe60e31SLeila Ghaffari q[1] = 0.0; 86cbe60e31SLeila Ghaffari q[2] = 0.0; 87cbe60e31SLeila Ghaffari q[3] = 0.0; 88cbe60e31SLeila Ghaffari q[4] = theta0; 89cbe60e31SLeila Ghaffari 902b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j]; 91cbe60e31SLeila Ghaffari 92cbe60e31SLeila Ghaffari } // End of Quadrature Point Loop 93cbe60e31SLeila Ghaffari return 0; 94cbe60e31SLeila Ghaffari } 95cbe60e31SLeila Ghaffari 96cbe60e31SLeila Ghaffari // ***************************************************************************** 97*04e40bb6SJeremy L Thompson // This QFunction implements the following formulation of Navier-Stokes with explicit time stepping method 983a8779fbSJames Wright // 99*04e40bb6SJeremy L Thompson // This is 3D compressible Navier-Stokes in conservation form with state variables of density, momentum density, and total energy density. 1003a8779fbSJames Wright // 1013a8779fbSJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 1023a8779fbSJames Wright // rho - Mass Density 1033a8779fbSJames Wright // Ui - Momentum Density, Ui = rho ui 1043a8779fbSJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 1053a8779fbSJames Wright // 1063a8779fbSJames Wright // Navier-Stokes Equations: 1073a8779fbSJames Wright // drho/dt + div( U ) = 0 1083a8779fbSJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 1093a8779fbSJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 1103a8779fbSJames Wright // 1113a8779fbSJames Wright // Viscous Stress: 1123a8779fbSJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 1133a8779fbSJames Wright // 1143a8779fbSJames Wright // Thermal Stress: 1153a8779fbSJames Wright // Fe = u Fu + k grad( T ) 116bb8a0c61SJames Wright // Equation of State 1173a8779fbSJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 1183a8779fbSJames Wright // 1193a8779fbSJames Wright // Stabilization: 1203a8779fbSJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 1213a8779fbSJames Wright // f1 = rho sqrt(ui uj gij) 1223a8779fbSJames Wright // gij = dXi/dX * dXi/dX 1233a8779fbSJames Wright // TauC = Cc f1 / (8 gii) 1243a8779fbSJames Wright // TauM = min( 1 , 1 / f1 ) 1253a8779fbSJames Wright // TauE = TauM / (Ce cv) 1263a8779fbSJames Wright // 1273a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 1283a8779fbSJames Wright // 1293a8779fbSJames Wright // Constants: 1303a8779fbSJames Wright // lambda = - 2 / 3, From Stokes hypothesis 1313a8779fbSJames Wright // mu , Dynamic viscosity 1323a8779fbSJames Wright // k , Thermal conductivity 1333a8779fbSJames Wright // cv , Specific heat, constant volume 1343a8779fbSJames Wright // cp , Specific heat, constant pressure 1353a8779fbSJames Wright // g , Gravity 1363a8779fbSJames Wright // gamma = cp / cv, Specific heat ratio 1373a8779fbSJames Wright // 138*04e40bb6SJeremy L Thompson // We require the product of the inverse of the Jacobian (dXdx_j,k) and its transpose (dXdx_k,j) to properly compute integrals of the form: int( gradv 139*04e40bb6SJeremy L Thompson // gradu ) 1403a8779fbSJames Wright // ***************************************************************************** 1412b916ea7SJeremy L Thompson CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 1423a8779fbSJames Wright // Inputs 1433d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 1443d65b166SJames Wright const CeedScalar(*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1]; 1453d65b166SJames Wright const CeedScalar(*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 1463d65b166SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 1473d65b166SJames Wright 1483a8779fbSJames Wright // Outputs 1493d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 1503d65b166SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 1513a8779fbSJames Wright 1523a8779fbSJames Wright // Context 1533a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 154bb8a0c61SJames Wright const CeedScalar *g = context->g; 155bb8a0c61SJames Wright const CeedScalar dt = context->dt; 1563a8779fbSJames Wright 1573a8779fbSJames Wright // Quadrature Point Loop 1583d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 159c1a52365SJed Brown CeedScalar U[5]; 160c1a52365SJed Brown for (int j = 0; j < 5; j++) U[j] = q[j][i]; 161c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 162c1a52365SJed Brown State s = StateFromU(context, U, x_i); 163c1a52365SJed Brown 1643a8779fbSJames Wright // -- Interp-to-Interp q_data 1653a8779fbSJames Wright const CeedScalar wdetJ = q_data[0][i]; 1663a8779fbSJames Wright // -- Interp-to-Grad q_data 1673a8779fbSJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 1682b916ea7SJeremy L Thompson const CeedScalar dXdx[3][3] = { 1692b916ea7SJeremy L Thompson {q_data[1][i], q_data[2][i], q_data[3][i]}, 17034ea8d65SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 17134ea8d65SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 1723a8779fbSJames Wright }; 173c1a52365SJed Brown State grad_s[3]; 174eef2387dSJed Brown for (CeedInt j = 0; j < 3; j++) { 1752f7ce6c1SJed Brown CeedScalar dx_i[3] = {0}, dU[5]; 1762b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) dU[k] = Grad_q[0][k][i] * dXdx[0][j] + Grad_q[1][k][i] * dXdx[1][j] + Grad_q[2][k][i] * dXdx[2][j]; 177c1a52365SJed Brown dx_i[j] = 1.; 1782f7ce6c1SJed Brown grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 179c1a52365SJed Brown } 180c1a52365SJed Brown 181c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 182c1a52365SJed Brown KMStrainRate(grad_s, strain_rate); 183c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 184c1a52365SJed Brown KMUnpack(kmstress, stress); 185c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 186c1a52365SJed Brown 187c1a52365SJed Brown StateConservative F_inviscid[3]; 188c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 189c1a52365SJed Brown 190c1a52365SJed Brown // Total flux 191c1a52365SJed Brown CeedScalar Flux[5][3]; 192d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 193c1a52365SJed Brown 1942b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 3; j++) { 1952b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) Grad_v[j][k][i] = wdetJ * (dXdx[j][0] * Flux[k][0] + dXdx[j][1] * Flux[k][1] + dXdx[j][2] * Flux[k][2]); 1962b916ea7SJeremy L Thompson } 197c1a52365SJed Brown 198c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density * g[0], s.U.density * g[1], s.U.density * g[2], 0}; 1992b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * body_force[j]; 2003a8779fbSJames Wright 201d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 202d1b9ef12SLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 203d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 204d1b9ef12SLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 2053a8779fbSJames Wright 2062b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 2072b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 3; k++) Grad_v[k][j][i] -= wdetJ * (stab[j][0] * dXdx[k][0] + stab[j][1] * dXdx[k][1] + stab[j][2] * dXdx[k][2]); 2082b916ea7SJeremy L Thompson } 2093a8779fbSJames Wright } // End Quadrature Point Loop 2103a8779fbSJames Wright 2113a8779fbSJames Wright // Return 2123a8779fbSJames Wright return 0; 2133a8779fbSJames Wright } 2143a8779fbSJames Wright 2153a8779fbSJames Wright // ***************************************************************************** 216*04e40bb6SJeremy L Thompson // This QFunction implements the Navier-Stokes equations (mentioned above) with implicit time stepping method 2173a8779fbSJames Wright // 2183a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 2193a8779fbSJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 220*04e40bb6SJeremy L Thompson // (diffusive terms will be added later) 2213a8779fbSJames Wright // ***************************************************************************** 2222b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateFromQi_t StateFromQi, 2232b916ea7SJeremy L Thompson StateFromQi_fwd_t StateFromQi_fwd) { 2243a8779fbSJames Wright // Inputs 2253d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 2263d65b166SJames Wright const CeedScalar(*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1]; 2273d65b166SJames Wright const CeedScalar(*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 2283d65b166SJames Wright const CeedScalar(*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 2293d65b166SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 2303d65b166SJames Wright 2313a8779fbSJames Wright // Outputs 2323d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 2333d65b166SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 2343d65b166SJames Wright CeedScalar(*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 2353d65b166SJames Wright 2363a8779fbSJames Wright // Context 2373a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 238bb8a0c61SJames Wright const CeedScalar *g = context->g; 239bb8a0c61SJames Wright const CeedScalar dt = context->dt; 2403a8779fbSJames Wright 2413a8779fbSJames Wright // Quadrature Point Loop 2423d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 2433d65b166SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 244c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 2453d65b166SJames Wright const State s = StateFromQi(context, qi, x_i); 246c1a52365SJed Brown 2473a8779fbSJames Wright // -- Interp-to-Interp q_data 2483a8779fbSJames Wright const CeedScalar wdetJ = q_data[0][i]; 2493a8779fbSJames Wright // -- Interp-to-Grad q_data 2503a8779fbSJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 2512b916ea7SJeremy L Thompson const CeedScalar dXdx[3][3] = { 2522b916ea7SJeremy L Thompson {q_data[1][i], q_data[2][i], q_data[3][i]}, 25334ea8d65SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 25434ea8d65SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 2553a8779fbSJames Wright }; 256c1a52365SJed Brown State grad_s[3]; 257493642f1SJames Wright for (CeedInt j = 0; j < 3; j++) { 25876555becSJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 2593d65b166SJames Wright for (CeedInt k = 0; k < 5; k++) { 2603d65b166SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + Grad_q[1][k][i] * dXdx[1][j] + Grad_q[2][k][i] * dXdx[2][j]; 2613d65b166SJames Wright } 262c1a52365SJed Brown dx_i[j] = 1.; 26376555becSJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 2643a8779fbSJames Wright } 265c1a52365SJed Brown 266c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 267c1a52365SJed Brown KMStrainRate(grad_s, strain_rate); 268c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 269c1a52365SJed Brown KMUnpack(kmstress, stress); 270c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 271c1a52365SJed Brown 272c1a52365SJed Brown StateConservative F_inviscid[3]; 273c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 274c1a52365SJed Brown 275c1a52365SJed Brown // Total flux 276c1a52365SJed Brown CeedScalar Flux[5][3]; 277d1b9ef12SLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 278c1a52365SJed Brown 2792b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 3; j++) { 2803d65b166SJames Wright for (CeedInt k = 0; k < 5; k++) { 2813d65b166SJames Wright Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + dXdx[j][1] * Flux[k][1] + dXdx[j][2] * Flux[k][2]); 2823d65b166SJames Wright } 2832b916ea7SJeremy L Thompson } 284c1a52365SJed Brown 285c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density * g[0], s.U.density * g[1], s.U.density * g[2], 0}; 2863a8779fbSJames Wright 287d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 28876555becSJames Wright CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}, qi_dot[5], dx0[3] = {0}; 28976555becSJames Wright for (int j = 0; j < 5; j++) qi_dot[j] = q_dot[j][i]; 29076555becSJames Wright State s_dot = StateFromQi_fwd(context, s, qi_dot, x_i, dx0); 29176555becSJames Wright UnpackState_U(s_dot.U, U_dot); 29276555becSJames Wright 2932b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 294d1b9ef12SLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 295d1b9ef12SLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 2963a8779fbSJames Wright 2972b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 2983d65b166SJames Wright for (CeedInt k = 0; k < 3; k++) { 2993d65b166SJames Wright Grad_v[k][j][i] += wdetJ * (stab[j][0] * dXdx[k][0] + stab[j][1] * dXdx[k][1] + stab[j][2] * dXdx[k][2]); 3003d65b166SJames Wright } 3012b916ea7SJeremy L Thompson } 30276555becSJames Wright for (CeedInt j = 0; j < 5; j++) jac_data[j][i] = qi[j]; 303eef2387dSJed Brown for (CeedInt j = 0; j < 6; j++) jac_data[5 + j][i] = kmstress[j]; 304eef2387dSJed Brown for (CeedInt j = 0; j < 3; j++) jac_data[5 + 6 + j][i] = Tau_d[j]; 3053a8779fbSJames Wright 3063a8779fbSJames Wright } // End Quadrature Point Loop 3073a8779fbSJames Wright 3083a8779fbSJames Wright // Return 3093a8779fbSJames Wright return 0; 3103a8779fbSJames Wright } 311f0b65372SJed Brown 3122b916ea7SJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 31376555becSJames Wright return IFunction_Newtonian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 31476555becSJames Wright } 31576555becSJames Wright 3162b916ea7SJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 31776555becSJames Wright return IFunction_Newtonian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 31876555becSJames Wright } 31976555becSJames Wright 320cbe60e31SLeila Ghaffari // ***************************************************************************** 321*04e40bb6SJeremy L Thompson // This QFunction implements the jacobian of the Navier-Stokes equations for implicit time stepping method. 322cbe60e31SLeila Ghaffari // ***************************************************************************** 3232b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateFromQi_t StateFromQi, 3242b916ea7SJeremy L Thompson StateFromQi_fwd_t StateFromQi_fwd) { 325f0b65372SJed Brown // Inputs 3263d65b166SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 3273d65b166SJames Wright const CeedScalar(*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1]; 3283d65b166SJames Wright const CeedScalar(*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 3293d65b166SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 3303d65b166SJames Wright const CeedScalar(*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 3313d65b166SJames Wright 332f0b65372SJed Brown // Outputs 3333d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 3343d65b166SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 3353d65b166SJames Wright 336f0b65372SJed Brown // Context 337f0b65372SJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 338f0b65372SJed Brown const CeedScalar *g = context->g; 339f0b65372SJed Brown 340f0b65372SJed Brown // Quadrature Point Loop 3413d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 342f0b65372SJed Brown // -- Interp-to-Interp q_data 343f0b65372SJed Brown const CeedScalar wdetJ = q_data[0][i]; 344f0b65372SJed Brown // -- Interp-to-Grad q_data 345f0b65372SJed Brown // ---- Inverse of change of coordinate matrix: X_i,j 3462b916ea7SJeremy L Thompson const CeedScalar dXdx[3][3] = { 3472b916ea7SJeremy L Thompson {q_data[1][i], q_data[2][i], q_data[3][i]}, 34834ea8d65SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 34934ea8d65SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 350f0b65372SJed Brown }; 351f0b65372SJed Brown 3528789e95fSJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3]; 35376555becSJames Wright for (int j = 0; j < 5; j++) qi[j] = jac_data[j][i]; 354f0b65372SJed Brown for (int j = 0; j < 6; j++) kmstress[j] = jac_data[5 + j][i]; 355f0b65372SJed Brown for (int j = 0; j < 3; j++) Tau_d[j] = jac_data[5 + 6 + j][i]; 356f0b65372SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 35776555becSJames Wright State s = StateFromQi(context, qi, x_i); 358f0b65372SJed Brown 35976555becSJames Wright CeedScalar dqi[5], dx0[3] = {0}; 36076555becSJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 36176555becSJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx0); 362f0b65372SJed Brown 363f0b65372SJed Brown State grad_ds[3]; 364f0b65372SJed Brown for (int j = 0; j < 3; j++) { 36576555becSJames Wright CeedScalar dqi_j[5]; 3662b916ea7SJeremy L Thompson for (int k = 0; k < 5; k++) dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + Grad_dq[1][k][i] * dXdx[1][j] + Grad_dq[2][k][i] * dXdx[2][j]; 36776555becSJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx0); 368f0b65372SJed Brown } 369f0b65372SJed Brown 370f0b65372SJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 371f0b65372SJed Brown KMStrainRate(grad_ds, dstrain_rate); 372f0b65372SJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 373f0b65372SJed Brown KMUnpack(dkmstress, dstress); 374f0b65372SJed Brown KMUnpack(kmstress, stress); 375f0b65372SJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 376f0b65372SJed Brown 377f0b65372SJed Brown StateConservative dF_inviscid[3]; 378f0b65372SJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 379f0b65372SJed Brown 380f0b65372SJed Brown // Total flux 381f0b65372SJed Brown CeedScalar dFlux[5][3]; 382d1b9ef12SLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 383f0b65372SJed Brown 3842b916ea7SJeremy L Thompson for (int j = 0; j < 3; j++) { 3852b916ea7SJeremy L Thompson for (int k = 0; k < 5; k++) Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + dXdx[j][1] * dFlux[k][1] + dXdx[j][2] * dFlux[k][2]); 3862b916ea7SJeremy L Thompson } 387f0b65372SJed Brown 388f0b65372SJed Brown const CeedScalar dbody_force[5] = {0, ds.U.density * g[0], ds.U.density * g[1], ds.U.density * g[2], 0}; 38976555becSJames Wright CeedScalar dU[5] = {0.}; 39076555becSJames Wright UnpackState_U(ds.U, dU); 3912b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 392f0b65372SJed Brown 393d1b9ef12SLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 394d1b9ef12SLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 395d1b9ef12SLeila Ghaffari for (CeedInt j = 0; j < 5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 396d1b9ef12SLeila Ghaffari Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, x_i, dstab); 397d1b9ef12SLeila Ghaffari 3982b916ea7SJeremy L Thompson for (int j = 0; j < 5; j++) { 3992b916ea7SJeremy L Thompson for (int k = 0; k < 3; k++) Grad_v[k][j][i] += wdetJ * (dstab[j][0] * dXdx[k][0] + dstab[j][1] * dXdx[k][1] + dstab[j][2] * dXdx[k][2]); 4002b916ea7SJeremy L Thompson } 401f0b65372SJed Brown } // End Quadrature Point Loop 402f0b65372SJed Brown return 0; 403f0b65372SJed Brown } 4048085925cSJames Wright 4052b916ea7SJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 40676555becSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 40776555becSJames Wright } 40876555becSJames Wright 4092b916ea7SJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 41076555becSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 41176555becSJames Wright } 41276555becSJames Wright 413d1b9ef12SLeila Ghaffari // ***************************************************************************** 4148085925cSJames Wright // Compute boundary integral (ie. for strongly set inflows) 415d1b9ef12SLeila Ghaffari // ***************************************************************************** 4162b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateFromQi_t StateFromQi, 4172b916ea7SJeremy L Thompson StateFromQi_fwd_t StateFromQi_fwd) { 4183d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 4193d65b166SJames Wright const CeedScalar(*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1]; 4203d65b166SJames Wright const CeedScalar(*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 4213d65b166SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 4228085925cSJames Wright 4233d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 4243d65b166SJames Wright CeedScalar(*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 4258085925cSJames Wright 426d3b25f3aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 427d3b25f3aSJames Wright const bool is_implicit = context->is_implicit; 4288085925cSJames Wright 4292b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 430d3b25f3aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 43141e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 43241e73928SJames Wright State s = StateFromQi(context, qi, x_i); 4338085925cSJames Wright 4348085925cSJames Wright const CeedScalar wdetJb = (is_implicit ? -1. : 1.) * q_data_sur[0][i]; 435c5740391SJames Wright // ---- Normal vector 4362b916ea7SJeremy L Thompson const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 4378085925cSJames Wright 438d3b25f3aSJames Wright const CeedScalar dXdx[2][3] = { 439d3b25f3aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 440d3b25f3aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 441d3b25f3aSJames Wright }; 4428085925cSJames Wright 443d3b25f3aSJames Wright State grad_s[3]; 444d3b25f3aSJames Wright for (CeedInt j = 0; j < 3; j++) { 44541e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 4462b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + Grad_q[1][k][i] * dXdx[1][j]; 447d3b25f3aSJames Wright dx_i[j] = 1.; 44841e73928SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 449d3b25f3aSJames Wright } 4508085925cSJames Wright 451d3b25f3aSJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 452d3b25f3aSJames Wright KMStrainRate(grad_s, strain_rate); 453d3b25f3aSJames Wright NewtonianStress(context, strain_rate, kmstress); 454d3b25f3aSJames Wright KMUnpack(kmstress, stress); 455d3b25f3aSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 456d3b25f3aSJames Wright 457d3b25f3aSJames Wright StateConservative F_inviscid[3]; 458d3b25f3aSJames Wright FluxInviscid(context, s, F_inviscid); 459d3b25f3aSJames Wright 460c5740391SJames Wright CeedScalar Flux[5]; 461c5740391SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 462d3b25f3aSJames Wright 463c5740391SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 4648085925cSJames Wright 465c5740391SJames Wright for (int j = 0; j < 5; j++) jac_data_sur[j][i] = qi[j]; 46668ae065aSJames Wright for (int j = 0; j < 6; j++) jac_data_sur[5 + j][i] = kmstress[j]; 4678085925cSJames Wright } 4688085925cSJames Wright return 0; 4698085925cSJames Wright } 4708085925cSJames Wright 4712b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 472d4559bbeSJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromU, StateFromU_fwd); 473d4559bbeSJames Wright } 474d4559bbeSJames Wright 4752b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 476d4559bbeSJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromY, StateFromY_fwd); 477d4559bbeSJames Wright } 478d4559bbeSJames Wright 479d1b9ef12SLeila Ghaffari // ***************************************************************************** 48068ae065aSJames Wright // Jacobian for "set nothing" boundary integral 481d1b9ef12SLeila Ghaffari // ***************************************************************************** 4822b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 483d4559bbeSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 48468ae065aSJames Wright // Inputs 4853d65b166SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 4863d65b166SJames Wright const CeedScalar(*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1]; 4873d65b166SJames Wright const CeedScalar(*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 4883d65b166SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 4893d65b166SJames Wright const CeedScalar(*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 4903d65b166SJames Wright 49168ae065aSJames Wright // Outputs 49268ae065aSJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 49368ae065aSJames Wright 49468ae065aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 49568ae065aSJames Wright const bool implicit = context->is_implicit; 49668ae065aSJames Wright 49768ae065aSJames Wright // Quadrature Point Loop 4983d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 49968ae065aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 50068ae065aSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 5012b916ea7SJeremy L Thompson const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 50268ae065aSJames Wright const CeedScalar dXdx[2][3] = { 50368ae065aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 50468ae065aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 50568ae065aSJames Wright }; 50668ae065aSJames Wright 50741e73928SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 50841e73928SJames Wright for (int j = 0; j < 5; j++) qi[j] = jac_data_sur[j][i]; 50968ae065aSJames Wright for (int j = 0; j < 6; j++) kmstress[j] = jac_data_sur[5 + j][i]; 51041e73928SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 5113934e2b1SJames Wright 51241e73928SJames Wright State s = StateFromQi(context, qi, x_i); 51341e73928SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 51468ae065aSJames Wright 51568ae065aSJames Wright State grad_ds[3]; 51668ae065aSJames Wright for (CeedInt j = 0; j < 3; j++) { 51741e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 5182b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + Grad_dq[1][k][i] * dXdx[1][j]; 51968ae065aSJames Wright dx_i[j] = 1.; 52041e73928SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 52168ae065aSJames Wright } 52268ae065aSJames Wright 52368ae065aSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 52468ae065aSJames Wright KMStrainRate(grad_ds, dstrain_rate); 52568ae065aSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 52668ae065aSJames Wright KMUnpack(dkmstress, dstress); 52768ae065aSJames Wright KMUnpack(kmstress, stress); 52868ae065aSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 52968ae065aSJames Wright 53068ae065aSJames Wright StateConservative dF_inviscid[3]; 53168ae065aSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 53268ae065aSJames Wright 533c5740391SJames Wright CeedScalar dFlux[5]; 534c5740391SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 53568ae065aSJames Wright 536c5740391SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 53768ae065aSJames Wright } // End Quadrature Point Loop 53868ae065aSJames Wright return 0; 53968ae065aSJames Wright } 54068ae065aSJames Wright 5412b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 542d4559bbeSJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 543d4559bbeSJames Wright } 544d4559bbeSJames Wright 5452b916ea7SJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 546d4559bbeSJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 547d4559bbeSJames Wright } 548d4559bbeSJames Wright 549d1b9ef12SLeila Ghaffari // ***************************************************************************** 55004b9037bSJames Wright // Outflow boundary condition, weakly setting a constant pressure 551d1b9ef12SLeila Ghaffari // ***************************************************************************** 5522b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int PressureOutflow(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateFromQi_t StateFromQi, 5532b916ea7SJeremy L Thompson StateFromQi_fwd_t StateFromQi_fwd) { 55404b9037bSJames Wright // Inputs 5553d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 5563d65b166SJames Wright const CeedScalar(*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1]; 5573d65b166SJames Wright const CeedScalar(*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 5583d65b166SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 5593d65b166SJames Wright 56004b9037bSJames Wright // Outputs 5613d65b166SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 5623d65b166SJames Wright CeedScalar(*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 56304b9037bSJames Wright 56404b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 56504b9037bSJames Wright const bool implicit = context->is_implicit; 56604b9037bSJames Wright const CeedScalar P0 = context->P0; 56704b9037bSJames Wright 56804b9037bSJames Wright // Quadrature Point Loop 5693d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 57004b9037bSJames Wright // Setup 57104b9037bSJames Wright // -- Interp in 57225bfcc41SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 57341e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 57441e73928SJames Wright State s = StateFromQi(context, qi, x_i); 57525bfcc41SJames Wright s.Y.pressure = P0; 57604b9037bSJames Wright 57704b9037bSJames Wright // -- Interp-to-Interp q_data 57804b9037bSJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 57904b9037bSJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 58004b9037bSJames Wright // We can effect this by swapping the sign on this weight 58104b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 58204b9037bSJames Wright 583c5740391SJames Wright // ---- Normal vector 584d4559bbeSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 58504b9037bSJames Wright 58625bfcc41SJames Wright const CeedScalar dXdx[2][3] = { 58725bfcc41SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 58825bfcc41SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 58925bfcc41SJames Wright }; 59004b9037bSJames Wright 59125bfcc41SJames Wright State grad_s[3]; 59225bfcc41SJames Wright for (CeedInt j = 0; j < 3; j++) { 59341e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 5942b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + Grad_q[1][k][i] * dXdx[1][j]; 59525bfcc41SJames Wright dx_i[j] = 1.; 59641e73928SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 59725bfcc41SJames Wright } 59825bfcc41SJames Wright 59925bfcc41SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 60025bfcc41SJames Wright KMStrainRate(grad_s, strain_rate); 60125bfcc41SJames Wright NewtonianStress(context, strain_rate, kmstress); 60225bfcc41SJames Wright KMUnpack(kmstress, stress); 60325bfcc41SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 60425bfcc41SJames Wright 60525bfcc41SJames Wright StateConservative F_inviscid[3]; 60625bfcc41SJames Wright FluxInviscid(context, s, F_inviscid); 60725bfcc41SJames Wright 608c5740391SJames Wright CeedScalar Flux[5]; 609c5740391SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 61004b9037bSJames Wright 611c5740391SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 61204b9037bSJames Wright 61304b9037bSJames Wright // Save values for Jacobian 614c5740391SJames Wright for (int j = 0; j < 5; j++) jac_data_sur[j][i] = qi[j]; 615b01ba163SJames Wright for (int j = 0; j < 6; j++) jac_data_sur[5 + j][i] = kmstress[j]; 61604b9037bSJames Wright } // End Quadrature Point Loop 61704b9037bSJames Wright return 0; 61804b9037bSJames Wright } 61904b9037bSJames Wright 6202b916ea7SJeremy L Thompson CEED_QFUNCTION(PressureOutflow_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 621d4559bbeSJames Wright return PressureOutflow(ctx, Q, in, out, StateFromU, StateFromU_fwd); 622d4559bbeSJames Wright } 623d4559bbeSJames Wright 6242b916ea7SJeremy L Thompson CEED_QFUNCTION(PressureOutflow_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 625d4559bbeSJames Wright return PressureOutflow(ctx, Q, in, out, StateFromY, StateFromY_fwd); 626d4559bbeSJames Wright } 627d4559bbeSJames Wright 628d1b9ef12SLeila Ghaffari // ***************************************************************************** 62904b9037bSJames Wright // Jacobian for weak-pressure outflow boundary condition 630d1b9ef12SLeila Ghaffari // ***************************************************************************** 6312b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER int PressureOutflow_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 632d4559bbeSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 63304b9037bSJames Wright // Inputs 6343d65b166SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 6353d65b166SJames Wright const CeedScalar(*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1]; 6363d65b166SJames Wright const CeedScalar(*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 6373d65b166SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 6383d65b166SJames Wright const CeedScalar(*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 6393d65b166SJames Wright 64004b9037bSJames Wright // Outputs 64104b9037bSJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 64204b9037bSJames Wright 64304b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 64404b9037bSJames Wright const bool implicit = context->is_implicit; 64504b9037bSJames Wright 64604b9037bSJames Wright // Quadrature Point Loop 6473d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 648b01ba163SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 64904b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 650d4559bbeSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 651b01ba163SJames Wright const CeedScalar dXdx[2][3] = { 652b01ba163SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 653b01ba163SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 654b01ba163SJames Wright }; 655b01ba163SJames Wright 65641e73928SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 65741e73928SJames Wright for (int j = 0; j < 5; j++) qi[j] = jac_data_sur[j][i]; 658b01ba163SJames Wright for (int j = 0; j < 6; j++) kmstress[j] = jac_data_sur[5 + j][i]; 65941e73928SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 6603934e2b1SJames Wright 66141e73928SJames Wright State s = StateFromQi(context, qi, x_i); 66241e73928SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 663b01ba163SJames Wright s.Y.pressure = context->P0; 664b01ba163SJames Wright ds.Y.pressure = 0.; 665b01ba163SJames Wright 666b01ba163SJames Wright State grad_ds[3]; 667b01ba163SJames Wright for (CeedInt j = 0; j < 3; j++) { 66841e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 6692b916ea7SJeremy L Thompson for (CeedInt k = 0; k < 5; k++) dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + Grad_dq[1][k][i] * dXdx[1][j]; 670b01ba163SJames Wright dx_i[j] = 1.; 67141e73928SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 672b01ba163SJames Wright } 673b01ba163SJames Wright 674b01ba163SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 675b01ba163SJames Wright KMStrainRate(grad_ds, dstrain_rate); 676b01ba163SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 677b01ba163SJames Wright KMUnpack(dkmstress, dstress); 678b01ba163SJames Wright KMUnpack(kmstress, stress); 679b01ba163SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 68004b9037bSJames Wright 681e6b47afbSJames Wright StateConservative dF_inviscid[3]; 682e6b47afbSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 68304b9037bSJames Wright 684c5740391SJames Wright CeedScalar dFlux[5]; 685c5740391SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 686e6b47afbSJames Wright 687c5740391SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 68804b9037bSJames Wright } // End Quadrature Point Loop 68904b9037bSJames Wright return 0; 69004b9037bSJames Wright } 69104b9037bSJames Wright 6922b916ea7SJeremy L Thompson CEED_QFUNCTION(PressureOutflow_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 693d4559bbeSJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 694d4559bbeSJames Wright } 695d4559bbeSJames Wright 6962b916ea7SJeremy L Thompson CEED_QFUNCTION(PressureOutflow_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 697d4559bbeSJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 698d4559bbeSJames Wright } 6992b916ea7SJeremy L Thompson 7003a8779fbSJames Wright #endif // newtonian_h 701