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 // ***************************************************************************** 226cbe60e31SLeila Ghaffari // This QFunction sets a "still" initial condition for generic Newtonian IG 227cbe60e31SLeila Ghaffari // problems in primitive variables 228cbe60e31SLeila Ghaffari // ***************************************************************************** 229cbe60e31SLeila Ghaffari CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, 230cbe60e31SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 231cbe60e31SLeila Ghaffari // Outputs 232cbe60e31SLeila Ghaffari CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 233cbe60e31SLeila Ghaffari 234cbe60e31SLeila Ghaffari // Context 235cbe60e31SLeila Ghaffari const SetupContext context = (SetupContext)ctx; 236cbe60e31SLeila Ghaffari const CeedScalar theta0 = context->theta0; 237cbe60e31SLeila Ghaffari const CeedScalar P0 = context->P0; 238cbe60e31SLeila Ghaffari 239cbe60e31SLeila Ghaffari // Quadrature Point Loop 240cbe60e31SLeila Ghaffari CeedPragmaSIMD 241cbe60e31SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 242cbe60e31SLeila Ghaffari CeedScalar q[5] = {0.}; 243cbe60e31SLeila Ghaffari 244cbe60e31SLeila Ghaffari // Initial Conditions 245cbe60e31SLeila Ghaffari q[0] = P0; 246cbe60e31SLeila Ghaffari q[1] = 0.0; 247cbe60e31SLeila Ghaffari q[2] = 0.0; 248cbe60e31SLeila Ghaffari q[3] = 0.0; 249cbe60e31SLeila Ghaffari q[4] = theta0; 250cbe60e31SLeila Ghaffari 251cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 252cbe60e31SLeila Ghaffari q0[j][i] = q[j]; 253cbe60e31SLeila Ghaffari 254cbe60e31SLeila Ghaffari } // End of Quadrature Point Loop 255cbe60e31SLeila Ghaffari return 0; 256cbe60e31SLeila Ghaffari } 257cbe60e31SLeila Ghaffari 258cbe60e31SLeila 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, 461cbe60e31SLeila 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]; 609cbe60e31SLeila 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 634cbe60e31SLeila Ghaffari // ***************************************************************************** 635cbe60e31SLeila Ghaffari // This QFunction implements the jacobean of the Navier-Stokes equations 636cbe60e31SLeila Ghaffari // for implicit time stepping method. 637cbe60e31SLeila Ghaffari // 638cbe60e31SLeila 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 x_i[3] = {x[0][i], x[1][i], x[2][i]}; 797*3934e2b1SJames Wright const CeedScalar solution_state[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 798*3934e2b1SJames Wright State s = context->is_primitive ? StateFromY(context, solution_state, x_i) 799*3934e2b1SJames Wright : StateFromU(context, solution_state, x_i); 8008085925cSJames Wright 8018085925cSJames Wright const CeedScalar wdetJb = (is_implicit ? -1. : 1.) * q_data_sur[0][i]; 8028085925cSJames Wright // ---- Normal vect 8038085925cSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 8048085925cSJames Wright q_data_sur[2][i], 8058085925cSJames Wright q_data_sur[3][i] 8068085925cSJames Wright }; 8078085925cSJames Wright 808d3b25f3aSJames Wright const CeedScalar dXdx[2][3] = { 809d3b25f3aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 810d3b25f3aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 811d3b25f3aSJames Wright }; 8128085925cSJames Wright 813d3b25f3aSJames Wright State grad_s[3]; 814d3b25f3aSJames Wright for (CeedInt j=0; j<3; j++) { 815d3b25f3aSJames Wright CeedScalar dx_i[3] = {0}, dU[5]; 816d3b25f3aSJames Wright for (CeedInt k=0; k<5; k++) 817d3b25f3aSJames Wright dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 818d3b25f3aSJames Wright Grad_q[1][k][i] * dXdx[1][j]; 819d3b25f3aSJames Wright dx_i[j] = 1.; 820d3b25f3aSJames Wright grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 821d3b25f3aSJames Wright } 8228085925cSJames Wright 823d3b25f3aSJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 824d3b25f3aSJames Wright KMStrainRate(grad_s, strain_rate); 825d3b25f3aSJames Wright NewtonianStress(context, strain_rate, kmstress); 826d3b25f3aSJames Wright KMUnpack(kmstress, stress); 827d3b25f3aSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 828d3b25f3aSJames Wright 829d3b25f3aSJames Wright StateConservative F_inviscid[3]; 830d3b25f3aSJames Wright FluxInviscid(context, s, F_inviscid); 831d3b25f3aSJames Wright 832d3b25f3aSJames Wright CeedScalar Flux[5] = {0.}; 833d3b25f3aSJames Wright for (int j=0; j<3; j++) { 834d3b25f3aSJames Wright Flux[0] += F_inviscid[j].density * norm[j]; 835d3b25f3aSJames Wright for (int k=0; k<3; k++) 836d3b25f3aSJames Wright Flux[k+1] += (F_inviscid[j].momentum[k] - stress[k][j]) * norm[j]; 837d3b25f3aSJames Wright Flux[4] += (F_inviscid[j].E_total + Fe[j])*norm[j]; 838d3b25f3aSJames Wright } 839d3b25f3aSJames Wright 8408085925cSJames Wright // -- Density 841d3b25f3aSJames Wright v[0][i] = -wdetJb * Flux[0]; 8428085925cSJames Wright 8438085925cSJames Wright // -- Momentum 8448085925cSJames Wright for (CeedInt j=0; j<3; j++) 845d3b25f3aSJames Wright v[j+1][i] = -wdetJb * Flux[j+1]; 8468085925cSJames Wright 8478085925cSJames Wright // -- Total Energy Density 848d3b25f3aSJames Wright v[4][i] = -wdetJb * Flux[4]; 84968ae065aSJames Wright 850*3934e2b1SJames Wright if (context->is_primitive) { 851*3934e2b1SJames Wright jac_data_sur[0][i] = s.Y.pressure; 852*3934e2b1SJames Wright for (int j=0; j<3; j++) jac_data_sur[j+1][i] = s.Y.velocity[j]; 853*3934e2b1SJames Wright jac_data_sur[4][i] = s.Y.temperature; 854*3934e2b1SJames Wright } else { 85568ae065aSJames Wright jac_data_sur[0][i] = s.U.density; 856*3934e2b1SJames Wright for (int j=0; j<3; j++) jac_data_sur[j+1][i] = s.U.momentum[j]; 85768ae065aSJames Wright jac_data_sur[4][i] = s.U.E_total; 858*3934e2b1SJames Wright } 85968ae065aSJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 8608085925cSJames Wright } 8618085925cSJames Wright return 0; 8628085925cSJames Wright } 8638085925cSJames Wright 86468ae065aSJames Wright // Jacobian for "set nothing" boundary integral 86568ae065aSJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian)(void *ctx, CeedInt Q, 86668ae065aSJames Wright const CeedScalar *const *in, 86768ae065aSJames Wright CeedScalar *const *out) { 86868ae065aSJames Wright // *INDENT-OFF* 86968ae065aSJames Wright // Inputs 87068ae065aSJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 87168ae065aSJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 87268ae065aSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 87368ae065aSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 87468ae065aSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 87568ae065aSJames Wright // Outputs 87668ae065aSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 87768ae065aSJames Wright // *INDENT-ON* 87868ae065aSJames Wright 87968ae065aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 88068ae065aSJames Wright const bool implicit = context->is_implicit; 88168ae065aSJames Wright 88268ae065aSJames Wright CeedPragmaSIMD 88368ae065aSJames Wright // Quadrature Point Loop 88468ae065aSJames Wright for (CeedInt i=0; i<Q; i++) { 88568ae065aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 88668ae065aSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 88768ae065aSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 88868ae065aSJames Wright q_data_sur[2][i], 88968ae065aSJames Wright q_data_sur[3][i] 89068ae065aSJames Wright }; 89168ae065aSJames Wright const CeedScalar dXdx[2][3] = { 89268ae065aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 89368ae065aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 89468ae065aSJames Wright }; 89568ae065aSJames Wright 896*3934e2b1SJames Wright CeedScalar state[5], kmstress[6], dstate[5], dx_i[3] = {0.}; 897*3934e2b1SJames Wright for (int j=0; j<5; j++) state[j] = jac_data_sur[j][i]; 89868ae065aSJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 899*3934e2b1SJames Wright for (int j=0; j<5; j++) dstate[j] = dq[j][i]; 900*3934e2b1SJames Wright 901*3934e2b1SJames Wright State s, ds; 902*3934e2b1SJames Wright if (context->is_primitive) { 903*3934e2b1SJames Wright s = StateFromY(context, state, x_i); 904*3934e2b1SJames Wright ds = StateFromY_fwd(context, s, dstate, x_i, dx_i); 905*3934e2b1SJames Wright } else { 906*3934e2b1SJames Wright s = StateFromU(context, state, x_i); 907*3934e2b1SJames Wright ds = StateFromU_fwd(context, s, dstate, x_i, dx_i); 908*3934e2b1SJames Wright } 90968ae065aSJames Wright 91068ae065aSJames Wright State grad_ds[3]; 91168ae065aSJames Wright for (CeedInt j=0; j<3; j++) { 91268ae065aSJames Wright CeedScalar dx_i[3] = {0}, dUj[5]; 91368ae065aSJames Wright for (CeedInt k=0; k<5; k++) 91468ae065aSJames Wright dUj[k] = Grad_dq[0][k][i] * dXdx[0][j] + 91568ae065aSJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 91668ae065aSJames Wright dx_i[j] = 1.; 91768ae065aSJames Wright grad_ds[j] = StateFromU_fwd(context, s, dUj, x_i, dx_i); 91868ae065aSJames Wright } 91968ae065aSJames Wright 92068ae065aSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 92168ae065aSJames Wright KMStrainRate(grad_ds, dstrain_rate); 92268ae065aSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 92368ae065aSJames Wright KMUnpack(dkmstress, dstress); 92468ae065aSJames Wright KMUnpack(kmstress, stress); 92568ae065aSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 92668ae065aSJames Wright 92768ae065aSJames Wright StateConservative dF_inviscid[3]; 92868ae065aSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 92968ae065aSJames Wright 93068ae065aSJames Wright CeedScalar dFlux[5] = {0.}; 93168ae065aSJames Wright for (int j=0; j<3; j++) { 93268ae065aSJames Wright dFlux[0] += dF_inviscid[j].density * norm[j]; 93368ae065aSJames Wright for (int k=0; k<3; k++) 93468ae065aSJames Wright dFlux[k+1] += (dF_inviscid[j].momentum[k] - dstress[k][j]) * norm[j]; 93568ae065aSJames Wright dFlux[4] += (dF_inviscid[j].E_total + dFe[j]) * norm[j]; 93668ae065aSJames Wright } 93768ae065aSJames Wright 93868ae065aSJames Wright for (int j=0; j<5; j++) 93968ae065aSJames Wright v[j][i] = -wdetJb * dFlux[j]; 94068ae065aSJames Wright } // End Quadrature Point Loop 94168ae065aSJames Wright return 0; 94268ae065aSJames Wright } 94368ae065aSJames Wright 94404b9037bSJames Wright // Outflow boundary condition, weakly setting a constant pressure 94504b9037bSJames Wright CEED_QFUNCTION(PressureOutflow)(void *ctx, CeedInt Q, 94604b9037bSJames Wright const CeedScalar *const *in, 94704b9037bSJames Wright CeedScalar *const *out) { 94804b9037bSJames Wright // *INDENT-OFF* 94904b9037bSJames Wright // Inputs 95004b9037bSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 95125bfcc41SJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 95225bfcc41SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 95325bfcc41SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 95404b9037bSJames Wright // Outputs 95504b9037bSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 95604b9037bSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 95704b9037bSJames Wright // *INDENT-ON* 95804b9037bSJames Wright 95904b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 96004b9037bSJames Wright const bool implicit = context->is_implicit; 96104b9037bSJames Wright const CeedScalar P0 = context->P0; 96204b9037bSJames Wright 96304b9037bSJames Wright CeedPragmaSIMD 96404b9037bSJames Wright // Quadrature Point Loop 96504b9037bSJames Wright for (CeedInt i=0; i<Q; i++) { 96604b9037bSJames Wright // Setup 96704b9037bSJames Wright // -- Interp in 96825bfcc41SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 969*3934e2b1SJames Wright const CeedScalar solution_state[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 970*3934e2b1SJames Wright State s = context->is_primitive ? StateFromY(context, solution_state, x_i) 971*3934e2b1SJames Wright : StateFromU(context, solution_state, x_i); 97225bfcc41SJames Wright s.Y.pressure = P0; 97304b9037bSJames Wright 97404b9037bSJames Wright // -- Interp-to-Interp q_data 97504b9037bSJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 97604b9037bSJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 97704b9037bSJames Wright // We can effect this by swapping the sign on this weight 97804b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 97904b9037bSJames Wright 98004b9037bSJames Wright // ---- Normal vect 98104b9037bSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 98204b9037bSJames Wright q_data_sur[2][i], 98304b9037bSJames Wright q_data_sur[3][i] 98404b9037bSJames Wright }; 98504b9037bSJames Wright 98625bfcc41SJames Wright const CeedScalar dXdx[2][3] = { 98725bfcc41SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 98825bfcc41SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 98925bfcc41SJames Wright }; 99004b9037bSJames Wright 99125bfcc41SJames Wright State grad_s[3]; 99225bfcc41SJames Wright for (CeedInt j=0; j<3; j++) { 99325bfcc41SJames Wright CeedScalar dx_i[3] = {0}, dU[5]; 99425bfcc41SJames Wright for (CeedInt k=0; k<5; k++) 99525bfcc41SJames Wright dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 99625bfcc41SJames Wright Grad_q[1][k][i] * dXdx[1][j]; 99725bfcc41SJames Wright dx_i[j] = 1.; 99825bfcc41SJames Wright grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 99925bfcc41SJames Wright } 100025bfcc41SJames Wright 100125bfcc41SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 100225bfcc41SJames Wright KMStrainRate(grad_s, strain_rate); 100325bfcc41SJames Wright NewtonianStress(context, strain_rate, kmstress); 100425bfcc41SJames Wright KMUnpack(kmstress, stress); 100525bfcc41SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 100625bfcc41SJames Wright 100725bfcc41SJames Wright StateConservative F_inviscid[3]; 100825bfcc41SJames Wright FluxInviscid(context, s, F_inviscid); 100925bfcc41SJames Wright 101025bfcc41SJames Wright CeedScalar Flux[5] = {0.}; 101125bfcc41SJames Wright for (int j=0; j<3; j++) { 101225bfcc41SJames Wright Flux[0] += F_inviscid[j].density * norm[j]; 101325bfcc41SJames Wright for (int k=0; k<3; k++) 101425bfcc41SJames Wright Flux[k+1] += (F_inviscid[j].momentum[k] - stress[k][j]) * norm[j]; 101525bfcc41SJames Wright Flux[4] += (F_inviscid[j].E_total + Fe[j])*norm[j]; 101625bfcc41SJames Wright } 101704b9037bSJames Wright 101804b9037bSJames Wright // -- Density 101925bfcc41SJames Wright v[0][i] = -wdetJb * Flux[0]; 102004b9037bSJames Wright 102104b9037bSJames Wright // -- Momentum 102204b9037bSJames Wright for (CeedInt j=0; j<3; j++) 102325bfcc41SJames Wright v[j+1][i] = -wdetJb * Flux[j+1]; 102404b9037bSJames Wright 102504b9037bSJames Wright // -- Total Energy Density 102625bfcc41SJames Wright v[4][i] = -wdetJb * Flux[4]; 102704b9037bSJames Wright 102804b9037bSJames Wright // Save values for Jacobian 1029*3934e2b1SJames Wright if (context->is_primitive) { 1030*3934e2b1SJames Wright jac_data_sur[0][i] = s.Y.pressure; 1031*3934e2b1SJames Wright for (int j=0; j<3; j++) jac_data_sur[j+1][i] = s.Y.velocity[j]; 1032*3934e2b1SJames Wright jac_data_sur[4][i] = s.Y.temperature; 1033*3934e2b1SJames Wright } else { 103425bfcc41SJames Wright jac_data_sur[0][i] = s.U.density; 1035*3934e2b1SJames Wright for (int j=0; j<3; j++) jac_data_sur[j+1][i] = s.U.momentum[j]; 103625bfcc41SJames Wright jac_data_sur[4][i] = s.U.E_total; 1037*3934e2b1SJames Wright } 1038b01ba163SJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 103904b9037bSJames Wright } // End Quadrature Point Loop 104004b9037bSJames Wright return 0; 104104b9037bSJames Wright } 104204b9037bSJames Wright 104304b9037bSJames Wright // Jacobian for weak-pressure outflow boundary condition 104404b9037bSJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian)(void *ctx, CeedInt Q, 104504b9037bSJames Wright const CeedScalar *const *in, 104604b9037bSJames Wright CeedScalar *const *out) { 104704b9037bSJames Wright // *INDENT-OFF* 104804b9037bSJames Wright // Inputs 104904b9037bSJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 1050b01ba163SJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 1051b01ba163SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 1052b01ba163SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 1053b01ba163SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 105404b9037bSJames Wright // Outputs 105504b9037bSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 105604b9037bSJames Wright // *INDENT-ON* 105704b9037bSJames Wright 105804b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 105904b9037bSJames Wright const bool implicit = context->is_implicit; 106004b9037bSJames Wright 106104b9037bSJames Wright CeedPragmaSIMD 106204b9037bSJames Wright // Quadrature Point Loop 106304b9037bSJames Wright for (CeedInt i=0; i<Q; i++) { 1064b01ba163SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 106504b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 106604b9037bSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 106704b9037bSJames Wright q_data_sur[2][i], 106804b9037bSJames Wright q_data_sur[3][i] 106904b9037bSJames Wright }; 1070b01ba163SJames Wright const CeedScalar dXdx[2][3] = { 1071b01ba163SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 1072b01ba163SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 1073b01ba163SJames Wright }; 1074b01ba163SJames Wright 1075*3934e2b1SJames Wright CeedScalar state[5], kmstress[6], dstate[5], dx_i[3] = {0.}; 1076*3934e2b1SJames Wright for (int j=0; j<5; j++) state[j] = jac_data_sur[j][i]; 1077b01ba163SJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 1078*3934e2b1SJames Wright for (int j=0; j<5; j++) dstate[j] = dq[j][i]; 1079*3934e2b1SJames Wright 1080*3934e2b1SJames Wright State s, ds; 1081*3934e2b1SJames Wright if (context->is_primitive) { 1082*3934e2b1SJames Wright s = StateFromY(context, state, x_i); 1083*3934e2b1SJames Wright ds = StateFromY_fwd(context, s, dstate, x_i, dx_i); 1084*3934e2b1SJames Wright } else { 1085*3934e2b1SJames Wright s = StateFromU(context, state, x_i); 1086*3934e2b1SJames Wright ds = StateFromU_fwd(context, s, dstate, x_i, dx_i); 1087*3934e2b1SJames Wright } 1088b01ba163SJames Wright s.Y.pressure = context->P0; 1089b01ba163SJames Wright ds.Y.pressure = 0.; 1090b01ba163SJames Wright 1091b01ba163SJames Wright State grad_ds[3]; 1092b01ba163SJames Wright for (CeedInt j=0; j<3; j++) { 1093b01ba163SJames Wright CeedScalar dx_i[3] = {0}, dUj[5]; 1094b01ba163SJames Wright for (CeedInt k=0; k<5; k++) 1095b01ba163SJames Wright dUj[k] = Grad_dq[0][k][i] * dXdx[0][j] + 1096b01ba163SJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 1097b01ba163SJames Wright dx_i[j] = 1.; 1098b01ba163SJames Wright grad_ds[j] = StateFromU_fwd(context, s, dUj, x_i, dx_i); 1099b01ba163SJames Wright } 1100b01ba163SJames Wright 1101b01ba163SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 1102b01ba163SJames Wright KMStrainRate(grad_ds, dstrain_rate); 1103b01ba163SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 1104b01ba163SJames Wright KMUnpack(dkmstress, dstress); 1105b01ba163SJames Wright KMUnpack(kmstress, stress); 1106b01ba163SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 110704b9037bSJames Wright 1108e6b47afbSJames Wright StateConservative dF_inviscid[3]; 1109e6b47afbSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 111004b9037bSJames Wright 1111e6b47afbSJames Wright CeedScalar dFlux[5] = {0.}; 1112e6b47afbSJames Wright for (int j=0; j<3; j++) { 1113e6b47afbSJames Wright dFlux[0] += dF_inviscid[j].density * norm[j]; 1114e6b47afbSJames Wright for (int k=0; k<3; k++) 1115b01ba163SJames Wright dFlux[k+1] += (dF_inviscid[j].momentum[k] - dstress[k][j]) * norm[j]; 1116b01ba163SJames Wright dFlux[4] += (dF_inviscid[j].E_total + dFe[j]) * norm[j]; 1117e6b47afbSJames Wright } 1118e6b47afbSJames Wright 1119e6b47afbSJames Wright for (int j=0; j<5; j++) 1120e6b47afbSJames Wright v[j][i] = -wdetJb * dFlux[j]; 112104b9037bSJames Wright } // End Quadrature Point Loop 112204b9037bSJames Wright return 0; 112304b9037bSJames Wright } 112404b9037bSJames Wright 11253a8779fbSJames Wright // ***************************************************************************** 1126cbe60e31SLeila Ghaffari // This QFunction implements the Navier-Stokes equations (mentioned above) in 1127cbe60e31SLeila Ghaffari // primitive variables and with implicit time stepping method 1128cbe60e31SLeila Ghaffari // 1129cbe60e31SLeila Ghaffari // ***************************************************************************** 1130cbe60e31SLeila Ghaffari CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, 1131cbe60e31SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 1132cbe60e31SLeila Ghaffari // *INDENT-OFF* 1133cbe60e31SLeila Ghaffari // Inputs 1134cbe60e31SLeila Ghaffari const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 1135cbe60e31SLeila Ghaffari (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 1136cbe60e31SLeila Ghaffari (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 1137cbe60e31SLeila Ghaffari (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 1138cbe60e31SLeila Ghaffari (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 1139cbe60e31SLeila Ghaffari // Outputs 1140cbe60e31SLeila Ghaffari CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 1141cbe60e31SLeila Ghaffari (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1], 1142cbe60e31SLeila Ghaffari (*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 1143cbe60e31SLeila Ghaffari // *INDENT-ON* 1144cbe60e31SLeila Ghaffari // Context 1145cbe60e31SLeila Ghaffari NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 1146cbe60e31SLeila Ghaffari const CeedScalar mu = context->mu; 1147cbe60e31SLeila Ghaffari const CeedScalar cv = context->cv; 1148cbe60e31SLeila Ghaffari const CeedScalar cp = context->cp; 1149cbe60e31SLeila Ghaffari const CeedScalar *g = context->g; 1150cbe60e31SLeila Ghaffari const CeedScalar dt = context->dt; 1151cbe60e31SLeila Ghaffari const CeedScalar gamma = cp / cv; 1152cbe60e31SLeila Ghaffari const CeedScalar Rd = cp - cv; 1153cbe60e31SLeila Ghaffari 1154cbe60e31SLeila Ghaffari CeedPragmaSIMD 1155cbe60e31SLeila Ghaffari // Quadrature Point Loop 1156cbe60e31SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 1157cbe60e31SLeila Ghaffari CeedScalar Y[5]; 1158cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) Y[j] = q[j][i]; 1159cbe60e31SLeila Ghaffari const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 1160cbe60e31SLeila Ghaffari State s = StateFromY(context, Y, x_i); 1161cbe60e31SLeila Ghaffari 1162cbe60e31SLeila Ghaffari // -- Interp-to-Interp q_data 1163cbe60e31SLeila Ghaffari const CeedScalar wdetJ = q_data[0][i]; 1164cbe60e31SLeila Ghaffari // -- Interp-to-Grad q_data 1165cbe60e31SLeila Ghaffari // ---- Inverse of change of coordinate matrix: X_i,j 1166cbe60e31SLeila Ghaffari // *INDENT-OFF* 1167cbe60e31SLeila Ghaffari const CeedScalar dXdx[3][3] = {{q_data[1][i], 1168cbe60e31SLeila Ghaffari q_data[2][i], 1169cbe60e31SLeila Ghaffari q_data[3][i]}, 1170cbe60e31SLeila Ghaffari {q_data[4][i], 1171cbe60e31SLeila Ghaffari q_data[5][i], 1172cbe60e31SLeila Ghaffari q_data[6][i]}, 1173cbe60e31SLeila Ghaffari {q_data[7][i], 1174cbe60e31SLeila Ghaffari q_data[8][i], 1175cbe60e31SLeila Ghaffari q_data[9][i]} 1176cbe60e31SLeila Ghaffari }; 1177cbe60e31SLeila Ghaffari // *INDENT-ON* 1178cbe60e31SLeila Ghaffari State grad_s[3]; 1179cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 1180cbe60e31SLeila Ghaffari CeedScalar dx_i[3] = {0}, dY[5]; 1181cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) 1182cbe60e31SLeila Ghaffari dY[k] = Grad_q[0][k][i] * dXdx[0][j] + 1183cbe60e31SLeila Ghaffari Grad_q[1][k][i] * dXdx[1][j] + 1184cbe60e31SLeila Ghaffari Grad_q[2][k][i] * dXdx[2][j]; 1185cbe60e31SLeila Ghaffari dx_i[j] = 1.; 1186cbe60e31SLeila Ghaffari grad_s[j] = StateFromY_fwd(context, s, dY, x_i, dx_i); 1187cbe60e31SLeila Ghaffari } 1188cbe60e31SLeila Ghaffari 1189cbe60e31SLeila Ghaffari CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 1190cbe60e31SLeila Ghaffari KMStrainRate(grad_s, strain_rate); 1191cbe60e31SLeila Ghaffari NewtonianStress(context, strain_rate, kmstress); 1192cbe60e31SLeila Ghaffari KMUnpack(kmstress, stress); 1193cbe60e31SLeila Ghaffari ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 1194cbe60e31SLeila Ghaffari 1195cbe60e31SLeila Ghaffari StateConservative F_inviscid[3]; 1196cbe60e31SLeila Ghaffari FluxInviscid(context, s, F_inviscid); 1197cbe60e31SLeila Ghaffari 1198cbe60e31SLeila Ghaffari // Total flux 1199cbe60e31SLeila Ghaffari CeedScalar Flux[5][3]; 1200cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 1201cbe60e31SLeila Ghaffari Flux[0][j] = F_inviscid[j].density; 1202cbe60e31SLeila Ghaffari for (CeedInt k=0; k<3; k++) 1203cbe60e31SLeila Ghaffari Flux[k+1][j] = F_inviscid[j].momentum[k] - stress[k][j]; 1204cbe60e31SLeila Ghaffari Flux[4][j] = F_inviscid[j].E_total + Fe[j]; 1205cbe60e31SLeila Ghaffari } 1206cbe60e31SLeila Ghaffari 1207cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 1208cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) { 1209cbe60e31SLeila Ghaffari Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + 1210cbe60e31SLeila Ghaffari dXdx[j][1] * Flux[k][1] + 1211cbe60e31SLeila Ghaffari dXdx[j][2] * Flux[k][2]); 1212cbe60e31SLeila Ghaffari } 1213cbe60e31SLeila Ghaffari } 1214cbe60e31SLeila Ghaffari 1215cbe60e31SLeila Ghaffari const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 1216cbe60e31SLeila Ghaffari 1217cbe60e31SLeila Ghaffari CeedScalar Y_dot[5], dx0[3] = {0}; 1218cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) Y_dot[j] = q_dot[j][i]; 1219cbe60e31SLeila Ghaffari State s_dot = StateFromY_fwd(context, s, Y_dot, x_i, dx0); 1220cbe60e31SLeila Ghaffari 1221cbe60e31SLeila Ghaffari CeedScalar U_dot[5] = {0.}; 1222cbe60e31SLeila Ghaffari U_dot[0] = s_dot.U.density; 1223cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1224cbe60e31SLeila Ghaffari U_dot[j+1] = s_dot.U.momentum[j]; 1225cbe60e31SLeila Ghaffari U_dot[4] = s_dot.U.E_total; 1226cbe60e31SLeila Ghaffari 1227cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 1228cbe60e31SLeila Ghaffari v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 1229cbe60e31SLeila Ghaffari 1230cbe60e31SLeila Ghaffari // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction 1231cbe60e31SLeila Ghaffari CeedScalar jacob_F_conv[3][5][5] = {0}; 1232cbe60e31SLeila Ghaffari computeFluxJacobian_NS(jacob_F_conv, s.U.density, s.Y.velocity, s.U.E_total, 1233cbe60e31SLeila Ghaffari gamma, g, x_i); 1234cbe60e31SLeila Ghaffari CeedScalar grad_U[5][3]; 1235cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 1236cbe60e31SLeila Ghaffari grad_U[0][j] = grad_s[j].U.density; 1237cbe60e31SLeila Ghaffari for (CeedInt k=0; k<3; k++) grad_U[k+1][j] = grad_s[j].U.momentum[k]; 1238cbe60e31SLeila Ghaffari grad_U[4][j] = grad_s[j].U.E_total; 1239cbe60e31SLeila Ghaffari } 1240cbe60e31SLeila Ghaffari 1241cbe60e31SLeila Ghaffari // strong_conv = dF/dq * dq/dx (Strong convection) 1242cbe60e31SLeila Ghaffari CeedScalar strong_conv[5] = {0}; 1243cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1244cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) 1245cbe60e31SLeila Ghaffari for (CeedInt l=0; l<5; l++) 1246cbe60e31SLeila Ghaffari strong_conv[k] += jacob_F_conv[j][k][l] * grad_U[l][j]; 1247cbe60e31SLeila Ghaffari 1248cbe60e31SLeila Ghaffari // Strong residual 1249cbe60e31SLeila Ghaffari CeedScalar strong_res[5]; 1250cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 1251cbe60e31SLeila Ghaffari strong_res[j] = U_dot[j] + strong_conv[j] - body_force[j]; 1252cbe60e31SLeila Ghaffari 1253cbe60e31SLeila Ghaffari // -- Stabilization method: none, SU, or SUPG 1254cbe60e31SLeila Ghaffari CeedScalar stab[5][3] = {{0.}}; 1255cbe60e31SLeila Ghaffari CeedScalar tau_strong_res[5] = {0.}, tau_strong_res_conservative[5] = {0}; 1256cbe60e31SLeila Ghaffari CeedScalar tau_strong_conv[5] = {0.}, tau_strong_conv_conservative[5] = {0}; 1257cbe60e31SLeila Ghaffari CeedScalar Tau_d[3] = {0.}; 1258cbe60e31SLeila Ghaffari switch (context->stabilization) { 1259cbe60e31SLeila Ghaffari case STAB_NONE: // Galerkin 1260cbe60e31SLeila Ghaffari break; 1261cbe60e31SLeila Ghaffari case STAB_SU: // SU 1262cbe60e31SLeila Ghaffari Tau_diagPrim(Tau_d, dXdx, s.Y.velocity, cv, context, mu, dt, s.U.density); 1263cbe60e31SLeila Ghaffari tau_strong_conv[0] = Tau_d[0] * strong_conv[0]; 1264cbe60e31SLeila Ghaffari tau_strong_conv[1] = Tau_d[1] * strong_conv[1]; 1265cbe60e31SLeila Ghaffari tau_strong_conv[2] = Tau_d[1] * strong_conv[2]; 1266cbe60e31SLeila Ghaffari tau_strong_conv[3] = Tau_d[1] * strong_conv[3]; 1267cbe60e31SLeila Ghaffari tau_strong_conv[4] = Tau_d[2] * strong_conv[4]; 1268cbe60e31SLeila Ghaffari PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 1269cbe60e31SLeila Ghaffari tau_strong_conv, tau_strong_conv_conservative); 1270cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1271cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) 1272cbe60e31SLeila Ghaffari for (CeedInt l=0; l<5; l++) 1273cbe60e31SLeila Ghaffari stab[k][j] += jacob_F_conv[j][k][l] * tau_strong_conv_conservative[l]; 1274cbe60e31SLeila Ghaffari 1275cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 1276cbe60e31SLeila Ghaffari for (CeedInt k=0; k<3; k++) 1277cbe60e31SLeila Ghaffari Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 1278cbe60e31SLeila Ghaffari stab[j][1] * dXdx[k][1] + 1279cbe60e31SLeila Ghaffari stab[j][2] * dXdx[k][2]); 1280cbe60e31SLeila Ghaffari 1281cbe60e31SLeila Ghaffari break; 1282cbe60e31SLeila Ghaffari case STAB_SUPG: // SUPG 1283cbe60e31SLeila Ghaffari Tau_diagPrim(Tau_d, dXdx, s.Y.velocity, cv, context, mu, dt, s.U.density); 1284cbe60e31SLeila Ghaffari tau_strong_res[0] = Tau_d[0] * strong_res[0]; 1285cbe60e31SLeila Ghaffari tau_strong_res[1] = Tau_d[1] * strong_res[1]; 1286cbe60e31SLeila Ghaffari tau_strong_res[2] = Tau_d[1] * strong_res[2]; 1287cbe60e31SLeila Ghaffari tau_strong_res[3] = Tau_d[1] * strong_res[3]; 1288cbe60e31SLeila Ghaffari tau_strong_res[4] = Tau_d[2] * strong_res[4]; 1289cbe60e31SLeila Ghaffari 1290cbe60e31SLeila Ghaffari PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 1291cbe60e31SLeila Ghaffari tau_strong_res, tau_strong_res_conservative); 1292cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1293cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) 1294cbe60e31SLeila Ghaffari for (CeedInt l=0; l<5; l++) 1295cbe60e31SLeila Ghaffari stab[k][j] += jacob_F_conv[j][k][l] * tau_strong_res_conservative[l]; 1296cbe60e31SLeila Ghaffari 1297cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 1298cbe60e31SLeila Ghaffari for (CeedInt k=0; k<3; k++) 1299cbe60e31SLeila Ghaffari Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 1300cbe60e31SLeila Ghaffari stab[j][1] * dXdx[k][1] + 1301cbe60e31SLeila Ghaffari stab[j][2] * dXdx[k][2]); 1302cbe60e31SLeila Ghaffari break; 1303cbe60e31SLeila Ghaffari } 1304cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) jac_data[j][i] = Y[j]; 1305cbe60e31SLeila Ghaffari for (CeedInt j=0; j<6; j++) jac_data[5+j][i] = kmstress[j]; 1306cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) jac_data[5+6+j][i] = Tau_d[j]; 1307cbe60e31SLeila Ghaffari 1308cbe60e31SLeila Ghaffari } // End Quadrature Point Loop 1309cbe60e31SLeila Ghaffari 1310cbe60e31SLeila Ghaffari // Return 1311cbe60e31SLeila Ghaffari return 0; 1312cbe60e31SLeila Ghaffari } 1313cbe60e31SLeila Ghaffari 1314cbe60e31SLeila Ghaffari // ***************************************************************************** 1315cbe60e31SLeila Ghaffari // This QFunction implements the jacobean of the Navier-Stokes equations 1316cbe60e31SLeila Ghaffari // in primitive variables for implicit time stepping method. 1317cbe60e31SLeila Ghaffari // 1318cbe60e31SLeila Ghaffari // ***************************************************************************** 1319cbe60e31SLeila Ghaffari CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, 1320cbe60e31SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 1321cbe60e31SLeila Ghaffari // *INDENT-OFF* 1322cbe60e31SLeila Ghaffari // Inputs 1323cbe60e31SLeila Ghaffari const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 1324cbe60e31SLeila Ghaffari (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 1325cbe60e31SLeila Ghaffari (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 1326cbe60e31SLeila Ghaffari (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 1327cbe60e31SLeila Ghaffari (*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 1328cbe60e31SLeila Ghaffari // Outputs 1329cbe60e31SLeila Ghaffari CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 1330cbe60e31SLeila Ghaffari (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 1331cbe60e31SLeila Ghaffari // *INDENT-ON* 1332cbe60e31SLeila Ghaffari // Context 1333cbe60e31SLeila Ghaffari NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 1334cbe60e31SLeila Ghaffari const CeedScalar *g = context->g; 1335cbe60e31SLeila Ghaffari const CeedScalar cp = context->cp; 1336cbe60e31SLeila Ghaffari const CeedScalar cv = context->cv; 1337cbe60e31SLeila Ghaffari const CeedScalar Rd = cp - cv; 1338cbe60e31SLeila Ghaffari const CeedScalar gamma = cp / cv; 1339cbe60e31SLeila Ghaffari 1340cbe60e31SLeila Ghaffari CeedPragmaSIMD 1341cbe60e31SLeila Ghaffari // Quadrature Point Loop 1342cbe60e31SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 1343cbe60e31SLeila Ghaffari // -- Interp-to-Interp q_data 1344cbe60e31SLeila Ghaffari const CeedScalar wdetJ = q_data[0][i]; 1345cbe60e31SLeila Ghaffari // -- Interp-to-Grad q_data 1346cbe60e31SLeila Ghaffari // ---- Inverse of change of coordinate matrix: X_i,j 1347cbe60e31SLeila Ghaffari // *INDENT-OFF* 1348cbe60e31SLeila Ghaffari const CeedScalar dXdx[3][3] = {{q_data[1][i], 1349cbe60e31SLeila Ghaffari q_data[2][i], 1350cbe60e31SLeila Ghaffari q_data[3][i]}, 1351cbe60e31SLeila Ghaffari {q_data[4][i], 1352cbe60e31SLeila Ghaffari q_data[5][i], 1353cbe60e31SLeila Ghaffari q_data[6][i]}, 1354cbe60e31SLeila Ghaffari {q_data[7][i], 1355cbe60e31SLeila Ghaffari q_data[8][i], 1356cbe60e31SLeila Ghaffari q_data[9][i]} 1357cbe60e31SLeila Ghaffari }; 1358cbe60e31SLeila Ghaffari // *INDENT-ON* 1359cbe60e31SLeila Ghaffari 1360cbe60e31SLeila Ghaffari CeedScalar Y[5], kmstress[6], Tau_d[3] __attribute((unused)); 1361cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) Y[j] = jac_data[j][i]; 1362cbe60e31SLeila Ghaffari for (int j=0; j<6; j++) kmstress[j] = jac_data[5+j][i]; 1363cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) Tau_d[j] = jac_data[5+6+j][i]; 1364cbe60e31SLeila Ghaffari const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 1365cbe60e31SLeila Ghaffari State s = StateFromY(context, Y, x_i); 1366cbe60e31SLeila Ghaffari 1367cbe60e31SLeila Ghaffari CeedScalar dY[5], dx0[3] = {0}; 1368cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) dY[j] = dq[j][i]; 1369cbe60e31SLeila Ghaffari State ds = StateFromY_fwd(context, s, dY, x_i, dx0); 1370cbe60e31SLeila Ghaffari 1371cbe60e31SLeila Ghaffari State grad_ds[3]; 1372cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) { 1373cbe60e31SLeila Ghaffari CeedScalar dYj[5]; 1374cbe60e31SLeila Ghaffari for (int k=0; k<5; k++) 1375cbe60e31SLeila Ghaffari dYj[k] = Grad_dq[0][k][i] * dXdx[0][j] + 1376cbe60e31SLeila Ghaffari Grad_dq[1][k][i] * dXdx[1][j] + 1377cbe60e31SLeila Ghaffari Grad_dq[2][k][i] * dXdx[2][j]; 1378cbe60e31SLeila Ghaffari grad_ds[j] = StateFromY_fwd(context, s, dYj, x_i, dx0); 1379cbe60e31SLeila Ghaffari } 1380cbe60e31SLeila Ghaffari 1381cbe60e31SLeila Ghaffari CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 1382cbe60e31SLeila Ghaffari KMStrainRate(grad_ds, dstrain_rate); 1383cbe60e31SLeila Ghaffari NewtonianStress(context, dstrain_rate, dkmstress); 1384cbe60e31SLeila Ghaffari KMUnpack(dkmstress, dstress); 1385cbe60e31SLeila Ghaffari KMUnpack(kmstress, stress); 1386cbe60e31SLeila Ghaffari ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 1387cbe60e31SLeila Ghaffari 1388cbe60e31SLeila Ghaffari StateConservative dF_inviscid[3]; 1389cbe60e31SLeila Ghaffari FluxInviscid_fwd(context, s, ds, dF_inviscid); 1390cbe60e31SLeila Ghaffari 1391cbe60e31SLeila Ghaffari // Total flux 1392cbe60e31SLeila Ghaffari CeedScalar dFlux[5][3]; 1393cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) { 1394cbe60e31SLeila Ghaffari dFlux[0][j] = dF_inviscid[j].density; 1395cbe60e31SLeila Ghaffari for (int k=0; k<3; k++) 1396cbe60e31SLeila Ghaffari dFlux[k+1][j] = dF_inviscid[j].momentum[k] - dstress[k][j]; 1397cbe60e31SLeila Ghaffari dFlux[4][j] = dF_inviscid[j].E_total + dFe[j]; 1398cbe60e31SLeila Ghaffari } 1399cbe60e31SLeila Ghaffari 1400cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) { 1401cbe60e31SLeila Ghaffari for (int k=0; k<5; k++) { 1402cbe60e31SLeila Ghaffari Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + 1403cbe60e31SLeila Ghaffari dXdx[j][1] * dFlux[k][1] + 1404cbe60e31SLeila Ghaffari dXdx[j][2] * dFlux[k][2]); 1405cbe60e31SLeila Ghaffari } 1406cbe60e31SLeila Ghaffari } 1407cbe60e31SLeila Ghaffari 1408cbe60e31SLeila Ghaffari const CeedScalar dbody_force[5] = {0, 1409cbe60e31SLeila Ghaffari ds.U.density *g[0], 1410cbe60e31SLeila Ghaffari ds.U.density *g[1], 1411cbe60e31SLeila Ghaffari ds.U.density *g[2], 1412cbe60e31SLeila Ghaffari 0 1413cbe60e31SLeila Ghaffari }; 1414cbe60e31SLeila Ghaffari CeedScalar dU[5] = {0.}; 1415cbe60e31SLeila Ghaffari dU[0] = ds.U.density; 1416cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1417cbe60e31SLeila Ghaffari dU[j+1] = ds.U.momentum[j]; 1418cbe60e31SLeila Ghaffari dU[4] = ds.U.E_total; 1419cbe60e31SLeila Ghaffari 1420cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) 1421cbe60e31SLeila Ghaffari v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 1422cbe60e31SLeila Ghaffari 1423cbe60e31SLeila Ghaffari if (1) { 1424cbe60e31SLeila Ghaffari CeedScalar jacob_F_conv[3][5][5] = {0}; 1425cbe60e31SLeila Ghaffari computeFluxJacobian_NS(jacob_F_conv, s.U.density, s.Y.velocity, s.U.E_total, 1426cbe60e31SLeila Ghaffari gamma, g, x_i); 1427cbe60e31SLeila Ghaffari CeedScalar grad_dU[5][3]; 1428cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) { 1429cbe60e31SLeila Ghaffari grad_dU[0][j] = grad_ds[j].U.density; 1430cbe60e31SLeila Ghaffari for (int k=0; k<3; k++) grad_dU[k+1][j] = grad_ds[j].U.momentum[k]; 1431cbe60e31SLeila Ghaffari grad_dU[4][j] = grad_ds[j].U.E_total; 1432cbe60e31SLeila Ghaffari } 1433cbe60e31SLeila Ghaffari CeedScalar dstrong_conv[5] = {0.}; 1434cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) 1435cbe60e31SLeila Ghaffari for (int k=0; k<5; k++) 1436cbe60e31SLeila Ghaffari for (int l=0; l<5; l++) 1437cbe60e31SLeila Ghaffari dstrong_conv[k] += jacob_F_conv[j][k][l] * grad_dU[l][j]; 1438cbe60e31SLeila Ghaffari 1439cbe60e31SLeila Ghaffari CeedScalar dstrong_res[5]; 1440cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) 1441cbe60e31SLeila Ghaffari dstrong_res[j] = context->ijacobian_time_shift * dU[j] + 1442cbe60e31SLeila Ghaffari dstrong_conv[j] - 1443cbe60e31SLeila Ghaffari dbody_force[j]; 1444cbe60e31SLeila Ghaffari 1445cbe60e31SLeila Ghaffari CeedScalar dtau_strong_res[5] = {0.}, 1446cbe60e31SLeila Ghaffari dtau_strong_res_conservative[5] = {0.}; 1447cbe60e31SLeila Ghaffari dtau_strong_res[0] = Tau_d[0] * dstrong_res[0]; 1448cbe60e31SLeila Ghaffari dtau_strong_res[1] = Tau_d[1] * dstrong_res[1]; 1449cbe60e31SLeila Ghaffari dtau_strong_res[2] = Tau_d[1] * dstrong_res[2]; 1450cbe60e31SLeila Ghaffari dtau_strong_res[3] = Tau_d[1] * dstrong_res[3]; 1451cbe60e31SLeila Ghaffari dtau_strong_res[4] = Tau_d[2] * dstrong_res[4]; 1452cbe60e31SLeila Ghaffari PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 1453cbe60e31SLeila Ghaffari dtau_strong_res, dtau_strong_res_conservative); 1454cbe60e31SLeila Ghaffari CeedScalar dstab[5][3] = {0}; 1455cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) 1456cbe60e31SLeila Ghaffari for (int k=0; k<5; k++) 1457cbe60e31SLeila Ghaffari for (int l=0; l<5; l++) 1458cbe60e31SLeila Ghaffari dstab[k][j] += jacob_F_conv[j][k][l] * dtau_strong_res_conservative[l]; 1459cbe60e31SLeila Ghaffari 1460cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) 1461cbe60e31SLeila Ghaffari for (int k=0; k<3; k++) 1462cbe60e31SLeila Ghaffari Grad_v[k][j][i] += wdetJ*(dstab[j][0] * dXdx[k][0] + 1463cbe60e31SLeila Ghaffari dstab[j][1] * dXdx[k][1] + 1464cbe60e31SLeila Ghaffari dstab[j][2] * dXdx[k][2]); 1465cbe60e31SLeila Ghaffari 1466cbe60e31SLeila Ghaffari } 1467cbe60e31SLeila Ghaffari } // End Quadrature Point Loop 1468cbe60e31SLeila Ghaffari return 0; 1469cbe60e31SLeila Ghaffari } 1470cbe60e31SLeila Ghaffari // ***************************************************************************** 1471cbe60e31SLeila Ghaffari 14723a8779fbSJames Wright #endif // newtonian_h 1473