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" 19704b8bbeSJames 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 // ***************************************************************************** 226*cbe60e31SLeila Ghaffari // This QFunction sets a "still" initial condition for generic Newtonian IG 227*cbe60e31SLeila Ghaffari // problems in primitive variables 228*cbe60e31SLeila Ghaffari // ***************************************************************************** 229*cbe60e31SLeila Ghaffari CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, 230*cbe60e31SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 231*cbe60e31SLeila Ghaffari // Outputs 232*cbe60e31SLeila Ghaffari CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 233*cbe60e31SLeila Ghaffari 234*cbe60e31SLeila Ghaffari // Context 235*cbe60e31SLeila Ghaffari const SetupContext context = (SetupContext)ctx; 236*cbe60e31SLeila Ghaffari const CeedScalar theta0 = context->theta0; 237*cbe60e31SLeila Ghaffari const CeedScalar P0 = context->P0; 238*cbe60e31SLeila Ghaffari 239*cbe60e31SLeila Ghaffari // Quadrature Point Loop 240*cbe60e31SLeila Ghaffari CeedPragmaSIMD 241*cbe60e31SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 242*cbe60e31SLeila Ghaffari CeedScalar q[5] = {0.}; 243*cbe60e31SLeila Ghaffari 244*cbe60e31SLeila Ghaffari // Initial Conditions 245*cbe60e31SLeila Ghaffari q[0] = P0; 246*cbe60e31SLeila Ghaffari q[1] = 0.0; 247*cbe60e31SLeila Ghaffari q[2] = 0.0; 248*cbe60e31SLeila Ghaffari q[3] = 0.0; 249*cbe60e31SLeila Ghaffari q[4] = theta0; 250*cbe60e31SLeila Ghaffari 251*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 252*cbe60e31SLeila Ghaffari q0[j][i] = q[j]; 253*cbe60e31SLeila Ghaffari 254*cbe60e31SLeila Ghaffari } // End of Quadrature Point Loop 255*cbe60e31SLeila Ghaffari return 0; 256*cbe60e31SLeila Ghaffari } 257*cbe60e31SLeila Ghaffari 258*cbe60e31SLeila Ghaffari // ***************************************************************************** 2593a8779fbSJames Wright // This QFunction implements the following formulation of Navier-Stokes with 2603a8779fbSJames Wright // explicit time stepping method 2613a8779fbSJames Wright // 2623a8779fbSJames Wright // This is 3D compressible Navier-Stokes in conservation form with state 2633a8779fbSJames Wright // variables of density, momentum density, and total energy density. 2643a8779fbSJames Wright // 2653a8779fbSJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 2663a8779fbSJames Wright // rho - Mass Density 2673a8779fbSJames Wright // Ui - Momentum Density, Ui = rho ui 2683a8779fbSJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 2693a8779fbSJames Wright // 2703a8779fbSJames Wright // Navier-Stokes Equations: 2713a8779fbSJames Wright // drho/dt + div( U ) = 0 2723a8779fbSJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 2733a8779fbSJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 2743a8779fbSJames Wright // 2753a8779fbSJames Wright // Viscous Stress: 2763a8779fbSJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 2773a8779fbSJames Wright // 2783a8779fbSJames Wright // Thermal Stress: 2793a8779fbSJames Wright // Fe = u Fu + k grad( T ) 280bb8a0c61SJames Wright // Equation of State 2813a8779fbSJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 2823a8779fbSJames Wright // 2833a8779fbSJames Wright // Stabilization: 2843a8779fbSJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 2853a8779fbSJames Wright // f1 = rho sqrt(ui uj gij) 2863a8779fbSJames Wright // gij = dXi/dX * dXi/dX 2873a8779fbSJames Wright // TauC = Cc f1 / (8 gii) 2883a8779fbSJames Wright // TauM = min( 1 , 1 / f1 ) 2893a8779fbSJames Wright // TauE = TauM / (Ce cv) 2903a8779fbSJames Wright // 2913a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 2923a8779fbSJames Wright // 2933a8779fbSJames Wright // Constants: 2943a8779fbSJames Wright // lambda = - 2 / 3, From Stokes hypothesis 2953a8779fbSJames Wright // mu , Dynamic viscosity 2963a8779fbSJames Wright // k , Thermal conductivity 2973a8779fbSJames Wright // cv , Specific heat, constant volume 2983a8779fbSJames Wright // cp , Specific heat, constant pressure 2993a8779fbSJames Wright // g , Gravity 3003a8779fbSJames Wright // gamma = cp / cv, Specific heat ratio 3013a8779fbSJames Wright // 3023a8779fbSJames Wright // We require the product of the inverse of the Jacobian (dXdx_j,k) and 3033a8779fbSJames Wright // its transpose (dXdx_k,j) to properly compute integrals of the form: 3043a8779fbSJames Wright // int( gradv gradu ) 3053a8779fbSJames Wright // 3063a8779fbSJames Wright // ***************************************************************************** 307c1a52365SJed Brown CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, 3083a8779fbSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 3093a8779fbSJames Wright // *INDENT-OFF* 3103a8779fbSJames Wright // Inputs 3113a8779fbSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 312752f40e3SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 3133a8779fbSJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 3143a8779fbSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 3153a8779fbSJames Wright // Outputs 3163a8779fbSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 317752f40e3SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 3183a8779fbSJames Wright // *INDENT-ON* 3193a8779fbSJames Wright 3203a8779fbSJames Wright // Context 3213a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 3223a8779fbSJames Wright const CeedScalar mu = context->mu; 3233a8779fbSJames Wright const CeedScalar cv = context->cv; 3243a8779fbSJames Wright const CeedScalar cp = context->cp; 325bb8a0c61SJames Wright const CeedScalar *g = context->g; 326bb8a0c61SJames Wright const CeedScalar dt = context->dt; 3273a8779fbSJames Wright const CeedScalar gamma = cp / cv; 328bb8a0c61SJames Wright const CeedScalar Rd = cp - cv; 3293a8779fbSJames Wright 3303a8779fbSJames Wright CeedPragmaSIMD 3313a8779fbSJames Wright // Quadrature Point Loop 3323a8779fbSJames Wright for (CeedInt i=0; i<Q; i++) { 333c1a52365SJed Brown CeedScalar U[5]; 334c1a52365SJed Brown for (int j=0; j<5; j++) U[j] = q[j][i]; 335c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 336c1a52365SJed Brown State s = StateFromU(context, U, x_i); 337c1a52365SJed Brown 3383a8779fbSJames Wright // -- Interp-to-Interp q_data 3393a8779fbSJames Wright const CeedScalar wdetJ = q_data[0][i]; 3403a8779fbSJames Wright // -- Interp-to-Grad q_data 3413a8779fbSJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 3423a8779fbSJames Wright // *INDENT-OFF* 3433a8779fbSJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], 3443a8779fbSJames Wright q_data[2][i], 3453a8779fbSJames Wright q_data[3][i]}, 3463a8779fbSJames Wright {q_data[4][i], 3473a8779fbSJames Wright q_data[5][i], 3483a8779fbSJames Wright q_data[6][i]}, 3493a8779fbSJames Wright {q_data[7][i], 3503a8779fbSJames Wright q_data[8][i], 3513a8779fbSJames Wright q_data[9][i]} 3523a8779fbSJames Wright }; 3533a8779fbSJames Wright // *INDENT-ON* 354c1a52365SJed Brown State grad_s[3]; 355eef2387dSJed Brown for (CeedInt j=0; j<3; j++) { 3562f7ce6c1SJed Brown CeedScalar dx_i[3] = {0}, dU[5]; 3572556a851SJed Brown for (CeedInt k=0; k<5; k++) 3582556a851SJed Brown dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 3592556a851SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 3602556a851SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 361c1a52365SJed Brown dx_i[j] = 1.; 3622f7ce6c1SJed Brown grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 363c1a52365SJed Brown } 364c1a52365SJed Brown 365c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 366c1a52365SJed Brown KMStrainRate(grad_s, strain_rate); 367c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 368c1a52365SJed Brown KMUnpack(kmstress, stress); 369c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 370c1a52365SJed Brown 371c1a52365SJed Brown StateConservative F_inviscid[3]; 372c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 373c1a52365SJed Brown 374c1a52365SJed Brown // Total flux 375c1a52365SJed Brown CeedScalar Flux[5][3]; 376eef2387dSJed Brown for (CeedInt j=0; j<3; j++) { 377c1a52365SJed Brown Flux[0][j] = F_inviscid[j].density; 378eef2387dSJed Brown for (CeedInt k=0; k<3; k++) 379c1a52365SJed Brown Flux[k+1][j] = F_inviscid[j].momentum[k] - stress[k][j]; 380c1a52365SJed Brown Flux[4][j] = F_inviscid[j].E_total + Fe[j]; 381c1a52365SJed Brown } 382c1a52365SJed Brown 383eef2387dSJed Brown for (CeedInt j=0; j<3; j++) { 384eef2387dSJed Brown for (CeedInt k=0; k<5; k++) { 385752f40e3SJed Brown Grad_v[j][k][i] = wdetJ * (dXdx[j][0] * Flux[k][0] + 386c1a52365SJed Brown dXdx[j][1] * Flux[k][1] + 387c1a52365SJed Brown dXdx[j][2] * Flux[k][2]); 388c1a52365SJed Brown } 389c1a52365SJed Brown } 390c1a52365SJed Brown 391c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 392c1a52365SJed Brown for (int j=0; j<5; j++) 393c1a52365SJed Brown v[j][i] = wdetJ * body_force[j]; 3943a8779fbSJames Wright 3953a8779fbSJames Wright // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction 396c1a52365SJed Brown CeedScalar jacob_F_conv[3][5][5] = {0}; 397c1a52365SJed Brown computeFluxJacobian_NS(jacob_F_conv, s.U.density, s.Y.velocity, s.U.E_total, 398c1a52365SJed Brown gamma, g, x_i); 399c1a52365SJed Brown CeedScalar grad_U[5][3]; 400493642f1SJames Wright for (CeedInt j=0; j<3; j++) { 401c1a52365SJed Brown grad_U[0][j] = grad_s[j].U.density; 402eef2387dSJed Brown for (CeedInt k=0; k<3; k++) grad_U[k+1][j] = grad_s[j].U.momentum[k]; 403c1a52365SJed Brown grad_U[4][j] = grad_s[j].U.E_total; 4043a8779fbSJames Wright } 4053a8779fbSJames Wright 4063a8779fbSJames Wright // strong_conv = dF/dq * dq/dx (Strong convection) 4073a8779fbSJames Wright CeedScalar strong_conv[5] = {0}; 408493642f1SJames Wright for (CeedInt j=0; j<3; j++) 409493642f1SJames Wright for (CeedInt k=0; k<5; k++) 410493642f1SJames Wright for (CeedInt l=0; l<5; l++) 411c1a52365SJed Brown strong_conv[k] += jacob_F_conv[j][k][l] * grad_U[l][j]; 4123a8779fbSJames Wright 413bb8a0c61SJames Wright // -- Stabilization method: none, SU, or SUPG 414bb8a0c61SJames Wright CeedScalar stab[5][3] = {{0.}}; 415bb8a0c61SJames Wright CeedScalar tau_strong_conv[5] = {0.}, tau_strong_conv_conservative[5] = {0}; 416bb8a0c61SJames Wright CeedScalar Tau_d[3] = {0.}; 4173a8779fbSJames Wright switch (context->stabilization) { 4183a8779fbSJames Wright case STAB_NONE: // Galerkin 4193a8779fbSJames Wright break; 4203a8779fbSJames Wright case STAB_SU: // SU 421c1a52365SJed Brown Tau_diagPrim(Tau_d, dXdx, s.Y.velocity, cv, context, mu, dt, s.U.density); 422bb8a0c61SJames Wright tau_strong_conv[0] = Tau_d[0] * strong_conv[0]; 423bb8a0c61SJames Wright tau_strong_conv[1] = Tau_d[1] * strong_conv[1]; 424bb8a0c61SJames Wright tau_strong_conv[2] = Tau_d[1] * strong_conv[2]; 425bb8a0c61SJames Wright tau_strong_conv[3] = Tau_d[1] * strong_conv[3]; 426bb8a0c61SJames Wright tau_strong_conv[4] = Tau_d[2] * strong_conv[4]; 427c1a52365SJed Brown PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 428c1a52365SJed Brown tau_strong_conv, 429bb8a0c61SJames Wright tau_strong_conv_conservative); 430493642f1SJames Wright for (CeedInt j=0; j<3; j++) 431493642f1SJames Wright for (CeedInt k=0; k<5; k++) 432493642f1SJames Wright for (CeedInt l=0; l<5; l++) 433bb8a0c61SJames Wright stab[k][j] += jacob_F_conv[j][k][l] * tau_strong_conv_conservative[l]; 4343a8779fbSJames Wright 435493642f1SJames Wright for (CeedInt j=0; j<5; j++) 436493642f1SJames Wright for (CeedInt k=0; k<3; k++) 437752f40e3SJed Brown Grad_v[k][j][i] -= wdetJ*(stab[j][0] * dXdx[k][0] + 4383a8779fbSJames Wright stab[j][1] * dXdx[k][1] + 4393a8779fbSJames Wright stab[j][2] * dXdx[k][2]); 4403a8779fbSJames Wright break; 4413a8779fbSJames Wright case STAB_SUPG: // SUPG is not implemented for explicit scheme 4423a8779fbSJames Wright break; 4433a8779fbSJames Wright } 4443a8779fbSJames Wright 4453a8779fbSJames Wright } // End Quadrature Point Loop 4463a8779fbSJames Wright 4473a8779fbSJames Wright // Return 4483a8779fbSJames Wright return 0; 4493a8779fbSJames Wright } 4503a8779fbSJames Wright 4513a8779fbSJames Wright // ***************************************************************************** 4523a8779fbSJames Wright // This QFunction implements the Navier-Stokes equations (mentioned above) with 4533a8779fbSJames Wright // implicit time stepping method 4543a8779fbSJames Wright // 4553a8779fbSJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 4563a8779fbSJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 4573a8779fbSJames Wright // (diffussive terms will be added later) 4583a8779fbSJames Wright // 4593a8779fbSJames Wright // ***************************************************************************** 4603a8779fbSJames Wright CEED_QFUNCTION(IFunction_Newtonian)(void *ctx, CeedInt Q, 461*cbe60e31SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 4623a8779fbSJames Wright // *INDENT-OFF* 4633a8779fbSJames Wright // Inputs 4643a8779fbSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 465752f40e3SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 4663a8779fbSJames Wright (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 4673a8779fbSJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 4683a8779fbSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 4693a8779fbSJames Wright // Outputs 4703a8779fbSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 471752f40e3SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1], 472752f40e3SJed Brown (*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 4733a8779fbSJames Wright // *INDENT-ON* 4743a8779fbSJames Wright // Context 4753a8779fbSJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 4763a8779fbSJames Wright const CeedScalar mu = context->mu; 4773a8779fbSJames Wright const CeedScalar cv = context->cv; 4783a8779fbSJames Wright const CeedScalar cp = context->cp; 479bb8a0c61SJames Wright const CeedScalar *g = context->g; 480bb8a0c61SJames Wright const CeedScalar dt = context->dt; 4813a8779fbSJames Wright const CeedScalar gamma = cp / cv; 482bb8a0c61SJames Wright const CeedScalar Rd = cp - cv; 4833a8779fbSJames Wright 4843a8779fbSJames Wright CeedPragmaSIMD 4853a8779fbSJames Wright // Quadrature Point Loop 4863a8779fbSJames Wright for (CeedInt i=0; i<Q; i++) { 487c1a52365SJed Brown CeedScalar U[5]; 488eef2387dSJed Brown for (CeedInt j=0; j<5; j++) U[j] = q[j][i]; 489c1a52365SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 490c1a52365SJed Brown State s = StateFromU(context, U, x_i); 491c1a52365SJed Brown 4923a8779fbSJames Wright // -- Interp-to-Interp q_data 4933a8779fbSJames Wright const CeedScalar wdetJ = q_data[0][i]; 4943a8779fbSJames Wright // -- Interp-to-Grad q_data 4953a8779fbSJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 4963a8779fbSJames Wright // *INDENT-OFF* 4973a8779fbSJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], 4983a8779fbSJames Wright q_data[2][i], 4993a8779fbSJames Wright q_data[3][i]}, 5003a8779fbSJames Wright {q_data[4][i], 5013a8779fbSJames Wright q_data[5][i], 5023a8779fbSJames Wright q_data[6][i]}, 5033a8779fbSJames Wright {q_data[7][i], 5043a8779fbSJames Wright q_data[8][i], 5053a8779fbSJames Wright q_data[9][i]} 5063a8779fbSJames Wright }; 5073a8779fbSJames Wright // *INDENT-ON* 508c1a52365SJed Brown State grad_s[3]; 509493642f1SJames Wright for (CeedInt j=0; j<3; j++) { 5102f7ce6c1SJed Brown CeedScalar dx_i[3] = {0}, dU[5]; 5112556a851SJed Brown for (CeedInt k=0; k<5; k++) 5122556a851SJed Brown dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 5132556a851SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 5142556a851SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 515c1a52365SJed Brown dx_i[j] = 1.; 5162f7ce6c1SJed Brown grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 5173a8779fbSJames Wright } 518c1a52365SJed Brown 519c1a52365SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 520c1a52365SJed Brown KMStrainRate(grad_s, strain_rate); 521c1a52365SJed Brown NewtonianStress(context, strain_rate, kmstress); 522c1a52365SJed Brown KMUnpack(kmstress, stress); 523c1a52365SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 524c1a52365SJed Brown 525c1a52365SJed Brown StateConservative F_inviscid[3]; 526c1a52365SJed Brown FluxInviscid(context, s, F_inviscid); 527c1a52365SJed Brown 528c1a52365SJed Brown 529c1a52365SJed Brown // Total flux 530c1a52365SJed Brown CeedScalar Flux[5][3]; 531eef2387dSJed Brown for (CeedInt j=0; j<3; j++) { 532c1a52365SJed Brown Flux[0][j] = F_inviscid[j].density; 533493642f1SJames Wright for (CeedInt k=0; k<3; k++) 534c1a52365SJed Brown Flux[k+1][j] = F_inviscid[j].momentum[k] - stress[k][j]; 535c1a52365SJed Brown Flux[4][j] = F_inviscid[j].E_total + Fe[j]; 536c1a52365SJed Brown } 537c1a52365SJed Brown 538eef2387dSJed Brown for (CeedInt j=0; j<3; j++) { 539eef2387dSJed Brown for (CeedInt k=0; k<5; k++) { 540752f40e3SJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + 541c1a52365SJed Brown dXdx[j][1] * Flux[k][1] + 542c1a52365SJed Brown dXdx[j][2] * Flux[k][2]); 543c1a52365SJed Brown } 544c1a52365SJed Brown } 545c1a52365SJed Brown 546c1a52365SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 547eef2387dSJed Brown for (CeedInt j=0; j<5; j++) 548c1a52365SJed Brown v[j][i] = wdetJ * (q_dot[j][i] - body_force[j]); 5493a8779fbSJames Wright 5503a8779fbSJames Wright // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction 551c1a52365SJed Brown CeedScalar jacob_F_conv[3][5][5] = {0}; 552c1a52365SJed Brown computeFluxJacobian_NS(jacob_F_conv, s.U.density, s.Y.velocity, s.U.E_total, 553c1a52365SJed Brown gamma, g, x_i); 554c1a52365SJed Brown CeedScalar grad_U[5][3]; 555493642f1SJames Wright for (CeedInt j=0; j<3; j++) { 556c1a52365SJed Brown grad_U[0][j] = grad_s[j].U.density; 557eef2387dSJed Brown for (CeedInt k=0; k<3; k++) grad_U[k+1][j] = grad_s[j].U.momentum[k]; 558c1a52365SJed Brown grad_U[4][j] = grad_s[j].U.E_total; 5593a8779fbSJames Wright } 560c1a52365SJed Brown 5613a8779fbSJames Wright // strong_conv = dF/dq * dq/dx (Strong convection) 5623a8779fbSJames Wright CeedScalar strong_conv[5] = {0}; 563493642f1SJames Wright for (CeedInt j=0; j<3; j++) 564493642f1SJames Wright for (CeedInt k=0; k<5; k++) 565493642f1SJames Wright for (CeedInt l=0; l<5; l++) 566c1a52365SJed Brown strong_conv[k] += jacob_F_conv[j][k][l] * grad_U[l][j]; 5673a8779fbSJames Wright 5683a8779fbSJames Wright // Strong residual 5693a8779fbSJames Wright CeedScalar strong_res[5]; 570493642f1SJames Wright for (CeedInt j=0; j<5; j++) 5713a8779fbSJames Wright strong_res[j] = q_dot[j][i] + strong_conv[j] - body_force[j]; 5723a8779fbSJames Wright 5733a8779fbSJames Wright // -- Stabilization method: none, SU, or SUPG 574bb8a0c61SJames Wright CeedScalar stab[5][3] = {{0.}}; 575bb8a0c61SJames Wright CeedScalar tau_strong_res[5] = {0.}, tau_strong_res_conservative[5] = {0}; 576bb8a0c61SJames Wright CeedScalar tau_strong_conv[5] = {0.}, tau_strong_conv_conservative[5] = {0}; 577bb8a0c61SJames Wright CeedScalar Tau_d[3] = {0.}; 5783a8779fbSJames Wright switch (context->stabilization) { 5793a8779fbSJames Wright case STAB_NONE: // Galerkin 5803a8779fbSJames Wright break; 5813a8779fbSJames Wright case STAB_SU: // SU 582c1a52365SJed Brown Tau_diagPrim(Tau_d, dXdx, s.Y.velocity, cv, context, mu, dt, s.U.density); 583bb8a0c61SJames Wright tau_strong_conv[0] = Tau_d[0] * strong_conv[0]; 584bb8a0c61SJames Wright tau_strong_conv[1] = Tau_d[1] * strong_conv[1]; 585bb8a0c61SJames Wright tau_strong_conv[2] = Tau_d[1] * strong_conv[2]; 586bb8a0c61SJames Wright tau_strong_conv[3] = Tau_d[1] * strong_conv[3]; 587bb8a0c61SJames Wright tau_strong_conv[4] = Tau_d[2] * strong_conv[4]; 588c1a52365SJed Brown PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 589c1a52365SJed Brown tau_strong_conv, tau_strong_conv_conservative); 590493642f1SJames Wright for (CeedInt j=0; j<3; j++) 591493642f1SJames Wright for (CeedInt k=0; k<5; k++) 592493642f1SJames Wright for (CeedInt l=0; l<5; l++) 593bb8a0c61SJames Wright stab[k][j] += jacob_F_conv[j][k][l] * tau_strong_conv_conservative[l]; 5943a8779fbSJames Wright 595493642f1SJames Wright for (CeedInt j=0; j<5; j++) 596493642f1SJames Wright for (CeedInt k=0; k<3; k++) 597752f40e3SJed Brown Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 5983a8779fbSJames Wright stab[j][1] * dXdx[k][1] + 5993a8779fbSJames Wright stab[j][2] * dXdx[k][2]); 600eef2387dSJed Brown 6013a8779fbSJames Wright break; 6023a8779fbSJames Wright case STAB_SUPG: // SUPG 603c1a52365SJed Brown Tau_diagPrim(Tau_d, dXdx, s.Y.velocity, cv, context, mu, dt, s.U.density); 604bb8a0c61SJames Wright tau_strong_res[0] = Tau_d[0] * strong_res[0]; 605bb8a0c61SJames Wright tau_strong_res[1] = Tau_d[1] * strong_res[1]; 606bb8a0c61SJames Wright tau_strong_res[2] = Tau_d[1] * strong_res[2]; 607bb8a0c61SJames Wright tau_strong_res[3] = Tau_d[1] * strong_res[3]; 608bb8a0c61SJames Wright tau_strong_res[4] = Tau_d[2] * strong_res[4]; 609*cbe60e31SLeila Ghaffari 610c1a52365SJed Brown PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 611c1a52365SJed Brown tau_strong_res, tau_strong_res_conservative); 612493642f1SJames Wright for (CeedInt j=0; j<3; j++) 613493642f1SJames Wright for (CeedInt k=0; k<5; k++) 614493642f1SJames Wright for (CeedInt l=0; l<5; l++) 615bb8a0c61SJames Wright stab[k][j] += jacob_F_conv[j][k][l] * tau_strong_res_conservative[l]; 6163a8779fbSJames Wright 617493642f1SJames Wright for (CeedInt j=0; j<5; j++) 618493642f1SJames Wright for (CeedInt k=0; k<3; k++) 619752f40e3SJed Brown Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 6203a8779fbSJames Wright stab[j][1] * dXdx[k][1] + 6213a8779fbSJames Wright stab[j][2] * dXdx[k][2]); 6223a8779fbSJames Wright break; 6233a8779fbSJames Wright } 624eef2387dSJed Brown for (CeedInt j=0; j<5; j++) jac_data[j][i] = U[j]; 625eef2387dSJed Brown for (CeedInt j=0; j<6; j++) jac_data[5+j][i] = kmstress[j]; 626eef2387dSJed Brown for (CeedInt j=0; j<3; j++) jac_data[5+6+j][i] = Tau_d[j]; 6273a8779fbSJames Wright 6283a8779fbSJames Wright } // End Quadrature Point Loop 6293a8779fbSJames Wright 6303a8779fbSJames Wright // Return 6313a8779fbSJames Wright return 0; 6323a8779fbSJames Wright } 633f0b65372SJed Brown 634*cbe60e31SLeila Ghaffari // ***************************************************************************** 635*cbe60e31SLeila Ghaffari // This QFunction implements the jacobean of the Navier-Stokes equations 636*cbe60e31SLeila Ghaffari // for implicit time stepping method. 637*cbe60e31SLeila Ghaffari // 638*cbe60e31SLeila Ghaffari // ***************************************************************************** 639f0b65372SJed Brown CEED_QFUNCTION(IJacobian_Newtonian)(void *ctx, CeedInt Q, 640f0b65372SJed Brown const CeedScalar *const *in, 641f0b65372SJed Brown CeedScalar *const *out) { 642f0b65372SJed Brown // *INDENT-OFF* 643f0b65372SJed Brown // Inputs 644f0b65372SJed Brown const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 645f0b65372SJed Brown (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 646f0b65372SJed Brown (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 647f0b65372SJed Brown (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 648f0b65372SJed Brown (*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 649f0b65372SJed Brown // Outputs 650f0b65372SJed Brown CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 651f0b65372SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 652f0b65372SJed Brown // *INDENT-ON* 653f0b65372SJed Brown // Context 654f0b65372SJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 655f0b65372SJed Brown const CeedScalar *g = context->g; 656f0b65372SJed Brown const CeedScalar cp = context->cp; 657f0b65372SJed Brown const CeedScalar cv = context->cv; 658f0b65372SJed Brown const CeedScalar Rd = cp - cv; 659f0b65372SJed Brown const CeedScalar gamma = cp / cv; 660f0b65372SJed Brown 661f0b65372SJed Brown CeedPragmaSIMD 662f0b65372SJed Brown // Quadrature Point Loop 663f0b65372SJed Brown for (CeedInt i=0; i<Q; i++) { 664f0b65372SJed Brown // -- Interp-to-Interp q_data 665f0b65372SJed Brown const CeedScalar wdetJ = q_data[0][i]; 666f0b65372SJed Brown // -- Interp-to-Grad q_data 667f0b65372SJed Brown // ---- Inverse of change of coordinate matrix: X_i,j 668f0b65372SJed Brown // *INDENT-OFF* 669f0b65372SJed Brown const CeedScalar dXdx[3][3] = {{q_data[1][i], 670f0b65372SJed Brown q_data[2][i], 671f0b65372SJed Brown q_data[3][i]}, 672f0b65372SJed Brown {q_data[4][i], 673f0b65372SJed Brown q_data[5][i], 674f0b65372SJed Brown q_data[6][i]}, 675f0b65372SJed Brown {q_data[7][i], 676f0b65372SJed Brown q_data[8][i], 677f0b65372SJed Brown q_data[9][i]} 678f0b65372SJed Brown }; 679f0b65372SJed Brown // *INDENT-ON* 680f0b65372SJed Brown 681f0b65372SJed Brown CeedScalar U[5], kmstress[6], Tau_d[3] __attribute((unused)); 682f0b65372SJed Brown for (int j=0; j<5; j++) U[j] = jac_data[j][i]; 683f0b65372SJed Brown for (int j=0; j<6; j++) kmstress[j] = jac_data[5+j][i]; 684f0b65372SJed Brown for (int j=0; j<3; j++) Tau_d[j] = jac_data[5+6+j][i]; 685f0b65372SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 686f0b65372SJed Brown State s = StateFromU(context, U, x_i); 687f0b65372SJed Brown 688f0b65372SJed Brown CeedScalar dU[5], dx0[3] = {0}; 689f0b65372SJed Brown for (int j=0; j<5; j++) dU[j] = dq[j][i]; 690f0b65372SJed Brown State ds = StateFromU_fwd(context, s, dU, x_i, dx0); 691f0b65372SJed Brown 692f0b65372SJed Brown State grad_ds[3]; 693f0b65372SJed Brown for (int j=0; j<3; j++) { 694f0b65372SJed Brown CeedScalar dUj[5]; 695f0b65372SJed Brown for (int k=0; k<5; k++) dUj[k] = Grad_dq[0][k][i] * dXdx[0][j] 696f0b65372SJed Brown + Grad_dq[1][k][i] * dXdx[1][j] 697f0b65372SJed Brown + Grad_dq[2][k][i] * dXdx[2][j]; 698f0b65372SJed Brown grad_ds[j] = StateFromU_fwd(context, s, dUj, x_i, dx0); 699f0b65372SJed Brown } 700f0b65372SJed Brown 701f0b65372SJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 702f0b65372SJed Brown KMStrainRate(grad_ds, dstrain_rate); 703f0b65372SJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 704f0b65372SJed Brown KMUnpack(dkmstress, dstress); 705f0b65372SJed Brown KMUnpack(kmstress, stress); 706f0b65372SJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 707f0b65372SJed Brown 708f0b65372SJed Brown StateConservative dF_inviscid[3]; 709f0b65372SJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 710f0b65372SJed Brown 711f0b65372SJed Brown // Total flux 712f0b65372SJed Brown CeedScalar dFlux[5][3]; 713f0b65372SJed Brown for (int j=0; j<3; j++) { 714f0b65372SJed Brown dFlux[0][j] = dF_inviscid[j].density; 715f0b65372SJed Brown for (int k=0; k<3; k++) 716f0b65372SJed Brown dFlux[k+1][j] = dF_inviscid[j].momentum[k] - dstress[k][j]; 717f0b65372SJed Brown dFlux[4][j] = dF_inviscid[j].E_total + dFe[j]; 718f0b65372SJed Brown } 719f0b65372SJed Brown 720f0b65372SJed Brown for (int j=0; j<3; j++) { 721f0b65372SJed Brown for (int k=0; k<5; k++) { 722f0b65372SJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + 723f0b65372SJed Brown dXdx[j][1] * dFlux[k][1] + 724f0b65372SJed Brown dXdx[j][2] * dFlux[k][2]); 725f0b65372SJed Brown } 726f0b65372SJed Brown } 727f0b65372SJed Brown 728f0b65372SJed Brown const CeedScalar dbody_force[5] = {0, ds.U.density *g[0], ds.U.density *g[1], ds.U.density *g[2], 0}; 729f0b65372SJed Brown for (int j=0; j<5; j++) 730f0b65372SJed Brown v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 731f0b65372SJed Brown 732f0b65372SJed Brown if (1) { 733f0b65372SJed Brown CeedScalar jacob_F_conv[3][5][5] = {0}; 734f0b65372SJed Brown computeFluxJacobian_NS(jacob_F_conv, s.U.density, s.Y.velocity, s.U.E_total, 735f0b65372SJed Brown gamma, g, x_i); 736f0b65372SJed Brown CeedScalar grad_dU[5][3]; 737f0b65372SJed Brown for (int j=0; j<3; j++) { 738f0b65372SJed Brown grad_dU[0][j] = grad_ds[j].U.density; 739f0b65372SJed Brown for (int k=0; k<3; k++) grad_dU[k+1][j] = grad_ds[j].U.momentum[k]; 740f0b65372SJed Brown grad_dU[4][j] = grad_ds[j].U.E_total; 741f0b65372SJed Brown } 742f0b65372SJed Brown CeedScalar dstrong_conv[5] = {0}; 743f0b65372SJed Brown for (int j=0; j<3; j++) 744f0b65372SJed Brown for (int k=0; k<5; k++) 745f0b65372SJed Brown for (int l=0; l<5; l++) 746f0b65372SJed Brown dstrong_conv[k] += jacob_F_conv[j][k][l] * grad_dU[l][j]; 747f0b65372SJed Brown CeedScalar dstrong_res[5]; 748f0b65372SJed Brown for (int j=0; j<5; j++) 749f0b65372SJed Brown dstrong_res[j] = context->ijacobian_time_shift * dU[j] + dstrong_conv[j] - 750f0b65372SJed Brown dbody_force[j]; 751f0b65372SJed Brown CeedScalar dtau_strong_res[5] = {0.}, dtau_strong_res_conservative[5] = {0}; 752f0b65372SJed Brown dtau_strong_res[0] = Tau_d[0] * dstrong_res[0]; 753f0b65372SJed Brown dtau_strong_res[1] = Tau_d[1] * dstrong_res[1]; 754f0b65372SJed Brown dtau_strong_res[2] = Tau_d[1] * dstrong_res[2]; 755f0b65372SJed Brown dtau_strong_res[3] = Tau_d[1] * dstrong_res[3]; 756f0b65372SJed Brown dtau_strong_res[4] = Tau_d[2] * dstrong_res[4]; 757f0b65372SJed Brown PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 758f0b65372SJed Brown dtau_strong_res, dtau_strong_res_conservative); 759f0b65372SJed Brown CeedScalar dstab[5][3] = {0}; 760f0b65372SJed Brown for (int j=0; j<3; j++) 761f0b65372SJed Brown for (int k=0; k<5; k++) 762f0b65372SJed Brown for (int l=0; l<5; l++) 763f0b65372SJed Brown dstab[k][j] += jacob_F_conv[j][k][l] * dtau_strong_res_conservative[l]; 764f0b65372SJed Brown for (int j=0; j<5; j++) 765f0b65372SJed Brown for (int k=0; k<3; k++) 766f0b65372SJed Brown Grad_v[k][j][i] += wdetJ*(dstab[j][0] * dXdx[k][0] + 767f0b65372SJed Brown dstab[j][1] * dXdx[k][1] + 768f0b65372SJed Brown dstab[j][2] * dXdx[k][2]); 769f0b65372SJed Brown 770f0b65372SJed Brown } 771f0b65372SJed Brown } // End Quadrature Point Loop 772f0b65372SJed Brown return 0; 773f0b65372SJed Brown } 7748085925cSJames Wright 7758085925cSJames Wright // Compute boundary integral (ie. for strongly set inflows) 7768085925cSJames Wright CEED_QFUNCTION(BoundaryIntegral)(void *ctx, CeedInt Q, 7778085925cSJames Wright const CeedScalar *const *in, 7788085925cSJames Wright CeedScalar *const *out) { 7798085925cSJames Wright 7808085925cSJames Wright //*INDENT-OFF* 7818085925cSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 782d3b25f3aSJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 783d3b25f3aSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 784d3b25f3aSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 7858085925cSJames Wright 78668ae065aSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[0], 78768ae065aSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[1]; 7888085925cSJames Wright 7898085925cSJames Wright //*INDENT-ON* 7908085925cSJames Wright 791d3b25f3aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext) ctx; 792d3b25f3aSJames Wright const bool is_implicit = context->is_implicit; 7938085925cSJames Wright 7948085925cSJames Wright CeedPragmaSIMD 7958085925cSJames Wright for(CeedInt i=0; i<Q; i++) { 796d3b25f3aSJames Wright const CeedScalar U[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 797d3b25f3aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 798d3b25f3aSJames Wright const State s = StateFromU(context, U, x_i); 7998085925cSJames Wright 8008085925cSJames Wright const CeedScalar wdetJb = (is_implicit ? -1. : 1.) * q_data_sur[0][i]; 8018085925cSJames Wright // ---- Normal vect 8028085925cSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 8038085925cSJames Wright q_data_sur[2][i], 8048085925cSJames Wright q_data_sur[3][i] 8058085925cSJames Wright }; 8068085925cSJames Wright 807d3b25f3aSJames Wright const CeedScalar dXdx[2][3] = { 808d3b25f3aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 809d3b25f3aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 810d3b25f3aSJames Wright }; 8118085925cSJames Wright 812d3b25f3aSJames Wright State grad_s[3]; 813d3b25f3aSJames Wright for (CeedInt j=0; j<3; j++) { 814d3b25f3aSJames Wright CeedScalar dx_i[3] = {0}, dU[5]; 815d3b25f3aSJames Wright for (CeedInt k=0; k<5; k++) 816d3b25f3aSJames Wright dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 817d3b25f3aSJames Wright Grad_q[1][k][i] * dXdx[1][j]; 818d3b25f3aSJames Wright dx_i[j] = 1.; 819d3b25f3aSJames Wright grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 820d3b25f3aSJames Wright } 8218085925cSJames Wright 822d3b25f3aSJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 823d3b25f3aSJames Wright KMStrainRate(grad_s, strain_rate); 824d3b25f3aSJames Wright NewtonianStress(context, strain_rate, kmstress); 825d3b25f3aSJames Wright KMUnpack(kmstress, stress); 826d3b25f3aSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 827d3b25f3aSJames Wright 828d3b25f3aSJames Wright StateConservative F_inviscid[3]; 829d3b25f3aSJames Wright FluxInviscid(context, s, F_inviscid); 830d3b25f3aSJames Wright 831d3b25f3aSJames Wright CeedScalar Flux[5] = {0.}; 832d3b25f3aSJames Wright for (int j=0; j<3; j++) { 833d3b25f3aSJames Wright Flux[0] += F_inviscid[j].density * norm[j]; 834d3b25f3aSJames Wright for (int k=0; k<3; k++) 835d3b25f3aSJames Wright Flux[k+1] += (F_inviscid[j].momentum[k] - stress[k][j]) * norm[j]; 836d3b25f3aSJames Wright Flux[4] += (F_inviscid[j].E_total + Fe[j])*norm[j]; 837d3b25f3aSJames Wright } 838d3b25f3aSJames Wright 8398085925cSJames Wright // -- Density 840d3b25f3aSJames Wright v[0][i] = -wdetJb * Flux[0]; 8418085925cSJames Wright 8428085925cSJames Wright // -- Momentum 8438085925cSJames Wright for (CeedInt j=0; j<3; j++) 844d3b25f3aSJames Wright v[j+1][i] = -wdetJb * Flux[j+1]; 8458085925cSJames Wright 8468085925cSJames Wright // -- Total Energy Density 847d3b25f3aSJames Wright v[4][i] = -wdetJb * Flux[4]; 84868ae065aSJames Wright 84968ae065aSJames Wright jac_data_sur[0][i] = s.U.density; 85068ae065aSJames Wright jac_data_sur[1][i] = s.Y.velocity[0]; 85168ae065aSJames Wright jac_data_sur[2][i] = s.Y.velocity[1]; 85268ae065aSJames Wright jac_data_sur[3][i] = s.Y.velocity[2]; 85368ae065aSJames Wright jac_data_sur[4][i] = s.U.E_total; 85468ae065aSJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 8558085925cSJames Wright } 8568085925cSJames Wright return 0; 8578085925cSJames Wright } 8588085925cSJames Wright 85968ae065aSJames Wright // Jacobian for "set nothing" boundary integral 86068ae065aSJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian)(void *ctx, CeedInt Q, 86168ae065aSJames Wright const CeedScalar *const *in, 86268ae065aSJames Wright CeedScalar *const *out) { 86368ae065aSJames Wright // *INDENT-OFF* 86468ae065aSJames Wright // Inputs 86568ae065aSJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 86668ae065aSJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 86768ae065aSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 86868ae065aSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 86968ae065aSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 87068ae065aSJames Wright // Outputs 87168ae065aSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 87268ae065aSJames Wright // *INDENT-ON* 87368ae065aSJames Wright 87468ae065aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 87568ae065aSJames Wright const bool implicit = context->is_implicit; 87668ae065aSJames Wright 87768ae065aSJames Wright CeedPragmaSIMD 87868ae065aSJames Wright // Quadrature Point Loop 87968ae065aSJames Wright for (CeedInt i=0; i<Q; i++) { 88068ae065aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 88168ae065aSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 88268ae065aSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 88368ae065aSJames Wright q_data_sur[2][i], 88468ae065aSJames Wright q_data_sur[3][i] 88568ae065aSJames Wright }; 88668ae065aSJames Wright const CeedScalar dXdx[2][3] = { 88768ae065aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 88868ae065aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 88968ae065aSJames Wright }; 89068ae065aSJames Wright 89168ae065aSJames Wright CeedScalar U[5], kmstress[6], dU[5], dx_i[3] = {0.}; 89268ae065aSJames Wright for (int j=0; j<5; j++) U[j] = jac_data_sur[j][i]; 89368ae065aSJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 89468ae065aSJames Wright for (int j=0; j<3; j++) U[j+1] *= U[0]; 89568ae065aSJames Wright for (int j=0; j<5; j++) dU[j] = dq[j][i]; 89668ae065aSJames Wright State s = StateFromU(context, U, x_i); 89768ae065aSJames Wright State ds = StateFromU_fwd(context, s, dU, x_i, dx_i); 89868ae065aSJames Wright 89968ae065aSJames Wright State grad_ds[3]; 90068ae065aSJames Wright for (CeedInt j=0; j<3; j++) { 90168ae065aSJames Wright CeedScalar dx_i[3] = {0}, dUj[5]; 90268ae065aSJames Wright for (CeedInt k=0; k<5; k++) 90368ae065aSJames Wright dUj[k] = Grad_dq[0][k][i] * dXdx[0][j] + 90468ae065aSJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 90568ae065aSJames Wright dx_i[j] = 1.; 90668ae065aSJames Wright grad_ds[j] = StateFromU_fwd(context, s, dUj, x_i, dx_i); 90768ae065aSJames Wright } 90868ae065aSJames Wright 90968ae065aSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 91068ae065aSJames Wright KMStrainRate(grad_ds, dstrain_rate); 91168ae065aSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 91268ae065aSJames Wright KMUnpack(dkmstress, dstress); 91368ae065aSJames Wright KMUnpack(kmstress, stress); 91468ae065aSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 91568ae065aSJames Wright 91668ae065aSJames Wright StateConservative dF_inviscid[3]; 91768ae065aSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 91868ae065aSJames Wright 91968ae065aSJames Wright CeedScalar dFlux[5] = {0.}; 92068ae065aSJames Wright for (int j=0; j<3; j++) { 92168ae065aSJames Wright dFlux[0] += dF_inviscid[j].density * norm[j]; 92268ae065aSJames Wright for (int k=0; k<3; k++) 92368ae065aSJames Wright dFlux[k+1] += (dF_inviscid[j].momentum[k] - dstress[k][j]) * norm[j]; 92468ae065aSJames Wright dFlux[4] += (dF_inviscid[j].E_total + dFe[j]) * norm[j]; 92568ae065aSJames Wright } 92668ae065aSJames Wright 92768ae065aSJames Wright for (int j=0; j<5; j++) 92868ae065aSJames Wright v[j][i] = -wdetJb * dFlux[j]; 92968ae065aSJames Wright } // End Quadrature Point Loop 93068ae065aSJames Wright return 0; 93168ae065aSJames Wright } 93268ae065aSJames Wright 93304b9037bSJames Wright // Outflow boundary condition, weakly setting a constant pressure 93404b9037bSJames Wright CEED_QFUNCTION(PressureOutflow)(void *ctx, CeedInt Q, 93504b9037bSJames Wright const CeedScalar *const *in, 93604b9037bSJames Wright CeedScalar *const *out) { 93704b9037bSJames Wright // *INDENT-OFF* 93804b9037bSJames Wright // Inputs 93904b9037bSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 94025bfcc41SJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 94125bfcc41SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 94225bfcc41SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 94304b9037bSJames Wright // Outputs 94404b9037bSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 94504b9037bSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 94604b9037bSJames Wright // *INDENT-ON* 94704b9037bSJames Wright 94804b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 94904b9037bSJames Wright const bool implicit = context->is_implicit; 95004b9037bSJames Wright const CeedScalar P0 = context->P0; 95104b9037bSJames Wright 95204b9037bSJames Wright CeedPragmaSIMD 95304b9037bSJames Wright // Quadrature Point Loop 95404b9037bSJames Wright for (CeedInt i=0; i<Q; i++) { 95504b9037bSJames Wright // Setup 95604b9037bSJames Wright // -- Interp in 95725bfcc41SJames Wright const CeedScalar U[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 95825bfcc41SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 95925bfcc41SJames Wright State s = StateFromU(context, U, x_i); 96025bfcc41SJames Wright s.Y.pressure = P0; 96104b9037bSJames Wright 96204b9037bSJames Wright // -- Interp-to-Interp q_data 96304b9037bSJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 96404b9037bSJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 96504b9037bSJames Wright // We can effect this by swapping the sign on this weight 96604b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 96704b9037bSJames Wright 96804b9037bSJames Wright // ---- Normal vect 96904b9037bSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 97004b9037bSJames Wright q_data_sur[2][i], 97104b9037bSJames Wright q_data_sur[3][i] 97204b9037bSJames Wright }; 97304b9037bSJames Wright 97425bfcc41SJames Wright const CeedScalar dXdx[2][3] = { 97525bfcc41SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 97625bfcc41SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 97725bfcc41SJames Wright }; 97804b9037bSJames Wright 97925bfcc41SJames Wright State grad_s[3]; 98025bfcc41SJames Wright for (CeedInt j=0; j<3; j++) { 98125bfcc41SJames Wright CeedScalar dx_i[3] = {0}, dU[5]; 98225bfcc41SJames Wright for (CeedInt k=0; k<5; k++) 98325bfcc41SJames Wright dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 98425bfcc41SJames Wright Grad_q[1][k][i] * dXdx[1][j]; 98525bfcc41SJames Wright dx_i[j] = 1.; 98625bfcc41SJames Wright grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 98725bfcc41SJames Wright } 98825bfcc41SJames Wright 98925bfcc41SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 99025bfcc41SJames Wright KMStrainRate(grad_s, strain_rate); 99125bfcc41SJames Wright NewtonianStress(context, strain_rate, kmstress); 99225bfcc41SJames Wright KMUnpack(kmstress, stress); 99325bfcc41SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 99425bfcc41SJames Wright 99525bfcc41SJames Wright StateConservative F_inviscid[3]; 99625bfcc41SJames Wright FluxInviscid(context, s, F_inviscid); 99725bfcc41SJames Wright 99825bfcc41SJames Wright CeedScalar Flux[5] = {0.}; 99925bfcc41SJames Wright for (int j=0; j<3; j++) { 100025bfcc41SJames Wright Flux[0] += F_inviscid[j].density * norm[j]; 100125bfcc41SJames Wright for (int k=0; k<3; k++) 100225bfcc41SJames Wright Flux[k+1] += (F_inviscid[j].momentum[k] - stress[k][j]) * norm[j]; 100325bfcc41SJames Wright Flux[4] += (F_inviscid[j].E_total + Fe[j])*norm[j]; 100425bfcc41SJames Wright } 100504b9037bSJames Wright 100604b9037bSJames Wright // -- Density 100725bfcc41SJames Wright v[0][i] = -wdetJb * Flux[0]; 100804b9037bSJames Wright 100904b9037bSJames Wright // -- Momentum 101004b9037bSJames Wright for (CeedInt j=0; j<3; j++) 101125bfcc41SJames Wright v[j+1][i] = -wdetJb * Flux[j+1]; 101204b9037bSJames Wright 101304b9037bSJames Wright // -- Total Energy Density 101425bfcc41SJames Wright v[4][i] = -wdetJb * Flux[4]; 101504b9037bSJames Wright 101604b9037bSJames Wright // Save values for Jacobian 101725bfcc41SJames Wright jac_data_sur[0][i] = s.U.density; 101825bfcc41SJames Wright jac_data_sur[1][i] = s.Y.velocity[0]; 101925bfcc41SJames Wright jac_data_sur[2][i] = s.Y.velocity[1]; 102025bfcc41SJames Wright jac_data_sur[3][i] = s.Y.velocity[2]; 102125bfcc41SJames Wright jac_data_sur[4][i] = s.U.E_total; 1022b01ba163SJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 102304b9037bSJames Wright } // End Quadrature Point Loop 102404b9037bSJames Wright return 0; 102504b9037bSJames Wright } 102604b9037bSJames Wright 102704b9037bSJames Wright // Jacobian for weak-pressure outflow boundary condition 102804b9037bSJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian)(void *ctx, CeedInt Q, 102904b9037bSJames Wright const CeedScalar *const *in, 103004b9037bSJames Wright CeedScalar *const *out) { 103104b9037bSJames Wright // *INDENT-OFF* 103204b9037bSJames Wright // Inputs 103304b9037bSJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 1034b01ba163SJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 1035b01ba163SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 1036b01ba163SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 1037b01ba163SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 103804b9037bSJames Wright // Outputs 103904b9037bSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 104004b9037bSJames Wright // *INDENT-ON* 104104b9037bSJames Wright 104204b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 104304b9037bSJames Wright const bool implicit = context->is_implicit; 104404b9037bSJames Wright 104504b9037bSJames Wright CeedPragmaSIMD 104604b9037bSJames Wright // Quadrature Point Loop 104704b9037bSJames Wright for (CeedInt i=0; i<Q; i++) { 1048b01ba163SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 104904b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 105004b9037bSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 105104b9037bSJames Wright q_data_sur[2][i], 105204b9037bSJames Wright q_data_sur[3][i] 105304b9037bSJames Wright }; 1054b01ba163SJames Wright const CeedScalar dXdx[2][3] = { 1055b01ba163SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 1056b01ba163SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 1057b01ba163SJames Wright }; 1058b01ba163SJames Wright 1059b01ba163SJames Wright CeedScalar U[5], kmstress[6], dU[5], dx_i[3] = {0.}; 1060b01ba163SJames Wright for (int j=0; j<5; j++) U[j] = jac_data_sur[j][i]; 1061b01ba163SJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 1062b01ba163SJames Wright for (int j=0; j<3; j++) U[j+1] *= U[0]; 1063b01ba163SJames Wright for (int j=0; j<5; j++) dU[j] = dq[j][i]; 1064b01ba163SJames Wright State s = StateFromU(context, U, x_i); 1065b01ba163SJames Wright State ds = StateFromU_fwd(context, s, dU, x_i, dx_i); 1066b01ba163SJames Wright s.Y.pressure = context->P0; 1067b01ba163SJames Wright ds.Y.pressure = 0.; 1068b01ba163SJames Wright 1069b01ba163SJames Wright State grad_ds[3]; 1070b01ba163SJames Wright for (CeedInt j=0; j<3; j++) { 1071b01ba163SJames Wright CeedScalar dx_i[3] = {0}, dUj[5]; 1072b01ba163SJames Wright for (CeedInt k=0; k<5; k++) 1073b01ba163SJames Wright dUj[k] = Grad_dq[0][k][i] * dXdx[0][j] + 1074b01ba163SJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 1075b01ba163SJames Wright dx_i[j] = 1.; 1076b01ba163SJames Wright grad_ds[j] = StateFromU_fwd(context, s, dUj, x_i, dx_i); 1077b01ba163SJames Wright } 1078b01ba163SJames Wright 1079b01ba163SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 1080b01ba163SJames Wright KMStrainRate(grad_ds, dstrain_rate); 1081b01ba163SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 1082b01ba163SJames Wright KMUnpack(dkmstress, dstress); 1083b01ba163SJames Wright KMUnpack(kmstress, stress); 1084b01ba163SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 108504b9037bSJames Wright 1086e6b47afbSJames Wright StateConservative dF_inviscid[3]; 1087e6b47afbSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 108804b9037bSJames Wright 1089e6b47afbSJames Wright CeedScalar dFlux[5] = {0.}; 1090e6b47afbSJames Wright for (int j=0; j<3; j++) { 1091e6b47afbSJames Wright dFlux[0] += dF_inviscid[j].density * norm[j]; 1092e6b47afbSJames Wright for (int k=0; k<3; k++) 1093b01ba163SJames Wright dFlux[k+1] += (dF_inviscid[j].momentum[k] - dstress[k][j]) * norm[j]; 1094b01ba163SJames Wright dFlux[4] += (dF_inviscid[j].E_total + dFe[j]) * norm[j]; 1095e6b47afbSJames Wright } 1096e6b47afbSJames Wright 1097e6b47afbSJames Wright for (int j=0; j<5; j++) 1098e6b47afbSJames Wright v[j][i] = -wdetJb * dFlux[j]; 109904b9037bSJames Wright } // End Quadrature Point Loop 110004b9037bSJames Wright return 0; 110104b9037bSJames Wright } 110204b9037bSJames Wright 11033a8779fbSJames Wright // ***************************************************************************** 1104*cbe60e31SLeila Ghaffari // This QFunction implements the Navier-Stokes equations (mentioned above) in 1105*cbe60e31SLeila Ghaffari // primitive variables and with implicit time stepping method 1106*cbe60e31SLeila Ghaffari // 1107*cbe60e31SLeila Ghaffari // ***************************************************************************** 1108*cbe60e31SLeila Ghaffari CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, 1109*cbe60e31SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 1110*cbe60e31SLeila Ghaffari // *INDENT-OFF* 1111*cbe60e31SLeila Ghaffari // Inputs 1112*cbe60e31SLeila Ghaffari const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 1113*cbe60e31SLeila Ghaffari (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 1114*cbe60e31SLeila Ghaffari (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 1115*cbe60e31SLeila Ghaffari (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 1116*cbe60e31SLeila Ghaffari (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 1117*cbe60e31SLeila Ghaffari // Outputs 1118*cbe60e31SLeila Ghaffari CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 1119*cbe60e31SLeila Ghaffari (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1], 1120*cbe60e31SLeila Ghaffari (*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 1121*cbe60e31SLeila Ghaffari // *INDENT-ON* 1122*cbe60e31SLeila Ghaffari // Context 1123*cbe60e31SLeila Ghaffari NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 1124*cbe60e31SLeila Ghaffari const CeedScalar mu = context->mu; 1125*cbe60e31SLeila Ghaffari const CeedScalar cv = context->cv; 1126*cbe60e31SLeila Ghaffari const CeedScalar cp = context->cp; 1127*cbe60e31SLeila Ghaffari const CeedScalar *g = context->g; 1128*cbe60e31SLeila Ghaffari const CeedScalar dt = context->dt; 1129*cbe60e31SLeila Ghaffari const CeedScalar gamma = cp / cv; 1130*cbe60e31SLeila Ghaffari const CeedScalar Rd = cp - cv; 1131*cbe60e31SLeila Ghaffari 1132*cbe60e31SLeila Ghaffari CeedPragmaSIMD 1133*cbe60e31SLeila Ghaffari // Quadrature Point Loop 1134*cbe60e31SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 1135*cbe60e31SLeila Ghaffari CeedScalar Y[5]; 1136*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) Y[j] = q[j][i]; 1137*cbe60e31SLeila Ghaffari const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 1138*cbe60e31SLeila Ghaffari State s = StateFromY(context, Y, x_i); 1139*cbe60e31SLeila Ghaffari 1140*cbe60e31SLeila Ghaffari // -- Interp-to-Interp q_data 1141*cbe60e31SLeila Ghaffari const CeedScalar wdetJ = q_data[0][i]; 1142*cbe60e31SLeila Ghaffari // -- Interp-to-Grad q_data 1143*cbe60e31SLeila Ghaffari // ---- Inverse of change of coordinate matrix: X_i,j 1144*cbe60e31SLeila Ghaffari // *INDENT-OFF* 1145*cbe60e31SLeila Ghaffari const CeedScalar dXdx[3][3] = {{q_data[1][i], 1146*cbe60e31SLeila Ghaffari q_data[2][i], 1147*cbe60e31SLeila Ghaffari q_data[3][i]}, 1148*cbe60e31SLeila Ghaffari {q_data[4][i], 1149*cbe60e31SLeila Ghaffari q_data[5][i], 1150*cbe60e31SLeila Ghaffari q_data[6][i]}, 1151*cbe60e31SLeila Ghaffari {q_data[7][i], 1152*cbe60e31SLeila Ghaffari q_data[8][i], 1153*cbe60e31SLeila Ghaffari q_data[9][i]} 1154*cbe60e31SLeila Ghaffari }; 1155*cbe60e31SLeila Ghaffari // *INDENT-ON* 1156*cbe60e31SLeila Ghaffari State grad_s[3]; 1157*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 1158*cbe60e31SLeila Ghaffari CeedScalar dx_i[3] = {0}, dY[5]; 1159*cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) 1160*cbe60e31SLeila Ghaffari dY[k] = Grad_q[0][k][i] * dXdx[0][j] + 1161*cbe60e31SLeila Ghaffari Grad_q[1][k][i] * dXdx[1][j] + 1162*cbe60e31SLeila Ghaffari Grad_q[2][k][i] * dXdx[2][j]; 1163*cbe60e31SLeila Ghaffari dx_i[j] = 1.; 1164*cbe60e31SLeila Ghaffari grad_s[j] = StateFromY_fwd(context, s, dY, x_i, dx_i); 1165*cbe60e31SLeila Ghaffari } 1166*cbe60e31SLeila Ghaffari 1167*cbe60e31SLeila Ghaffari CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 1168*cbe60e31SLeila Ghaffari KMStrainRate(grad_s, strain_rate); 1169*cbe60e31SLeila Ghaffari NewtonianStress(context, strain_rate, kmstress); 1170*cbe60e31SLeila Ghaffari KMUnpack(kmstress, stress); 1171*cbe60e31SLeila Ghaffari ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 1172*cbe60e31SLeila Ghaffari 1173*cbe60e31SLeila Ghaffari StateConservative F_inviscid[3]; 1174*cbe60e31SLeila Ghaffari FluxInviscid(context, s, F_inviscid); 1175*cbe60e31SLeila Ghaffari 1176*cbe60e31SLeila Ghaffari // Total flux 1177*cbe60e31SLeila Ghaffari CeedScalar Flux[5][3]; 1178*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 1179*cbe60e31SLeila Ghaffari Flux[0][j] = F_inviscid[j].density; 1180*cbe60e31SLeila Ghaffari for (CeedInt k=0; k<3; k++) 1181*cbe60e31SLeila Ghaffari Flux[k+1][j] = F_inviscid[j].momentum[k] - stress[k][j]; 1182*cbe60e31SLeila Ghaffari Flux[4][j] = F_inviscid[j].E_total + Fe[j]; 1183*cbe60e31SLeila Ghaffari } 1184*cbe60e31SLeila Ghaffari 1185*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 1186*cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) { 1187*cbe60e31SLeila Ghaffari Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + 1188*cbe60e31SLeila Ghaffari dXdx[j][1] * Flux[k][1] + 1189*cbe60e31SLeila Ghaffari dXdx[j][2] * Flux[k][2]); 1190*cbe60e31SLeila Ghaffari } 1191*cbe60e31SLeila Ghaffari } 1192*cbe60e31SLeila Ghaffari 1193*cbe60e31SLeila Ghaffari const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 1194*cbe60e31SLeila Ghaffari 1195*cbe60e31SLeila Ghaffari CeedScalar Y_dot[5], dx0[3] = {0}; 1196*cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) Y_dot[j] = q_dot[j][i]; 1197*cbe60e31SLeila Ghaffari State s_dot = StateFromY_fwd(context, s, Y_dot, x_i, dx0); 1198*cbe60e31SLeila Ghaffari 1199*cbe60e31SLeila Ghaffari CeedScalar U_dot[5] = {0.}; 1200*cbe60e31SLeila Ghaffari U_dot[0] = s_dot.U.density; 1201*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1202*cbe60e31SLeila Ghaffari U_dot[j+1] = s_dot.U.momentum[j]; 1203*cbe60e31SLeila Ghaffari U_dot[4] = s_dot.U.E_total; 1204*cbe60e31SLeila Ghaffari 1205*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 1206*cbe60e31SLeila Ghaffari v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 1207*cbe60e31SLeila Ghaffari 1208*cbe60e31SLeila Ghaffari // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction 1209*cbe60e31SLeila Ghaffari CeedScalar jacob_F_conv[3][5][5] = {0}; 1210*cbe60e31SLeila Ghaffari computeFluxJacobian_NS(jacob_F_conv, s.U.density, s.Y.velocity, s.U.E_total, 1211*cbe60e31SLeila Ghaffari gamma, g, x_i); 1212*cbe60e31SLeila Ghaffari CeedScalar grad_U[5][3]; 1213*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 1214*cbe60e31SLeila Ghaffari grad_U[0][j] = grad_s[j].U.density; 1215*cbe60e31SLeila Ghaffari for (CeedInt k=0; k<3; k++) grad_U[k+1][j] = grad_s[j].U.momentum[k]; 1216*cbe60e31SLeila Ghaffari grad_U[4][j] = grad_s[j].U.E_total; 1217*cbe60e31SLeila Ghaffari } 1218*cbe60e31SLeila Ghaffari 1219*cbe60e31SLeila Ghaffari // strong_conv = dF/dq * dq/dx (Strong convection) 1220*cbe60e31SLeila Ghaffari CeedScalar strong_conv[5] = {0}; 1221*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1222*cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) 1223*cbe60e31SLeila Ghaffari for (CeedInt l=0; l<5; l++) 1224*cbe60e31SLeila Ghaffari strong_conv[k] += jacob_F_conv[j][k][l] * grad_U[l][j]; 1225*cbe60e31SLeila Ghaffari 1226*cbe60e31SLeila Ghaffari // Strong residual 1227*cbe60e31SLeila Ghaffari CeedScalar strong_res[5]; 1228*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 1229*cbe60e31SLeila Ghaffari strong_res[j] = U_dot[j] + strong_conv[j] - body_force[j]; 1230*cbe60e31SLeila Ghaffari 1231*cbe60e31SLeila Ghaffari // -- Stabilization method: none, SU, or SUPG 1232*cbe60e31SLeila Ghaffari CeedScalar stab[5][3] = {{0.}}; 1233*cbe60e31SLeila Ghaffari CeedScalar tau_strong_res[5] = {0.}, tau_strong_res_conservative[5] = {0}; 1234*cbe60e31SLeila Ghaffari CeedScalar tau_strong_conv[5] = {0.}, tau_strong_conv_conservative[5] = {0}; 1235*cbe60e31SLeila Ghaffari CeedScalar Tau_d[3] = {0.}; 1236*cbe60e31SLeila Ghaffari switch (context->stabilization) { 1237*cbe60e31SLeila Ghaffari case STAB_NONE: // Galerkin 1238*cbe60e31SLeila Ghaffari break; 1239*cbe60e31SLeila Ghaffari case STAB_SU: // SU 1240*cbe60e31SLeila Ghaffari Tau_diagPrim(Tau_d, dXdx, s.Y.velocity, cv, context, mu, dt, s.U.density); 1241*cbe60e31SLeila Ghaffari tau_strong_conv[0] = Tau_d[0] * strong_conv[0]; 1242*cbe60e31SLeila Ghaffari tau_strong_conv[1] = Tau_d[1] * strong_conv[1]; 1243*cbe60e31SLeila Ghaffari tau_strong_conv[2] = Tau_d[1] * strong_conv[2]; 1244*cbe60e31SLeila Ghaffari tau_strong_conv[3] = Tau_d[1] * strong_conv[3]; 1245*cbe60e31SLeila Ghaffari tau_strong_conv[4] = Tau_d[2] * strong_conv[4]; 1246*cbe60e31SLeila Ghaffari PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 1247*cbe60e31SLeila Ghaffari tau_strong_conv, tau_strong_conv_conservative); 1248*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1249*cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) 1250*cbe60e31SLeila Ghaffari for (CeedInt l=0; l<5; l++) 1251*cbe60e31SLeila Ghaffari stab[k][j] += jacob_F_conv[j][k][l] * tau_strong_conv_conservative[l]; 1252*cbe60e31SLeila Ghaffari 1253*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 1254*cbe60e31SLeila Ghaffari for (CeedInt k=0; k<3; k++) 1255*cbe60e31SLeila Ghaffari Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 1256*cbe60e31SLeila Ghaffari stab[j][1] * dXdx[k][1] + 1257*cbe60e31SLeila Ghaffari stab[j][2] * dXdx[k][2]); 1258*cbe60e31SLeila Ghaffari 1259*cbe60e31SLeila Ghaffari break; 1260*cbe60e31SLeila Ghaffari case STAB_SUPG: // SUPG 1261*cbe60e31SLeila Ghaffari Tau_diagPrim(Tau_d, dXdx, s.Y.velocity, cv, context, mu, dt, s.U.density); 1262*cbe60e31SLeila Ghaffari tau_strong_res[0] = Tau_d[0] * strong_res[0]; 1263*cbe60e31SLeila Ghaffari tau_strong_res[1] = Tau_d[1] * strong_res[1]; 1264*cbe60e31SLeila Ghaffari tau_strong_res[2] = Tau_d[1] * strong_res[2]; 1265*cbe60e31SLeila Ghaffari tau_strong_res[3] = Tau_d[1] * strong_res[3]; 1266*cbe60e31SLeila Ghaffari tau_strong_res[4] = Tau_d[2] * strong_res[4]; 1267*cbe60e31SLeila Ghaffari 1268*cbe60e31SLeila Ghaffari PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 1269*cbe60e31SLeila Ghaffari tau_strong_res, tau_strong_res_conservative); 1270*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1271*cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) 1272*cbe60e31SLeila Ghaffari for (CeedInt l=0; l<5; l++) 1273*cbe60e31SLeila Ghaffari stab[k][j] += jacob_F_conv[j][k][l] * tau_strong_res_conservative[l]; 1274*cbe60e31SLeila Ghaffari 1275*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 1276*cbe60e31SLeila Ghaffari for (CeedInt k=0; k<3; k++) 1277*cbe60e31SLeila Ghaffari Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 1278*cbe60e31SLeila Ghaffari stab[j][1] * dXdx[k][1] + 1279*cbe60e31SLeila Ghaffari stab[j][2] * dXdx[k][2]); 1280*cbe60e31SLeila Ghaffari break; 1281*cbe60e31SLeila Ghaffari } 1282*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) jac_data[j][i] = Y[j]; 1283*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<6; j++) jac_data[5+j][i] = kmstress[j]; 1284*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) jac_data[5+6+j][i] = Tau_d[j]; 1285*cbe60e31SLeila Ghaffari 1286*cbe60e31SLeila Ghaffari } // End Quadrature Point Loop 1287*cbe60e31SLeila Ghaffari 1288*cbe60e31SLeila Ghaffari // Return 1289*cbe60e31SLeila Ghaffari return 0; 1290*cbe60e31SLeila Ghaffari } 1291*cbe60e31SLeila Ghaffari 1292*cbe60e31SLeila Ghaffari // ***************************************************************************** 1293*cbe60e31SLeila Ghaffari // This QFunction implements the jacobean of the Navier-Stokes equations 1294*cbe60e31SLeila Ghaffari // in primitive variables for implicit time stepping method. 1295*cbe60e31SLeila Ghaffari // 1296*cbe60e31SLeila Ghaffari // ***************************************************************************** 1297*cbe60e31SLeila Ghaffari CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, 1298*cbe60e31SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 1299*cbe60e31SLeila Ghaffari // *INDENT-OFF* 1300*cbe60e31SLeila Ghaffari // Inputs 1301*cbe60e31SLeila Ghaffari const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 1302*cbe60e31SLeila Ghaffari (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 1303*cbe60e31SLeila Ghaffari (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 1304*cbe60e31SLeila Ghaffari (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 1305*cbe60e31SLeila Ghaffari (*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 1306*cbe60e31SLeila Ghaffari // Outputs 1307*cbe60e31SLeila Ghaffari CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 1308*cbe60e31SLeila Ghaffari (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 1309*cbe60e31SLeila Ghaffari // *INDENT-ON* 1310*cbe60e31SLeila Ghaffari // Context 1311*cbe60e31SLeila Ghaffari NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 1312*cbe60e31SLeila Ghaffari const CeedScalar *g = context->g; 1313*cbe60e31SLeila Ghaffari const CeedScalar cp = context->cp; 1314*cbe60e31SLeila Ghaffari const CeedScalar cv = context->cv; 1315*cbe60e31SLeila Ghaffari const CeedScalar Rd = cp - cv; 1316*cbe60e31SLeila Ghaffari const CeedScalar gamma = cp / cv; 1317*cbe60e31SLeila Ghaffari 1318*cbe60e31SLeila Ghaffari CeedPragmaSIMD 1319*cbe60e31SLeila Ghaffari // Quadrature Point Loop 1320*cbe60e31SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 1321*cbe60e31SLeila Ghaffari // -- Interp-to-Interp q_data 1322*cbe60e31SLeila Ghaffari const CeedScalar wdetJ = q_data[0][i]; 1323*cbe60e31SLeila Ghaffari // -- Interp-to-Grad q_data 1324*cbe60e31SLeila Ghaffari // ---- Inverse of change of coordinate matrix: X_i,j 1325*cbe60e31SLeila Ghaffari // *INDENT-OFF* 1326*cbe60e31SLeila Ghaffari const CeedScalar dXdx[3][3] = {{q_data[1][i], 1327*cbe60e31SLeila Ghaffari q_data[2][i], 1328*cbe60e31SLeila Ghaffari q_data[3][i]}, 1329*cbe60e31SLeila Ghaffari {q_data[4][i], 1330*cbe60e31SLeila Ghaffari q_data[5][i], 1331*cbe60e31SLeila Ghaffari q_data[6][i]}, 1332*cbe60e31SLeila Ghaffari {q_data[7][i], 1333*cbe60e31SLeila Ghaffari q_data[8][i], 1334*cbe60e31SLeila Ghaffari q_data[9][i]} 1335*cbe60e31SLeila Ghaffari }; 1336*cbe60e31SLeila Ghaffari // *INDENT-ON* 1337*cbe60e31SLeila Ghaffari 1338*cbe60e31SLeila Ghaffari CeedScalar Y[5], kmstress[6], Tau_d[3] __attribute((unused)); 1339*cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) Y[j] = jac_data[j][i]; 1340*cbe60e31SLeila Ghaffari for (int j=0; j<6; j++) kmstress[j] = jac_data[5+j][i]; 1341*cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) Tau_d[j] = jac_data[5+6+j][i]; 1342*cbe60e31SLeila Ghaffari const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 1343*cbe60e31SLeila Ghaffari State s = StateFromY(context, Y, x_i); 1344*cbe60e31SLeila Ghaffari 1345*cbe60e31SLeila Ghaffari CeedScalar dY[5], dx0[3] = {0}; 1346*cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) dY[j] = dq[j][i]; 1347*cbe60e31SLeila Ghaffari State ds = StateFromY_fwd(context, s, dY, x_i, dx0); 1348*cbe60e31SLeila Ghaffari 1349*cbe60e31SLeila Ghaffari State grad_ds[3]; 1350*cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) { 1351*cbe60e31SLeila Ghaffari CeedScalar dYj[5]; 1352*cbe60e31SLeila Ghaffari for (int k=0; k<5; k++) 1353*cbe60e31SLeila Ghaffari dYj[k] = Grad_dq[0][k][i] * dXdx[0][j] + 1354*cbe60e31SLeila Ghaffari Grad_dq[1][k][i] * dXdx[1][j] + 1355*cbe60e31SLeila Ghaffari Grad_dq[2][k][i] * dXdx[2][j]; 1356*cbe60e31SLeila Ghaffari grad_ds[j] = StateFromY_fwd(context, s, dYj, x_i, dx0); 1357*cbe60e31SLeila Ghaffari } 1358*cbe60e31SLeila Ghaffari 1359*cbe60e31SLeila Ghaffari CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 1360*cbe60e31SLeila Ghaffari KMStrainRate(grad_ds, dstrain_rate); 1361*cbe60e31SLeila Ghaffari NewtonianStress(context, dstrain_rate, dkmstress); 1362*cbe60e31SLeila Ghaffari KMUnpack(dkmstress, dstress); 1363*cbe60e31SLeila Ghaffari KMUnpack(kmstress, stress); 1364*cbe60e31SLeila Ghaffari ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 1365*cbe60e31SLeila Ghaffari 1366*cbe60e31SLeila Ghaffari StateConservative dF_inviscid[3]; 1367*cbe60e31SLeila Ghaffari FluxInviscid_fwd(context, s, ds, dF_inviscid); 1368*cbe60e31SLeila Ghaffari 1369*cbe60e31SLeila Ghaffari // Total flux 1370*cbe60e31SLeila Ghaffari CeedScalar dFlux[5][3]; 1371*cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) { 1372*cbe60e31SLeila Ghaffari dFlux[0][j] = dF_inviscid[j].density; 1373*cbe60e31SLeila Ghaffari for (int k=0; k<3; k++) 1374*cbe60e31SLeila Ghaffari dFlux[k+1][j] = dF_inviscid[j].momentum[k] - dstress[k][j]; 1375*cbe60e31SLeila Ghaffari dFlux[4][j] = dF_inviscid[j].E_total + dFe[j]; 1376*cbe60e31SLeila Ghaffari } 1377*cbe60e31SLeila Ghaffari 1378*cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) { 1379*cbe60e31SLeila Ghaffari for (int k=0; k<5; k++) { 1380*cbe60e31SLeila Ghaffari Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + 1381*cbe60e31SLeila Ghaffari dXdx[j][1] * dFlux[k][1] + 1382*cbe60e31SLeila Ghaffari dXdx[j][2] * dFlux[k][2]); 1383*cbe60e31SLeila Ghaffari } 1384*cbe60e31SLeila Ghaffari } 1385*cbe60e31SLeila Ghaffari 1386*cbe60e31SLeila Ghaffari const CeedScalar dbody_force[5] = {0, 1387*cbe60e31SLeila Ghaffari ds.U.density *g[0], 1388*cbe60e31SLeila Ghaffari ds.U.density *g[1], 1389*cbe60e31SLeila Ghaffari ds.U.density *g[2], 1390*cbe60e31SLeila Ghaffari 0 1391*cbe60e31SLeila Ghaffari }; 1392*cbe60e31SLeila Ghaffari CeedScalar dU[5] = {0.}; 1393*cbe60e31SLeila Ghaffari dU[0] = ds.U.density; 1394*cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1395*cbe60e31SLeila Ghaffari dU[j+1] = ds.U.momentum[j]; 1396*cbe60e31SLeila Ghaffari dU[4] = ds.U.E_total; 1397*cbe60e31SLeila Ghaffari 1398*cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) 1399*cbe60e31SLeila Ghaffari v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 1400*cbe60e31SLeila Ghaffari 1401*cbe60e31SLeila Ghaffari if (1) { 1402*cbe60e31SLeila Ghaffari CeedScalar jacob_F_conv[3][5][5] = {0}; 1403*cbe60e31SLeila Ghaffari computeFluxJacobian_NS(jacob_F_conv, s.U.density, s.Y.velocity, s.U.E_total, 1404*cbe60e31SLeila Ghaffari gamma, g, x_i); 1405*cbe60e31SLeila Ghaffari CeedScalar grad_dU[5][3]; 1406*cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) { 1407*cbe60e31SLeila Ghaffari grad_dU[0][j] = grad_ds[j].U.density; 1408*cbe60e31SLeila Ghaffari for (int k=0; k<3; k++) grad_dU[k+1][j] = grad_ds[j].U.momentum[k]; 1409*cbe60e31SLeila Ghaffari grad_dU[4][j] = grad_ds[j].U.E_total; 1410*cbe60e31SLeila Ghaffari } 1411*cbe60e31SLeila Ghaffari CeedScalar dstrong_conv[5] = {0.}; 1412*cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) 1413*cbe60e31SLeila Ghaffari for (int k=0; k<5; k++) 1414*cbe60e31SLeila Ghaffari for (int l=0; l<5; l++) 1415*cbe60e31SLeila Ghaffari dstrong_conv[k] += jacob_F_conv[j][k][l] * grad_dU[l][j]; 1416*cbe60e31SLeila Ghaffari 1417*cbe60e31SLeila Ghaffari CeedScalar dstrong_res[5]; 1418*cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) 1419*cbe60e31SLeila Ghaffari dstrong_res[j] = context->ijacobian_time_shift * dU[j] + 1420*cbe60e31SLeila Ghaffari dstrong_conv[j] - 1421*cbe60e31SLeila Ghaffari dbody_force[j]; 1422*cbe60e31SLeila Ghaffari 1423*cbe60e31SLeila Ghaffari CeedScalar dtau_strong_res[5] = {0.}, 1424*cbe60e31SLeila Ghaffari dtau_strong_res_conservative[5] = {0.}; 1425*cbe60e31SLeila Ghaffari dtau_strong_res[0] = Tau_d[0] * dstrong_res[0]; 1426*cbe60e31SLeila Ghaffari dtau_strong_res[1] = Tau_d[1] * dstrong_res[1]; 1427*cbe60e31SLeila Ghaffari dtau_strong_res[2] = Tau_d[1] * dstrong_res[2]; 1428*cbe60e31SLeila Ghaffari dtau_strong_res[3] = Tau_d[1] * dstrong_res[3]; 1429*cbe60e31SLeila Ghaffari dtau_strong_res[4] = Tau_d[2] * dstrong_res[4]; 1430*cbe60e31SLeila Ghaffari PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 1431*cbe60e31SLeila Ghaffari dtau_strong_res, dtau_strong_res_conservative); 1432*cbe60e31SLeila Ghaffari CeedScalar dstab[5][3] = {0}; 1433*cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) 1434*cbe60e31SLeila Ghaffari for (int k=0; k<5; k++) 1435*cbe60e31SLeila Ghaffari for (int l=0; l<5; l++) 1436*cbe60e31SLeila Ghaffari dstab[k][j] += jacob_F_conv[j][k][l] * dtau_strong_res_conservative[l]; 1437*cbe60e31SLeila Ghaffari 1438*cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) 1439*cbe60e31SLeila Ghaffari for (int k=0; k<3; k++) 1440*cbe60e31SLeila Ghaffari Grad_v[k][j][i] += wdetJ*(dstab[j][0] * dXdx[k][0] + 1441*cbe60e31SLeila Ghaffari dstab[j][1] * dXdx[k][1] + 1442*cbe60e31SLeila Ghaffari dstab[j][2] * dXdx[k][2]); 1443*cbe60e31SLeila Ghaffari 1444*cbe60e31SLeila Ghaffari } 1445*cbe60e31SLeila Ghaffari } // End Quadrature Point Loop 1446*cbe60e31SLeila Ghaffari return 0; 1447*cbe60e31SLeila Ghaffari } 1448*cbe60e31SLeila Ghaffari // ***************************************************************************** 1449*cbe60e31SLeila Ghaffari 14503a8779fbSJames Wright #endif // newtonian_h 1451