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 <math.h> 163a8779fbSJames Wright #include <ceed.h> 1715a3537eSJed Brown #include "newtonian_types.h" 18475b2820SJames Wright #include "newtonian_state.h" 19*704b8bbeSJames Wright #include "utils.h" 203a8779fbSJames Wright 213a8779fbSJames Wright // ***************************************************************************** 223a8779fbSJames Wright // Helper function for computing flux Jacobian 233a8779fbSJames Wright // ***************************************************************************** 243a8779fbSJames Wright CEED_QFUNCTION_HELPER void computeFluxJacobian_NS(CeedScalar dF[3][5][5], 253a8779fbSJames Wright const CeedScalar rho, const CeedScalar u[3], const CeedScalar E, 26bb8a0c61SJames Wright const CeedScalar gamma, const CeedScalar g[3], const CeedScalar x[3]) { 273a8779fbSJames Wright CeedScalar u_sq = u[0]*u[0] + u[1]*u[1] + u[2]*u[2]; // Velocity square 28bb8a0c61SJames Wright CeedScalar e_potential = -(g[0]*x[0] + g[1]*x[1] + g[2]*x[2]); 293a8779fbSJames Wright for (CeedInt i=0; i<3; i++) { // Jacobian matrices for 3 directions 303a8779fbSJames Wright for (CeedInt j=0; j<3; j++) { // Rows of each Jacobian matrix 31bb8a0c61SJames Wright dF[i][j+1][0] = ((i==j) ? ((gamma-1.)*(u_sq/2. - e_potential)) : 0.) - 32bb8a0c61SJames Wright u[i]*u[j]; 333a8779fbSJames Wright for (CeedInt k=0; k<3; k++) { // Columns of each Jacobian matrix 343a8779fbSJames Wright dF[i][0][k+1] = ((i==k) ? 1. : 0.); 353a8779fbSJames Wright dF[i][j+1][k+1] = ((j==k) ? u[i] : 0.) + 363a8779fbSJames Wright ((i==k) ? u[j] : 0.) - 373a8779fbSJames Wright ((i==j) ? u[k] : 0.) * (gamma-1.); 383a8779fbSJames Wright dF[i][4][k+1] = ((i==k) ? (E*gamma/rho - (gamma-1.)*u_sq/2.) : 0.) - 393a8779fbSJames Wright (gamma-1.)*u[i]*u[k]; 403a8779fbSJames Wright } 413a8779fbSJames Wright dF[i][j+1][4] = ((i==j) ? (gamma-1.) : 0.); 423a8779fbSJames Wright } 433a8779fbSJames Wright dF[i][4][0] = u[i] * ((gamma-1.)*u_sq - E*gamma/rho); 443a8779fbSJames Wright dF[i][4][4] = u[i] * gamma; 453a8779fbSJames Wright } 463a8779fbSJames Wright } 473a8779fbSJames Wright 483a8779fbSJames Wright // ***************************************************************************** 49bb8a0c61SJames Wright // Helper function for computing flux Jacobian of Primitive variables 50bb8a0c61SJames Wright // ***************************************************************************** 51bb8a0c61SJames Wright CEED_QFUNCTION_HELPER void computeFluxJacobian_NSp(CeedScalar dF[3][5][5], 52bb8a0c61SJames Wright const CeedScalar rho, const CeedScalar u[3], const CeedScalar E, 53bb8a0c61SJames Wright const CeedScalar Rd, const CeedScalar cv) { 54bb8a0c61SJames Wright CeedScalar u_sq = u[0]*u[0] + u[1]*u[1] + u[2]*u[2]; // Velocity square 55bb8a0c61SJames Wright // TODO Add in gravity's contribution 56bb8a0c61SJames Wright 57bb8a0c61SJames Wright CeedScalar T = ( E / rho - u_sq / 2. ) / cv; 58bb8a0c61SJames Wright CeedScalar drdT = -rho / T; 59bb8a0c61SJames Wright CeedScalar drdP = 1. / ( Rd * T); 60bb8a0c61SJames Wright CeedScalar etot = E / rho ; 61bb8a0c61SJames Wright CeedScalar e2p = drdP * etot + 1. ; 62bb8a0c61SJames Wright CeedScalar e3p = ( E + rho * Rd * T ); 63bb8a0c61SJames Wright CeedScalar e4p = drdT * etot + rho * cv ; 64bb8a0c61SJames Wright 65bb8a0c61SJames Wright for (CeedInt i=0; i<3; i++) { // Jacobian matrices for 3 directions 66bb8a0c61SJames Wright for (CeedInt j=0; j<3; j++) { // j counts F^{m_j} 67bb8a0c61SJames Wright // [row][col] of A_i 68bb8a0c61SJames Wright dF[i][j+1][0] = drdP * u[i] * u[j] + ((i==j) ? 1. : 0.); // F^{{m_j} wrt p 69bb8a0c61SJames Wright for (CeedInt k=0; k<3; k++) { // k counts the wrt vel_k 702acc7cbcSKenneth E. Jansen dF[i][0][k+1] = ((i==k) ? rho : 0.); // F^c wrt u_k 71bb8a0c61SJames Wright dF[i][j+1][k+1] = (((j==k) ? u[i] : 0.) + // F^m_j wrt u_k 72bb8a0c61SJames Wright ((i==k) ? u[j] : 0.) ) * rho; 73bb8a0c61SJames Wright dF[i][4][k+1] = rho * u[i] * u[k] 74bb8a0c61SJames Wright + ((i==k) ? e3p : 0.) ; // F^e wrt u_k 75bb8a0c61SJames Wright } 76bb8a0c61SJames Wright dF[i][j+1][4] = drdT * u[i] * u[j]; // F^{m_j} wrt T 77bb8a0c61SJames Wright } 78bb8a0c61SJames Wright dF[i][4][0] = u[i] * e2p; // F^e wrt p 79bb8a0c61SJames Wright dF[i][4][4] = u[i] * e4p; // F^e wrt T 80bb8a0c61SJames Wright dF[i][0][0] = u[i] * drdP; // F^c wrt p 81bb8a0c61SJames Wright dF[i][0][4] = u[i] * drdT; // F^c wrt T 82bb8a0c61SJames Wright } 83bb8a0c61SJames Wright } 84bb8a0c61SJames Wright 85bb8a0c61SJames Wright CEED_QFUNCTION_HELPER void PrimitiveToConservative_fwd(const CeedScalar rho, 86bb8a0c61SJames Wright const CeedScalar u[3], const CeedScalar E, const CeedScalar Rd, 87bb8a0c61SJames Wright const CeedScalar cv, const CeedScalar dY[5], CeedScalar dU[5]) { 88bb8a0c61SJames Wright CeedScalar u_sq = u[0]*u[0] + u[1]*u[1] + u[2]*u[2]; 89bb8a0c61SJames Wright CeedScalar T = ( E / rho - u_sq / 2. ) / cv; 90bb8a0c61SJames Wright CeedScalar drdT = -rho / T; 91bb8a0c61SJames Wright CeedScalar drdP = 1. / ( Rd * T); 92bb8a0c61SJames Wright dU[0] = drdP * dY[0] + drdT * dY[4]; 93bb8a0c61SJames Wright CeedScalar de_kinetic = 0; 94493642f1SJames Wright for (CeedInt i=0; i<3; i++) { 95bb8a0c61SJames Wright dU[1+i] = dU[0] * u[i] + rho * dY[1+i]; 96bb8a0c61SJames Wright de_kinetic += u[i] * dY[1+i]; 97bb8a0c61SJames Wright } 98bb8a0c61SJames Wright dU[4] = rho * cv * dY[4] + dU[0] * cv * T // internal energy: rho * e 99bb8a0c61SJames Wright + rho * de_kinetic + .5 * dU[0] * u_sq; // kinetic energy: .5 * rho * |u|^2 100bb8a0c61SJames Wright } 101bb8a0c61SJames Wright 102bb8a0c61SJames Wright // ***************************************************************************** 103bb8a0c61SJames Wright // Helper function for computing Tau elements (stabilization constant) 104bb8a0c61SJames Wright // Model from: 105bb8a0c61SJames Wright // PHASTA 106bb8a0c61SJames Wright // 107bb8a0c61SJames Wright // Tau[i] = itau=0 which is diagonal-Shakib (3 values still but not spatial) 108bb8a0c61SJames Wright // 109bb8a0c61SJames Wright // Where NOT UPDATED YET 110bb8a0c61SJames Wright // ***************************************************************************** 111bb8a0c61SJames Wright CEED_QFUNCTION_HELPER void Tau_diagPrim(CeedScalar Tau_d[3], 112bb8a0c61SJames Wright const CeedScalar dXdx[3][3], const CeedScalar u[3], 113bb8a0c61SJames Wright const CeedScalar cv, const NewtonianIdealGasContext newt_ctx, 114bb8a0c61SJames Wright const CeedScalar mu, const CeedScalar dt, 115bb8a0c61SJames Wright const CeedScalar rho) { 116bb8a0c61SJames Wright // Context 117bb8a0c61SJames Wright const CeedScalar Ctau_t = newt_ctx->Ctau_t; 118bb8a0c61SJames Wright const CeedScalar Ctau_v = newt_ctx->Ctau_v; 119bb8a0c61SJames Wright const CeedScalar Ctau_C = newt_ctx->Ctau_C; 120bb8a0c61SJames Wright const CeedScalar Ctau_M = newt_ctx->Ctau_M; 121bb8a0c61SJames Wright const CeedScalar Ctau_E = newt_ctx->Ctau_E; 122bb8a0c61SJames Wright CeedScalar gijd[6]; 123bb8a0c61SJames Wright CeedScalar tau; 124bb8a0c61SJames Wright CeedScalar dts; 125bb8a0c61SJames Wright CeedScalar fact; 126bb8a0c61SJames Wright 127bb8a0c61SJames Wright //*INDENT-OFF* 128bb8a0c61SJames Wright gijd[0] = dXdx[0][0] * dXdx[0][0] 129bb8a0c61SJames Wright + dXdx[1][0] * dXdx[1][0] 130bb8a0c61SJames Wright + dXdx[2][0] * dXdx[2][0]; 131bb8a0c61SJames Wright 132bb8a0c61SJames Wright gijd[1] = dXdx[0][0] * dXdx[0][1] 133bb8a0c61SJames Wright + dXdx[1][0] * dXdx[1][1] 134bb8a0c61SJames Wright + dXdx[2][0] * dXdx[2][1]; 135bb8a0c61SJames Wright 136bb8a0c61SJames Wright gijd[2] = dXdx[0][1] * dXdx[0][1] 137bb8a0c61SJames Wright + dXdx[1][1] * dXdx[1][1] 138bb8a0c61SJames Wright + dXdx[2][1] * dXdx[2][1]; 139bb8a0c61SJames Wright 140bb8a0c61SJames Wright gijd[3] = dXdx[0][0] * dXdx[0][2] 141bb8a0c61SJames Wright + dXdx[1][0] * dXdx[1][2] 142bb8a0c61SJames Wright + dXdx[2][0] * dXdx[2][2]; 143bb8a0c61SJames Wright 144bb8a0c61SJames Wright gijd[4] = dXdx[0][1] * dXdx[0][2] 145bb8a0c61SJames Wright + dXdx[1][1] * dXdx[1][2] 146bb8a0c61SJames Wright + dXdx[2][1] * dXdx[2][2]; 147bb8a0c61SJames Wright 148bb8a0c61SJames Wright gijd[5] = dXdx[0][2] * dXdx[0][2] 149bb8a0c61SJames Wright + dXdx[1][2] * dXdx[1][2] 150bb8a0c61SJames Wright + dXdx[2][2] * dXdx[2][2]; 151bb8a0c61SJames Wright //*INDENT-ON* 152bb8a0c61SJames Wright 153bb8a0c61SJames Wright dts = Ctau_t / dt ; 154bb8a0c61SJames Wright 155bb8a0c61SJames Wright tau = rho*rho*((4. * dts * dts) 156bb8a0c61SJames Wright + u[0] * ( u[0] * gijd[0] + 2. * ( u[1] * gijd[1] + u[2] * gijd[3])) 157bb8a0c61SJames Wright + u[1] * ( u[1] * gijd[2] + 2. * u[2] * gijd[4]) 158bb8a0c61SJames Wright + u[2] * u[2] * gijd[5]) 159bb8a0c61SJames Wright + Ctau_v* mu * mu * 160bb8a0c61SJames Wright (gijd[0]*gijd[0] + gijd[2]*gijd[2] + gijd[5]*gijd[5] + 161bb8a0c61SJames Wright + 2. * (gijd[1]*gijd[1] + gijd[3]*gijd[3] + gijd[4]*gijd[4])); 162bb8a0c61SJames Wright 163bb8a0c61SJames Wright fact=sqrt(tau); 164bb8a0c61SJames Wright 165bb8a0c61SJames Wright Tau_d[0] = Ctau_C * fact / (rho*(gijd[0] + gijd[2] + gijd[5]))*0.125; 166bb8a0c61SJames Wright 167bb8a0c61SJames Wright Tau_d[1] = Ctau_M / fact; 168bb8a0c61SJames Wright Tau_d[2] = Ctau_E / ( fact * cv ); 169bb8a0c61SJames Wright 170bb8a0c61SJames Wright // consider putting back the way I initially had it Ctau_E * Tau_d[1] /cv 171bb8a0c61SJames Wright // to avoid a division if the compiler is smart enough to see that cv IS 172bb8a0c61SJames Wright // a constant that it could invert once for all elements 173bb8a0c61SJames Wright // but in that case energy tau is scaled by the product of Ctau_E * Ctau_M 174bb8a0c61SJames Wright // OR we could absorb cv into Ctau_E but this puts more burden on user to 175bb8a0c61SJames Wright // know how to change constants with a change of fluid or units. Same for 176bb8a0c61SJames Wright // Ctau_v * mu * mu IF AND ONLY IF we don't add viscosity law =f(T) 177bb8a0c61SJames Wright } 178bb8a0c61SJames Wright 179bb8a0c61SJames Wright // ***************************************************************************** 1803a8779fbSJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 1813a8779fbSJames Wright // ***************************************************************************** 1823a8779fbSJames Wright CEED_QFUNCTION(ICsNewtonianIG)(void *ctx, CeedInt Q, 1833a8779fbSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 1843a8779fbSJames Wright // Inputs 1853a8779fbSJames Wright const CeedScalar (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 1863a8779fbSJames Wright 1873a8779fbSJames Wright // Outputs 1883a8779fbSJames Wright CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 1893a8779fbSJames Wright 190bb8a0c61SJames Wright // Context 191bb8a0c61SJames Wright const SetupContext context = (SetupContext)ctx; 192bb8a0c61SJames Wright const CeedScalar theta0 = context->theta0; 193bb8a0c61SJames Wright const CeedScalar P0 = context->P0; 194bb8a0c61SJames Wright const CeedScalar cv = context->cv; 195bb8a0c61SJames Wright const CeedScalar cp = context->cp; 196bb8a0c61SJames Wright const CeedScalar *g = context->g; 197bb8a0c61SJames Wright const CeedScalar Rd = cp - cv; 198bb8a0c61SJames Wright 1993a8779fbSJames Wright // Quadrature Point Loop 2003a8779fbSJames Wright CeedPragmaSIMD 2013a8779fbSJames Wright for (CeedInt i=0; i<Q; i++) { 2023a8779fbSJames Wright CeedScalar q[5] = {0.}; 2033a8779fbSJames Wright 2043a8779fbSJames Wright // Setup 2053a8779fbSJames Wright // -- Coordinates 206bb8a0c61SJames Wright const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]}; 207bb8a0c61SJames Wright const CeedScalar e_potential = -(g[0]*x[0] + g[1]*x[1] + g[2]*x[2]); 2083a8779fbSJames Wright 2093a8779fbSJames Wright // -- Density 210bb8a0c61SJames Wright const CeedScalar rho = P0 / (Rd*theta0); 2113a8779fbSJames Wright 2123a8779fbSJames Wright // Initial Conditions 2133a8779fbSJames Wright q[0] = rho; 2143a8779fbSJames Wright q[1] = 0.0; 2153a8779fbSJames Wright q[2] = 0.0; 2163a8779fbSJames Wright q[3] = 0.0; 217bb8a0c61SJames Wright q[4] = rho * (cv*theta0 + e_potential); 2183a8779fbSJames Wright 2193a8779fbSJames Wright for (CeedInt j=0; j<5; j++) 2203a8779fbSJames Wright q0[j][i] = q[j]; 2213a8779fbSJames Wright } // End of Quadrature Point Loop 2223a8779fbSJames Wright return 0; 2233a8779fbSJames Wright } 2243a8779fbSJames Wright 2253a8779fbSJames Wright // ***************************************************************************** 2263a8779fbSJames Wright // This QFunction implements the following formulation of Navier-Stokes with 2273a8779fbSJames Wright // explicit time stepping method 2283a8779fbSJames Wright // 2293a8779fbSJames Wright // This is 3D compressible Navier-Stokes in conservation form with state 2303a8779fbSJames Wright // variables of density, momentum density, and total energy density. 2313a8779fbSJames Wright // 2323a8779fbSJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 2333a8779fbSJames Wright // rho - Mass Density 2343a8779fbSJames Wright // Ui - Momentum Density, Ui = rho ui 2353a8779fbSJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 2363a8779fbSJames Wright // 2373a8779fbSJames Wright // Navier-Stokes Equations: 2383a8779fbSJames Wright // drho/dt + div( U ) = 0 2393a8779fbSJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 2403a8779fbSJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 2413a8779fbSJames Wright // 2423a8779fbSJames Wright // Viscous Stress: 2433a8779fbSJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 2443a8779fbSJames Wright // 2453a8779fbSJames Wright // Thermal Stress: 2463a8779fbSJames Wright // Fe = u Fu + k grad( T ) 247bb8a0c61SJames Wright // Equation of State 2483a8779fbSJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 2493a8779fbSJames Wright // 2503a8779fbSJames Wright // Stabilization: 2513a8779fbSJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 2523a8779fbSJames Wright // f1 = rho sqrt(ui uj gij) 2533a8779fbSJames Wright // gij = dXi/dX * dXi/dX 2543a8779fbSJames Wright // TauC = Cc f1 / (8 gii) 2553a8779fbSJames Wright // TauM = min( 1 , 1 / f1 ) 2563a8779fbSJames Wright // TauE = TauM / (Ce cv) 2573a8779fbSJames Wright // 2583a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 2593a8779fbSJames Wright // 2603a8779fbSJames Wright // Constants: 2613a8779fbSJames Wright // lambda = - 2 / 3, From Stokes hypothesis 2623a8779fbSJames Wright // mu , Dynamic viscosity 2633a8779fbSJames Wright // k , Thermal conductivity 2643a8779fbSJames Wright // cv , Specific heat, constant volume 2653a8779fbSJames Wright // cp , Specific heat, constant pressure 2663a8779fbSJames Wright // g , Gravity 2673a8779fbSJames Wright // gamma = cp / cv, Specific heat ratio 2683a8779fbSJames Wright // 2693a8779fbSJames Wright // We require the product of the inverse of the Jacobian (dXdx_j,k) and 2703a8779fbSJames Wright // its transpose (dXdx_k,j) to properly compute integrals of the form: 2713a8779fbSJames Wright // int( gradv gradu ) 2723a8779fbSJames Wright // 2733a8779fbSJames Wright // ***************************************************************************** 274c1a52365SJed Brown CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, 2753a8779fbSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 2763a8779fbSJames Wright // *INDENT-OFF* 2773a8779fbSJames Wright // Inputs 2783a8779fbSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 279752f40e3SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 2803a8779fbSJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 2813a8779fbSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 2823a8779fbSJames Wright // Outputs 2833a8779fbSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 284752f40e3SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 2853a8779fbSJames Wright // *INDENT-ON* 2863a8779fbSJames Wright 2873a8779fbSJames Wright // Context 2883a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 2893a8779fbSJames Wright const CeedScalar mu = context->mu; 2903a8779fbSJames Wright const CeedScalar cv = context->cv; 2913a8779fbSJames Wright const CeedScalar cp = context->cp; 292bb8a0c61SJames Wright const CeedScalar *g = context->g; 293bb8a0c61SJames Wright const CeedScalar dt = context->dt; 2943a8779fbSJames Wright const CeedScalar gamma = cp / cv; 295bb8a0c61SJames Wright const CeedScalar Rd = cp - cv; 2963a8779fbSJames Wright 2973a8779fbSJames Wright CeedPragmaSIMD 2983a8779fbSJames Wright // Quadrature Point Loop 2993a8779fbSJames Wright for (CeedInt i=0; i<Q; i++) { 300c1a52365SJed Brown CeedScalar U[5]; 301c1a52365SJed Brown for (int j=0; j<5; j++) U[j] = q[j][i]; 302c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 303c1a52365SJed Brown State s = StateFromU(context, U, x_i); 304c1a52365SJed Brown 3053a8779fbSJames Wright // -- Interp-to-Interp q_data 3063a8779fbSJames Wright const CeedScalar wdetJ = q_data[0][i]; 3073a8779fbSJames Wright // -- Interp-to-Grad q_data 3083a8779fbSJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 3093a8779fbSJames Wright // *INDENT-OFF* 3103a8779fbSJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], 3113a8779fbSJames Wright q_data[2][i], 3123a8779fbSJames Wright q_data[3][i]}, 3133a8779fbSJames Wright {q_data[4][i], 3143a8779fbSJames Wright q_data[5][i], 3153a8779fbSJames Wright q_data[6][i]}, 3163a8779fbSJames Wright {q_data[7][i], 3173a8779fbSJames Wright q_data[8][i], 3183a8779fbSJames Wright q_data[9][i]} 3193a8779fbSJames Wright }; 3203a8779fbSJames Wright // *INDENT-ON* 3213a8779fbSJames Wright 322c1a52365SJed Brown State grad_s[3]; 323eef2387dSJed Brown for (CeedInt j=0; j<3; j++) { 3242f7ce6c1SJed Brown CeedScalar dx_i[3] = {0}, dU[5]; 3252556a851SJed Brown for (CeedInt k=0; k<5; k++) 3262556a851SJed Brown dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 3272556a851SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 3282556a851SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 329c1a52365SJed Brown dx_i[j] = 1.; 3302f7ce6c1SJed Brown grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 331c1a52365SJed Brown } 332c1a52365SJed Brown 333c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 334c1a52365SJed Brown KMStrainRate(grad_s, strain_rate); 335c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 336c1a52365SJed Brown KMUnpack(kmstress, stress); 337c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 338c1a52365SJed Brown 339c1a52365SJed Brown StateConservative F_inviscid[3]; 340c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 341c1a52365SJed Brown 342c1a52365SJed Brown // Total flux 343c1a52365SJed Brown CeedScalar Flux[5][3]; 344eef2387dSJed Brown for (CeedInt j=0; j<3; j++) { 345c1a52365SJed Brown Flux[0][j] = F_inviscid[j].density; 346eef2387dSJed Brown for (CeedInt k=0; k<3; k++) 347c1a52365SJed Brown Flux[k+1][j] = F_inviscid[j].momentum[k] - stress[k][j]; 348c1a52365SJed Brown Flux[4][j] = F_inviscid[j].E_total + Fe[j]; 349c1a52365SJed Brown } 350c1a52365SJed Brown 351eef2387dSJed Brown for (CeedInt j=0; j<3; j++) { 352eef2387dSJed Brown for (CeedInt k=0; k<5; k++) { 353752f40e3SJed Brown Grad_v[j][k][i] = wdetJ * (dXdx[j][0] * Flux[k][0] + 354c1a52365SJed Brown dXdx[j][1] * Flux[k][1] + 355c1a52365SJed Brown dXdx[j][2] * Flux[k][2]); 356c1a52365SJed Brown } 357c1a52365SJed Brown } 358c1a52365SJed Brown 359c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 360c1a52365SJed Brown for (int j=0; j<5; j++) 361c1a52365SJed Brown v[j][i] = wdetJ * body_force[j]; 3623a8779fbSJames Wright 3633a8779fbSJames Wright // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction 364c1a52365SJed Brown CeedScalar jacob_F_conv[3][5][5] = {0}; 365c1a52365SJed Brown computeFluxJacobian_NS(jacob_F_conv, s.U.density, s.Y.velocity, s.U.E_total, 366c1a52365SJed Brown gamma, g, x_i); 367c1a52365SJed Brown CeedScalar grad_U[5][3]; 368493642f1SJames Wright for (CeedInt j=0; j<3; j++) { 369c1a52365SJed Brown grad_U[0][j] = grad_s[j].U.density; 370eef2387dSJed Brown for (CeedInt k=0; k<3; k++) grad_U[k+1][j] = grad_s[j].U.momentum[k]; 371c1a52365SJed Brown grad_U[4][j] = grad_s[j].U.E_total; 3723a8779fbSJames Wright } 3733a8779fbSJames Wright 3743a8779fbSJames Wright // strong_conv = dF/dq * dq/dx (Strong convection) 3753a8779fbSJames Wright CeedScalar strong_conv[5] = {0}; 376493642f1SJames Wright for (CeedInt j=0; j<3; j++) 377493642f1SJames Wright for (CeedInt k=0; k<5; k++) 378493642f1SJames Wright for (CeedInt l=0; l<5; l++) 379c1a52365SJed Brown strong_conv[k] += jacob_F_conv[j][k][l] * grad_U[l][j]; 3803a8779fbSJames Wright 381bb8a0c61SJames Wright // -- Stabilization method: none, SU, or SUPG 382bb8a0c61SJames Wright CeedScalar stab[5][3] = {{0.}}; 383bb8a0c61SJames Wright CeedScalar tau_strong_conv[5] = {0.}, tau_strong_conv_conservative[5] = {0}; 384bb8a0c61SJames Wright CeedScalar Tau_d[3] = {0.}; 3853a8779fbSJames Wright switch (context->stabilization) { 3863a8779fbSJames Wright case STAB_NONE: // Galerkin 3873a8779fbSJames Wright break; 3883a8779fbSJames Wright case STAB_SU: // SU 389c1a52365SJed Brown Tau_diagPrim(Tau_d, dXdx, s.Y.velocity, cv, context, mu, dt, s.U.density); 390bb8a0c61SJames Wright tau_strong_conv[0] = Tau_d[0] * strong_conv[0]; 391bb8a0c61SJames Wright tau_strong_conv[1] = Tau_d[1] * strong_conv[1]; 392bb8a0c61SJames Wright tau_strong_conv[2] = Tau_d[1] * strong_conv[2]; 393bb8a0c61SJames Wright tau_strong_conv[3] = Tau_d[1] * strong_conv[3]; 394bb8a0c61SJames Wright tau_strong_conv[4] = Tau_d[2] * strong_conv[4]; 395c1a52365SJed Brown PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 396c1a52365SJed Brown tau_strong_conv, 397bb8a0c61SJames Wright tau_strong_conv_conservative); 398493642f1SJames Wright for (CeedInt j=0; j<3; j++) 399493642f1SJames Wright for (CeedInt k=0; k<5; k++) 400493642f1SJames Wright for (CeedInt l=0; l<5; l++) 401bb8a0c61SJames Wright stab[k][j] += jacob_F_conv[j][k][l] * tau_strong_conv_conservative[l]; 4023a8779fbSJames Wright 403493642f1SJames Wright for (CeedInt j=0; j<5; j++) 404493642f1SJames Wright for (CeedInt k=0; k<3; k++) 405752f40e3SJed Brown Grad_v[k][j][i] -= wdetJ*(stab[j][0] * dXdx[k][0] + 4063a8779fbSJames Wright stab[j][1] * dXdx[k][1] + 4073a8779fbSJames Wright stab[j][2] * dXdx[k][2]); 4083a8779fbSJames Wright break; 4093a8779fbSJames Wright case STAB_SUPG: // SUPG is not implemented for explicit scheme 4103a8779fbSJames Wright break; 4113a8779fbSJames Wright } 4123a8779fbSJames Wright 4133a8779fbSJames Wright } // End Quadrature Point Loop 4143a8779fbSJames Wright 4153a8779fbSJames Wright // Return 4163a8779fbSJames Wright return 0; 4173a8779fbSJames Wright } 4183a8779fbSJames Wright 4193a8779fbSJames Wright // ***************************************************************************** 4203a8779fbSJames Wright // This QFunction implements the Navier-Stokes equations (mentioned above) with 4213a8779fbSJames Wright // implicit time stepping method 4223a8779fbSJames Wright // 4233a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 4243a8779fbSJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 4253a8779fbSJames Wright // (diffussive terms will be added later) 4263a8779fbSJames Wright // 4273a8779fbSJames Wright // ***************************************************************************** 4283a8779fbSJames Wright CEED_QFUNCTION(IFunction_Newtonian)(void *ctx, CeedInt Q, 4293a8779fbSJames Wright const CeedScalar *const *in, 4303a8779fbSJames Wright CeedScalar *const *out) { 4313a8779fbSJames Wright // *INDENT-OFF* 4323a8779fbSJames Wright // Inputs 4333a8779fbSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 434752f40e3SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 4353a8779fbSJames Wright (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 4363a8779fbSJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 4373a8779fbSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 4383a8779fbSJames Wright // Outputs 4393a8779fbSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 440752f40e3SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1], 441752f40e3SJed Brown (*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 4423a8779fbSJames Wright // *INDENT-ON* 4433a8779fbSJames Wright // Context 4443a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 4453a8779fbSJames Wright const CeedScalar mu = context->mu; 4463a8779fbSJames Wright const CeedScalar cv = context->cv; 4473a8779fbSJames Wright const CeedScalar cp = context->cp; 448bb8a0c61SJames Wright const CeedScalar *g = context->g; 449bb8a0c61SJames Wright const CeedScalar dt = context->dt; 4503a8779fbSJames Wright const CeedScalar gamma = cp / cv; 451bb8a0c61SJames Wright const CeedScalar Rd = cp-cv; 4523a8779fbSJames Wright 4533a8779fbSJames Wright CeedPragmaSIMD 4543a8779fbSJames Wright // Quadrature Point Loop 4553a8779fbSJames Wright for (CeedInt i=0; i<Q; i++) { 456c1a52365SJed Brown CeedScalar U[5]; 457eef2387dSJed Brown for (CeedInt j=0; j<5; j++) U[j] = q[j][i]; 458c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 459c1a52365SJed Brown State s = StateFromU(context, U, x_i); 460c1a52365SJed Brown 4613a8779fbSJames Wright // -- Interp-to-Interp q_data 4623a8779fbSJames Wright const CeedScalar wdetJ = q_data[0][i]; 4633a8779fbSJames Wright // -- Interp-to-Grad q_data 4643a8779fbSJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 4653a8779fbSJames Wright // *INDENT-OFF* 4663a8779fbSJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], 4673a8779fbSJames Wright q_data[2][i], 4683a8779fbSJames Wright q_data[3][i]}, 4693a8779fbSJames Wright {q_data[4][i], 4703a8779fbSJames Wright q_data[5][i], 4713a8779fbSJames Wright q_data[6][i]}, 4723a8779fbSJames Wright {q_data[7][i], 4733a8779fbSJames Wright q_data[8][i], 4743a8779fbSJames Wright q_data[9][i]} 4753a8779fbSJames Wright }; 4763a8779fbSJames Wright // *INDENT-ON* 477c1a52365SJed Brown State grad_s[3]; 478493642f1SJames Wright for (CeedInt j=0; j<3; j++) { 4792f7ce6c1SJed Brown CeedScalar dx_i[3] = {0}, dU[5]; 4802556a851SJed Brown for (CeedInt k=0; k<5; k++) 4812556a851SJed Brown dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 4822556a851SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 4832556a851SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 484c1a52365SJed Brown dx_i[j] = 1.; 4852f7ce6c1SJed Brown grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 4863a8779fbSJames Wright } 487c1a52365SJed Brown 488c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 489c1a52365SJed Brown KMStrainRate(grad_s, strain_rate); 490c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 491c1a52365SJed Brown KMUnpack(kmstress, stress); 492c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 493c1a52365SJed Brown 494c1a52365SJed Brown StateConservative F_inviscid[3]; 495c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 496c1a52365SJed Brown 497c1a52365SJed Brown 498c1a52365SJed Brown // Total flux 499c1a52365SJed Brown CeedScalar Flux[5][3]; 500eef2387dSJed Brown for (CeedInt j=0; j<3; j++) { 501c1a52365SJed Brown Flux[0][j] = F_inviscid[j].density; 502493642f1SJames Wright for (CeedInt k=0; k<3; k++) 503c1a52365SJed Brown Flux[k+1][j] = F_inviscid[j].momentum[k] - stress[k][j]; 504c1a52365SJed Brown Flux[4][j] = F_inviscid[j].E_total + Fe[j]; 505c1a52365SJed Brown } 506c1a52365SJed Brown 507eef2387dSJed Brown for (CeedInt j=0; j<3; j++) { 508eef2387dSJed Brown for (CeedInt k=0; k<5; k++) { 509752f40e3SJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + 510c1a52365SJed Brown dXdx[j][1] * Flux[k][1] + 511c1a52365SJed Brown dXdx[j][2] * Flux[k][2]); 512c1a52365SJed Brown } 513c1a52365SJed Brown } 514c1a52365SJed Brown 515c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 516eef2387dSJed Brown for (CeedInt j=0; j<5; j++) 517c1a52365SJed Brown v[j][i] = wdetJ * (q_dot[j][i] - body_force[j]); 5183a8779fbSJames Wright 5193a8779fbSJames Wright // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction 520c1a52365SJed Brown CeedScalar jacob_F_conv[3][5][5] = {0}; 521c1a52365SJed Brown computeFluxJacobian_NS(jacob_F_conv, s.U.density, s.Y.velocity, s.U.E_total, 522c1a52365SJed Brown gamma, g, x_i); 523c1a52365SJed Brown CeedScalar grad_U[5][3]; 524493642f1SJames Wright for (CeedInt j=0; j<3; j++) { 525c1a52365SJed Brown grad_U[0][j] = grad_s[j].U.density; 526eef2387dSJed Brown for (CeedInt k=0; k<3; k++) grad_U[k+1][j] = grad_s[j].U.momentum[k]; 527c1a52365SJed Brown grad_U[4][j] = grad_s[j].U.E_total; 5283a8779fbSJames Wright } 529c1a52365SJed Brown 5303a8779fbSJames Wright // strong_conv = dF/dq * dq/dx (Strong convection) 5313a8779fbSJames Wright CeedScalar strong_conv[5] = {0}; 532493642f1SJames Wright for (CeedInt j=0; j<3; j++) 533493642f1SJames Wright for (CeedInt k=0; k<5; k++) 534493642f1SJames Wright for (CeedInt l=0; l<5; l++) 535c1a52365SJed Brown strong_conv[k] += jacob_F_conv[j][k][l] * grad_U[l][j]; 5363a8779fbSJames Wright 5373a8779fbSJames Wright // Strong residual 5383a8779fbSJames Wright CeedScalar strong_res[5]; 539493642f1SJames Wright for (CeedInt j=0; j<5; j++) 5403a8779fbSJames Wright strong_res[j] = q_dot[j][i] + strong_conv[j] - body_force[j]; 5413a8779fbSJames Wright 5423a8779fbSJames Wright // -- Stabilization method: none, SU, or SUPG 543bb8a0c61SJames Wright CeedScalar stab[5][3] = {{0.}}; 544bb8a0c61SJames Wright CeedScalar tau_strong_res[5] = {0.}, tau_strong_res_conservative[5] = {0}; 545bb8a0c61SJames Wright CeedScalar tau_strong_conv[5] = {0.}, tau_strong_conv_conservative[5] = {0}; 546bb8a0c61SJames Wright CeedScalar Tau_d[3] = {0.}; 5473a8779fbSJames Wright switch (context->stabilization) { 5483a8779fbSJames Wright case STAB_NONE: // Galerkin 5493a8779fbSJames Wright break; 5503a8779fbSJames Wright case STAB_SU: // SU 551c1a52365SJed Brown Tau_diagPrim(Tau_d, dXdx, s.Y.velocity, cv, context, mu, dt, s.U.density); 552bb8a0c61SJames Wright tau_strong_conv[0] = Tau_d[0] * strong_conv[0]; 553bb8a0c61SJames Wright tau_strong_conv[1] = Tau_d[1] * strong_conv[1]; 554bb8a0c61SJames Wright tau_strong_conv[2] = Tau_d[1] * strong_conv[2]; 555bb8a0c61SJames Wright tau_strong_conv[3] = Tau_d[1] * strong_conv[3]; 556bb8a0c61SJames Wright tau_strong_conv[4] = Tau_d[2] * strong_conv[4]; 557c1a52365SJed Brown PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 558c1a52365SJed Brown tau_strong_conv, tau_strong_conv_conservative); 559493642f1SJames Wright for (CeedInt j=0; j<3; j++) 560493642f1SJames Wright for (CeedInt k=0; k<5; k++) 561493642f1SJames Wright for (CeedInt l=0; l<5; l++) 562bb8a0c61SJames Wright stab[k][j] += jacob_F_conv[j][k][l] * tau_strong_conv_conservative[l]; 5633a8779fbSJames Wright 564493642f1SJames Wright for (CeedInt j=0; j<5; j++) 565493642f1SJames Wright for (CeedInt k=0; k<3; k++) 566752f40e3SJed Brown Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 5673a8779fbSJames Wright stab[j][1] * dXdx[k][1] + 5683a8779fbSJames Wright stab[j][2] * dXdx[k][2]); 569eef2387dSJed Brown 5703a8779fbSJames Wright break; 5713a8779fbSJames Wright case STAB_SUPG: // SUPG 572c1a52365SJed Brown Tau_diagPrim(Tau_d, dXdx, s.Y.velocity, cv, context, mu, dt, s.U.density); 573bb8a0c61SJames Wright tau_strong_res[0] = Tau_d[0] * strong_res[0]; 574bb8a0c61SJames Wright tau_strong_res[1] = Tau_d[1] * strong_res[1]; 575bb8a0c61SJames Wright tau_strong_res[2] = Tau_d[1] * strong_res[2]; 576bb8a0c61SJames Wright tau_strong_res[3] = Tau_d[1] * strong_res[3]; 577bb8a0c61SJames Wright tau_strong_res[4] = Tau_d[2] * strong_res[4]; 578bb8a0c61SJames Wright // Alternate route (useful later with primitive variable code) 579bb8a0c61SJames Wright // this function was verified against PHASTA for as IC that was as close as possible 580bb8a0c61SJames Wright // computeFluxJacobian_NSp(jacob_F_conv_p, rho, u, E, Rd, cv); 581bb8a0c61SJames Wright // it has also been verified to compute a correct through the following 582bb8a0c61SJames Wright // stab[k][j] += jacob_F_conv_p[j][k][l] * tau_strong_res[l] // flux Jacobian wrt primitive 583bb8a0c61SJames Wright // applied in the triple loop below 584bb8a0c61SJames Wright // However, it is more flops than using the existing Jacobian wrt q after q_{,Y} viz 585c1a52365SJed Brown PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 586c1a52365SJed Brown tau_strong_res, tau_strong_res_conservative); 587493642f1SJames Wright for (CeedInt j=0; j<3; j++) 588493642f1SJames Wright for (CeedInt k=0; k<5; k++) 589493642f1SJames Wright for (CeedInt l=0; l<5; l++) 590bb8a0c61SJames Wright stab[k][j] += jacob_F_conv[j][k][l] * tau_strong_res_conservative[l]; 5913a8779fbSJames Wright 592493642f1SJames Wright for (CeedInt j=0; j<5; j++) 593493642f1SJames Wright for (CeedInt k=0; k<3; k++) 594752f40e3SJed Brown Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 5953a8779fbSJames Wright stab[j][1] * dXdx[k][1] + 5963a8779fbSJames Wright stab[j][2] * dXdx[k][2]); 5973a8779fbSJames Wright break; 5983a8779fbSJames Wright } 599eef2387dSJed Brown for (CeedInt j=0; j<5; j++) jac_data[j][i] = U[j]; 600eef2387dSJed Brown for (CeedInt j=0; j<6; j++) jac_data[5+j][i] = kmstress[j]; 601eef2387dSJed Brown for (CeedInt j=0; j<3; j++) jac_data[5+6+j][i] = Tau_d[j]; 6023a8779fbSJames Wright 6033a8779fbSJames Wright } // End Quadrature Point Loop 6043a8779fbSJames Wright 6053a8779fbSJames Wright // Return 6063a8779fbSJames Wright return 0; 6073a8779fbSJames Wright } 608f0b65372SJed Brown 609f0b65372SJed Brown CEED_QFUNCTION(IJacobian_Newtonian)(void *ctx, CeedInt Q, 610f0b65372SJed Brown const CeedScalar *const *in, 611f0b65372SJed Brown CeedScalar *const *out) { 612f0b65372SJed Brown // *INDENT-OFF* 613f0b65372SJed Brown // Inputs 614f0b65372SJed Brown const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 615f0b65372SJed Brown (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 616f0b65372SJed Brown (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 617f0b65372SJed Brown (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 618f0b65372SJed Brown (*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 619f0b65372SJed Brown // Outputs 620f0b65372SJed Brown CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 621f0b65372SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 622f0b65372SJed Brown // *INDENT-ON* 623f0b65372SJed Brown // Context 624f0b65372SJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 625f0b65372SJed Brown const CeedScalar *g = context->g; 626f0b65372SJed Brown const CeedScalar cp = context->cp; 627f0b65372SJed Brown const CeedScalar cv = context->cv; 628f0b65372SJed Brown const CeedScalar Rd = cp - cv; 629f0b65372SJed Brown const CeedScalar gamma = cp / cv; 630f0b65372SJed Brown 631f0b65372SJed Brown CeedPragmaSIMD 632f0b65372SJed Brown // Quadrature Point Loop 633f0b65372SJed Brown for (CeedInt i=0; i<Q; i++) { 634f0b65372SJed Brown // -- Interp-to-Interp q_data 635f0b65372SJed Brown const CeedScalar wdetJ = q_data[0][i]; 636f0b65372SJed Brown // -- Interp-to-Grad q_data 637f0b65372SJed Brown // ---- Inverse of change of coordinate matrix: X_i,j 638f0b65372SJed Brown // *INDENT-OFF* 639f0b65372SJed Brown const CeedScalar dXdx[3][3] = {{q_data[1][i], 640f0b65372SJed Brown q_data[2][i], 641f0b65372SJed Brown q_data[3][i]}, 642f0b65372SJed Brown {q_data[4][i], 643f0b65372SJed Brown q_data[5][i], 644f0b65372SJed Brown q_data[6][i]}, 645f0b65372SJed Brown {q_data[7][i], 646f0b65372SJed Brown q_data[8][i], 647f0b65372SJed Brown q_data[9][i]} 648f0b65372SJed Brown }; 649f0b65372SJed Brown // *INDENT-ON* 650f0b65372SJed Brown 651f0b65372SJed Brown CeedScalar U[5], kmstress[6], Tau_d[3] __attribute((unused)); 652f0b65372SJed Brown for (int j=0; j<5; j++) U[j] = jac_data[j][i]; 653f0b65372SJed Brown for (int j=0; j<6; j++) kmstress[j] = jac_data[5+j][i]; 654f0b65372SJed Brown for (int j=0; j<3; j++) Tau_d[j] = jac_data[5+6+j][i]; 655f0b65372SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 656f0b65372SJed Brown State s = StateFromU(context, U, x_i); 657f0b65372SJed Brown 658f0b65372SJed Brown CeedScalar dU[5], dx0[3] = {0}; 659f0b65372SJed Brown for (int j=0; j<5; j++) dU[j] = dq[j][i]; 660f0b65372SJed Brown State ds = StateFromU_fwd(context, s, dU, x_i, dx0); 661f0b65372SJed Brown 662f0b65372SJed Brown State grad_ds[3]; 663f0b65372SJed Brown for (int j=0; j<3; j++) { 664f0b65372SJed Brown CeedScalar dUj[5]; 665f0b65372SJed Brown for (int k=0; k<5; k++) dUj[k] = Grad_dq[0][k][i] * dXdx[0][j] 666f0b65372SJed Brown + Grad_dq[1][k][i] * dXdx[1][j] 667f0b65372SJed Brown + Grad_dq[2][k][i] * dXdx[2][j]; 668f0b65372SJed Brown grad_ds[j] = StateFromU_fwd(context, s, dUj, x_i, dx0); 669f0b65372SJed Brown } 670f0b65372SJed Brown 671f0b65372SJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 672f0b65372SJed Brown KMStrainRate(grad_ds, dstrain_rate); 673f0b65372SJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 674f0b65372SJed Brown KMUnpack(dkmstress, dstress); 675f0b65372SJed Brown KMUnpack(kmstress, stress); 676f0b65372SJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 677f0b65372SJed Brown 678f0b65372SJed Brown StateConservative dF_inviscid[3]; 679f0b65372SJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 680f0b65372SJed Brown 681f0b65372SJed Brown // Total flux 682f0b65372SJed Brown CeedScalar dFlux[5][3]; 683f0b65372SJed Brown for (int j=0; j<3; j++) { 684f0b65372SJed Brown dFlux[0][j] = dF_inviscid[j].density; 685f0b65372SJed Brown for (int k=0; k<3; k++) 686f0b65372SJed Brown dFlux[k+1][j] = dF_inviscid[j].momentum[k] - dstress[k][j]; 687f0b65372SJed Brown dFlux[4][j] = dF_inviscid[j].E_total + dFe[j]; 688f0b65372SJed Brown } 689f0b65372SJed Brown 690f0b65372SJed Brown for (int j=0; j<3; j++) { 691f0b65372SJed Brown for (int k=0; k<5; k++) { 692f0b65372SJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + 693f0b65372SJed Brown dXdx[j][1] * dFlux[k][1] + 694f0b65372SJed Brown dXdx[j][2] * dFlux[k][2]); 695f0b65372SJed Brown } 696f0b65372SJed Brown } 697f0b65372SJed Brown 698f0b65372SJed Brown const CeedScalar dbody_force[5] = {0, ds.U.density *g[0], ds.U.density *g[1], ds.U.density *g[2], 0}; 699f0b65372SJed Brown for (int j=0; j<5; j++) 700f0b65372SJed Brown v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 701f0b65372SJed Brown 702f0b65372SJed Brown if (1) { 703f0b65372SJed Brown CeedScalar jacob_F_conv[3][5][5] = {0}; 704f0b65372SJed Brown computeFluxJacobian_NS(jacob_F_conv, s.U.density, s.Y.velocity, s.U.E_total, 705f0b65372SJed Brown gamma, g, x_i); 706f0b65372SJed Brown CeedScalar grad_dU[5][3]; 707f0b65372SJed Brown for (int j=0; j<3; j++) { 708f0b65372SJed Brown grad_dU[0][j] = grad_ds[j].U.density; 709f0b65372SJed Brown for (int k=0; k<3; k++) grad_dU[k+1][j] = grad_ds[j].U.momentum[k]; 710f0b65372SJed Brown grad_dU[4][j] = grad_ds[j].U.E_total; 711f0b65372SJed Brown } 712f0b65372SJed Brown CeedScalar dstrong_conv[5] = {0}; 713f0b65372SJed Brown for (int j=0; j<3; j++) 714f0b65372SJed Brown for (int k=0; k<5; k++) 715f0b65372SJed Brown for (int l=0; l<5; l++) 716f0b65372SJed Brown dstrong_conv[k] += jacob_F_conv[j][k][l] * grad_dU[l][j]; 717f0b65372SJed Brown CeedScalar dstrong_res[5]; 718f0b65372SJed Brown for (int j=0; j<5; j++) 719f0b65372SJed Brown dstrong_res[j] = context->ijacobian_time_shift * dU[j] + dstrong_conv[j] - 720f0b65372SJed Brown dbody_force[j]; 721f0b65372SJed Brown CeedScalar dtau_strong_res[5] = {0.}, dtau_strong_res_conservative[5] = {0}; 722f0b65372SJed Brown dtau_strong_res[0] = Tau_d[0] * dstrong_res[0]; 723f0b65372SJed Brown dtau_strong_res[1] = Tau_d[1] * dstrong_res[1]; 724f0b65372SJed Brown dtau_strong_res[2] = Tau_d[1] * dstrong_res[2]; 725f0b65372SJed Brown dtau_strong_res[3] = Tau_d[1] * dstrong_res[3]; 726f0b65372SJed Brown dtau_strong_res[4] = Tau_d[2] * dstrong_res[4]; 727f0b65372SJed Brown PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 728f0b65372SJed Brown dtau_strong_res, dtau_strong_res_conservative); 729f0b65372SJed Brown CeedScalar dstab[5][3] = {0}; 730f0b65372SJed Brown for (int j=0; j<3; j++) 731f0b65372SJed Brown for (int k=0; k<5; k++) 732f0b65372SJed Brown for (int l=0; l<5; l++) 733f0b65372SJed Brown dstab[k][j] += jacob_F_conv[j][k][l] * dtau_strong_res_conservative[l]; 734f0b65372SJed Brown for (int j=0; j<5; j++) 735f0b65372SJed Brown for (int k=0; k<3; k++) 736f0b65372SJed Brown Grad_v[k][j][i] += wdetJ*(dstab[j][0] * dXdx[k][0] + 737f0b65372SJed Brown dstab[j][1] * dXdx[k][1] + 738f0b65372SJed Brown dstab[j][2] * dXdx[k][2]); 739f0b65372SJed Brown 740f0b65372SJed Brown } 741f0b65372SJed Brown } // End Quadrature Point Loop 742f0b65372SJed Brown return 0; 743f0b65372SJed Brown } 7448085925cSJames Wright 7458085925cSJames Wright // Compute boundary integral (ie. for strongly set inflows) 7468085925cSJames Wright CEED_QFUNCTION(BoundaryIntegral)(void *ctx, CeedInt Q, 7478085925cSJames Wright const CeedScalar *const *in, 7488085925cSJames Wright CeedScalar *const *out) { 7498085925cSJames Wright 7508085925cSJames Wright //*INDENT-OFF* 7518085925cSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 752d3b25f3aSJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 753d3b25f3aSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 754d3b25f3aSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 7558085925cSJames Wright 75668ae065aSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[0], 75768ae065aSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[1]; 7588085925cSJames Wright 7598085925cSJames Wright //*INDENT-ON* 7608085925cSJames Wright 761d3b25f3aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext) ctx; 762d3b25f3aSJames Wright const bool is_implicit = context->is_implicit; 7638085925cSJames Wright 7648085925cSJames Wright CeedPragmaSIMD 7658085925cSJames Wright for(CeedInt i=0; i<Q; i++) { 766d3b25f3aSJames Wright const CeedScalar U[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 767d3b25f3aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 768d3b25f3aSJames Wright const State s = StateFromU(context, U, x_i); 7698085925cSJames Wright 7708085925cSJames Wright const CeedScalar wdetJb = (is_implicit ? -1. : 1.) * q_data_sur[0][i]; 7718085925cSJames Wright // ---- Normal vect 7728085925cSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 7738085925cSJames Wright q_data_sur[2][i], 7748085925cSJames Wright q_data_sur[3][i] 7758085925cSJames Wright }; 7768085925cSJames Wright 777d3b25f3aSJames Wright const CeedScalar dXdx[2][3] = { 778d3b25f3aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 779d3b25f3aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 780d3b25f3aSJames Wright }; 7818085925cSJames Wright 782d3b25f3aSJames Wright State grad_s[3]; 783d3b25f3aSJames Wright for (CeedInt j=0; j<3; j++) { 784d3b25f3aSJames Wright CeedScalar dx_i[3] = {0}, dU[5]; 785d3b25f3aSJames Wright for (CeedInt k=0; k<5; k++) 786d3b25f3aSJames Wright dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 787d3b25f3aSJames Wright Grad_q[1][k][i] * dXdx[1][j]; 788d3b25f3aSJames Wright dx_i[j] = 1.; 789d3b25f3aSJames Wright grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 790d3b25f3aSJames Wright } 7918085925cSJames Wright 792d3b25f3aSJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 793d3b25f3aSJames Wright KMStrainRate(grad_s, strain_rate); 794d3b25f3aSJames Wright NewtonianStress(context, strain_rate, kmstress); 795d3b25f3aSJames Wright KMUnpack(kmstress, stress); 796d3b25f3aSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 797d3b25f3aSJames Wright 798d3b25f3aSJames Wright StateConservative F_inviscid[3]; 799d3b25f3aSJames Wright FluxInviscid(context, s, F_inviscid); 800d3b25f3aSJames Wright 801d3b25f3aSJames Wright CeedScalar Flux[5] = {0.}; 802d3b25f3aSJames Wright for (int j=0; j<3; j++) { 803d3b25f3aSJames Wright Flux[0] += F_inviscid[j].density * norm[j]; 804d3b25f3aSJames Wright for (int k=0; k<3; k++) 805d3b25f3aSJames Wright Flux[k+1] += (F_inviscid[j].momentum[k] - stress[k][j]) * norm[j]; 806d3b25f3aSJames Wright Flux[4] += (F_inviscid[j].E_total + Fe[j])*norm[j]; 807d3b25f3aSJames Wright } 808d3b25f3aSJames Wright 8098085925cSJames Wright // -- Density 810d3b25f3aSJames Wright v[0][i] = -wdetJb * Flux[0]; 8118085925cSJames Wright 8128085925cSJames Wright // -- Momentum 8138085925cSJames Wright for (CeedInt j=0; j<3; j++) 814d3b25f3aSJames Wright v[j+1][i] = -wdetJb * Flux[j+1]; 8158085925cSJames Wright 8168085925cSJames Wright // -- Total Energy Density 817d3b25f3aSJames Wright v[4][i] = -wdetJb * Flux[4]; 81868ae065aSJames Wright 81968ae065aSJames Wright jac_data_sur[0][i] = s.U.density; 82068ae065aSJames Wright jac_data_sur[1][i] = s.Y.velocity[0]; 82168ae065aSJames Wright jac_data_sur[2][i] = s.Y.velocity[1]; 82268ae065aSJames Wright jac_data_sur[3][i] = s.Y.velocity[2]; 82368ae065aSJames Wright jac_data_sur[4][i] = s.U.E_total; 82468ae065aSJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 8258085925cSJames Wright } 8268085925cSJames Wright return 0; 8278085925cSJames Wright } 8288085925cSJames Wright 82968ae065aSJames Wright // Jacobian for "set nothing" boundary integral 83068ae065aSJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian)(void *ctx, CeedInt Q, 83168ae065aSJames Wright const CeedScalar *const *in, 83268ae065aSJames Wright CeedScalar *const *out) { 83368ae065aSJames Wright // *INDENT-OFF* 83468ae065aSJames Wright // Inputs 83568ae065aSJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 83668ae065aSJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 83768ae065aSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 83868ae065aSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 83968ae065aSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 84068ae065aSJames Wright // Outputs 84168ae065aSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 84268ae065aSJames Wright // *INDENT-ON* 84368ae065aSJames Wright 84468ae065aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 84568ae065aSJames Wright const bool implicit = context->is_implicit; 84668ae065aSJames Wright 84768ae065aSJames Wright CeedPragmaSIMD 84868ae065aSJames Wright // Quadrature Point Loop 84968ae065aSJames Wright for (CeedInt i=0; i<Q; i++) { 85068ae065aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 85168ae065aSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 85268ae065aSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 85368ae065aSJames Wright q_data_sur[2][i], 85468ae065aSJames Wright q_data_sur[3][i] 85568ae065aSJames Wright }; 85668ae065aSJames Wright const CeedScalar dXdx[2][3] = { 85768ae065aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 85868ae065aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 85968ae065aSJames Wright }; 86068ae065aSJames Wright 86168ae065aSJames Wright CeedScalar U[5], kmstress[6], dU[5], dx_i[3] = {0.}; 86268ae065aSJames Wright for (int j=0; j<5; j++) U[j] = jac_data_sur[j][i]; 86368ae065aSJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 86468ae065aSJames Wright for (int j=0; j<3; j++) U[j+1] *= U[0]; 86568ae065aSJames Wright for (int j=0; j<5; j++) dU[j] = dq[j][i]; 86668ae065aSJames Wright State s = StateFromU(context, U, x_i); 86768ae065aSJames Wright State ds = StateFromU_fwd(context, s, dU, x_i, dx_i); 86868ae065aSJames Wright 86968ae065aSJames Wright State grad_ds[3]; 87068ae065aSJames Wright for (CeedInt j=0; j<3; j++) { 87168ae065aSJames Wright CeedScalar dx_i[3] = {0}, dUj[5]; 87268ae065aSJames Wright for (CeedInt k=0; k<5; k++) 87368ae065aSJames Wright dUj[k] = Grad_dq[0][k][i] * dXdx[0][j] + 87468ae065aSJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 87568ae065aSJames Wright dx_i[j] = 1.; 87668ae065aSJames Wright grad_ds[j] = StateFromU_fwd(context, s, dUj, x_i, dx_i); 87768ae065aSJames Wright } 87868ae065aSJames Wright 87968ae065aSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 88068ae065aSJames Wright KMStrainRate(grad_ds, dstrain_rate); 88168ae065aSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 88268ae065aSJames Wright KMUnpack(dkmstress, dstress); 88368ae065aSJames Wright KMUnpack(kmstress, stress); 88468ae065aSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 88568ae065aSJames Wright 88668ae065aSJames Wright StateConservative dF_inviscid[3]; 88768ae065aSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 88868ae065aSJames Wright 88968ae065aSJames Wright CeedScalar dFlux[5] = {0.}; 89068ae065aSJames Wright for (int j=0; j<3; j++) { 89168ae065aSJames Wright dFlux[0] += dF_inviscid[j].density * norm[j]; 89268ae065aSJames Wright for (int k=0; k<3; k++) 89368ae065aSJames Wright dFlux[k+1] += (dF_inviscid[j].momentum[k] - dstress[k][j]) * norm[j]; 89468ae065aSJames Wright dFlux[4] += (dF_inviscid[j].E_total + dFe[j]) * norm[j]; 89568ae065aSJames Wright } 89668ae065aSJames Wright 89768ae065aSJames Wright for (int j=0; j<5; j++) 89868ae065aSJames Wright v[j][i] = -wdetJb * dFlux[j]; 89968ae065aSJames Wright } // End Quadrature Point Loop 90068ae065aSJames Wright return 0; 90168ae065aSJames Wright } 90268ae065aSJames Wright 90304b9037bSJames Wright // Outflow boundary condition, weakly setting a constant pressure 90404b9037bSJames Wright CEED_QFUNCTION(PressureOutflow)(void *ctx, CeedInt Q, 90504b9037bSJames Wright const CeedScalar *const *in, 90604b9037bSJames Wright CeedScalar *const *out) { 90704b9037bSJames Wright // *INDENT-OFF* 90804b9037bSJames Wright // Inputs 90904b9037bSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 91025bfcc41SJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 91125bfcc41SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 91225bfcc41SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 91304b9037bSJames Wright // Outputs 91404b9037bSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 91504b9037bSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 91604b9037bSJames Wright // *INDENT-ON* 91704b9037bSJames Wright 91804b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 91904b9037bSJames Wright const bool implicit = context->is_implicit; 92004b9037bSJames Wright const CeedScalar P0 = context->P0; 92104b9037bSJames Wright 92204b9037bSJames Wright CeedPragmaSIMD 92304b9037bSJames Wright // Quadrature Point Loop 92404b9037bSJames Wright for (CeedInt i=0; i<Q; i++) { 92504b9037bSJames Wright // Setup 92604b9037bSJames Wright // -- Interp in 92725bfcc41SJames Wright const CeedScalar U[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 92825bfcc41SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 92925bfcc41SJames Wright State s = StateFromU(context, U, x_i); 93025bfcc41SJames Wright s.Y.pressure = P0; 93104b9037bSJames Wright 93204b9037bSJames Wright // -- Interp-to-Interp q_data 93304b9037bSJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 93404b9037bSJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 93504b9037bSJames Wright // We can effect this by swapping the sign on this weight 93604b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 93704b9037bSJames Wright 93804b9037bSJames Wright // ---- Normal vect 93904b9037bSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 94004b9037bSJames Wright q_data_sur[2][i], 94104b9037bSJames Wright q_data_sur[3][i] 94204b9037bSJames Wright }; 94304b9037bSJames Wright 94425bfcc41SJames Wright const CeedScalar dXdx[2][3] = { 94525bfcc41SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 94625bfcc41SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 94725bfcc41SJames Wright }; 94804b9037bSJames Wright 94925bfcc41SJames Wright State grad_s[3]; 95025bfcc41SJames Wright for (CeedInt j=0; j<3; j++) { 95125bfcc41SJames Wright CeedScalar dx_i[3] = {0}, dU[5]; 95225bfcc41SJames Wright for (CeedInt k=0; k<5; k++) 95325bfcc41SJames Wright dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 95425bfcc41SJames Wright Grad_q[1][k][i] * dXdx[1][j]; 95525bfcc41SJames Wright dx_i[j] = 1.; 95625bfcc41SJames Wright grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 95725bfcc41SJames Wright } 95825bfcc41SJames Wright 95925bfcc41SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 96025bfcc41SJames Wright KMStrainRate(grad_s, strain_rate); 96125bfcc41SJames Wright NewtonianStress(context, strain_rate, kmstress); 96225bfcc41SJames Wright KMUnpack(kmstress, stress); 96325bfcc41SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 96425bfcc41SJames Wright 96525bfcc41SJames Wright StateConservative F_inviscid[3]; 96625bfcc41SJames Wright FluxInviscid(context, s, F_inviscid); 96725bfcc41SJames Wright 96825bfcc41SJames Wright CeedScalar Flux[5] = {0.}; 96925bfcc41SJames Wright for (int j=0; j<3; j++) { 97025bfcc41SJames Wright Flux[0] += F_inviscid[j].density * norm[j]; 97125bfcc41SJames Wright for (int k=0; k<3; k++) 97225bfcc41SJames Wright Flux[k+1] += (F_inviscid[j].momentum[k] - stress[k][j]) * norm[j]; 97325bfcc41SJames Wright Flux[4] += (F_inviscid[j].E_total + Fe[j])*norm[j]; 97425bfcc41SJames Wright } 97504b9037bSJames Wright 97604b9037bSJames Wright // -- Density 97725bfcc41SJames Wright v[0][i] = -wdetJb * Flux[0]; 97804b9037bSJames Wright 97904b9037bSJames Wright // -- Momentum 98004b9037bSJames Wright for (CeedInt j=0; j<3; j++) 98125bfcc41SJames Wright v[j+1][i] = -wdetJb * Flux[j+1]; 98204b9037bSJames Wright 98304b9037bSJames Wright // -- Total Energy Density 98425bfcc41SJames Wright v[4][i] = -wdetJb * Flux[4]; 98504b9037bSJames Wright 98604b9037bSJames Wright // Save values for Jacobian 98725bfcc41SJames Wright jac_data_sur[0][i] = s.U.density; 98825bfcc41SJames Wright jac_data_sur[1][i] = s.Y.velocity[0]; 98925bfcc41SJames Wright jac_data_sur[2][i] = s.Y.velocity[1]; 99025bfcc41SJames Wright jac_data_sur[3][i] = s.Y.velocity[2]; 99125bfcc41SJames Wright jac_data_sur[4][i] = s.U.E_total; 992b01ba163SJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 99304b9037bSJames Wright } // End Quadrature Point Loop 99404b9037bSJames Wright return 0; 99504b9037bSJames Wright } 99604b9037bSJames Wright 99704b9037bSJames Wright // Jacobian for weak-pressure outflow boundary condition 99804b9037bSJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian)(void *ctx, CeedInt Q, 99904b9037bSJames Wright const CeedScalar *const *in, 100004b9037bSJames Wright CeedScalar *const *out) { 100104b9037bSJames Wright // *INDENT-OFF* 100204b9037bSJames Wright // Inputs 100304b9037bSJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 1004b01ba163SJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 1005b01ba163SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 1006b01ba163SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 1007b01ba163SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 100804b9037bSJames Wright // Outputs 100904b9037bSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 101004b9037bSJames Wright // *INDENT-ON* 101104b9037bSJames Wright 101204b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 101304b9037bSJames Wright const bool implicit = context->is_implicit; 101404b9037bSJames Wright 101504b9037bSJames Wright CeedPragmaSIMD 101604b9037bSJames Wright // Quadrature Point Loop 101704b9037bSJames Wright for (CeedInt i=0; i<Q; i++) { 1018b01ba163SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 101904b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 102004b9037bSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 102104b9037bSJames Wright q_data_sur[2][i], 102204b9037bSJames Wright q_data_sur[3][i] 102304b9037bSJames Wright }; 1024b01ba163SJames Wright const CeedScalar dXdx[2][3] = { 1025b01ba163SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 1026b01ba163SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 1027b01ba163SJames Wright }; 1028b01ba163SJames Wright 1029b01ba163SJames Wright CeedScalar U[5], kmstress[6], dU[5], dx_i[3] = {0.}; 1030b01ba163SJames Wright for (int j=0; j<5; j++) U[j] = jac_data_sur[j][i]; 1031b01ba163SJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 1032b01ba163SJames Wright for (int j=0; j<3; j++) U[j+1] *= U[0]; 1033b01ba163SJames Wright for (int j=0; j<5; j++) dU[j] = dq[j][i]; 1034b01ba163SJames Wright State s = StateFromU(context, U, x_i); 1035b01ba163SJames Wright State ds = StateFromU_fwd(context, s, dU, x_i, dx_i); 1036b01ba163SJames Wright s.Y.pressure = context->P0; 1037b01ba163SJames Wright ds.Y.pressure = 0.; 1038b01ba163SJames Wright 1039b01ba163SJames Wright State grad_ds[3]; 1040b01ba163SJames Wright for (CeedInt j=0; j<3; j++) { 1041b01ba163SJames Wright CeedScalar dx_i[3] = {0}, dUj[5]; 1042b01ba163SJames Wright for (CeedInt k=0; k<5; k++) 1043b01ba163SJames Wright dUj[k] = Grad_dq[0][k][i] * dXdx[0][j] + 1044b01ba163SJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 1045b01ba163SJames Wright dx_i[j] = 1.; 1046b01ba163SJames Wright grad_ds[j] = StateFromU_fwd(context, s, dUj, x_i, dx_i); 1047b01ba163SJames Wright } 1048b01ba163SJames Wright 1049b01ba163SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 1050b01ba163SJames Wright KMStrainRate(grad_ds, dstrain_rate); 1051b01ba163SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 1052b01ba163SJames Wright KMUnpack(dkmstress, dstress); 1053b01ba163SJames Wright KMUnpack(kmstress, stress); 1054b01ba163SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 105504b9037bSJames Wright 1056e6b47afbSJames Wright StateConservative dF_inviscid[3]; 1057e6b47afbSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 105804b9037bSJames Wright 1059e6b47afbSJames Wright CeedScalar dFlux[5] = {0.}; 1060e6b47afbSJames Wright for (int j=0; j<3; j++) { 1061e6b47afbSJames Wright dFlux[0] += dF_inviscid[j].density * norm[j]; 1062e6b47afbSJames Wright for (int k=0; k<3; k++) 1063b01ba163SJames Wright dFlux[k+1] += (dF_inviscid[j].momentum[k] - dstress[k][j]) * norm[j]; 1064b01ba163SJames Wright dFlux[4] += (dF_inviscid[j].E_total + dFe[j]) * norm[j]; 1065e6b47afbSJames Wright } 1066e6b47afbSJames Wright 1067e6b47afbSJames Wright for (int j=0; j<5; j++) 1068e6b47afbSJames Wright v[j][i] = -wdetJb * dFlux[j]; 106904b9037bSJames Wright } // End Quadrature Point Loop 107004b9037bSJames Wright return 0; 107104b9037bSJames Wright } 107204b9037bSJames Wright 10733a8779fbSJames Wright // ***************************************************************************** 10743a8779fbSJames Wright #endif // newtonian_h 1075