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; 793*41e73928SJames Wright State (*StateFromQi)(NewtonianIdealGasContext gas, 794*41e73928SJames Wright const CeedScalar qi[5], const CeedScalar x[3]); 795*41e73928SJames Wright State (*StateFromQi_fwd)(NewtonianIdealGasContext gas, 796*41e73928SJames Wright State s, const CeedScalar dqi[5], 797*41e73928SJames Wright const CeedScalar x[3], const CeedScalar dx[3]); 798*41e73928SJames Wright StateFromQi = context->is_primitive ? &StateFromY : &StateFromU; 799*41e73928SJames Wright StateFromQi_fwd = context->is_primitive ? &StateFromY_fwd : &StateFromU_fwd; 800*41e73928SJames Wright 8018085925cSJames Wright 8028085925cSJames Wright CeedPragmaSIMD 8038085925cSJames Wright for(CeedInt i=0; i<Q; i++) { 804d3b25f3aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 805*41e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 806*41e73928SJames Wright State s = StateFromQi(context, qi, x_i); 8078085925cSJames Wright 8088085925cSJames Wright const CeedScalar wdetJb = (is_implicit ? -1. : 1.) * q_data_sur[0][i]; 8098085925cSJames Wright // ---- Normal vect 8108085925cSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 8118085925cSJames Wright q_data_sur[2][i], 8128085925cSJames Wright q_data_sur[3][i] 8138085925cSJames Wright }; 8148085925cSJames Wright 815d3b25f3aSJames Wright const CeedScalar dXdx[2][3] = { 816d3b25f3aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 817d3b25f3aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 818d3b25f3aSJames Wright }; 8198085925cSJames Wright 820d3b25f3aSJames Wright State grad_s[3]; 821d3b25f3aSJames Wright for (CeedInt j=0; j<3; j++) { 822*41e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 823d3b25f3aSJames Wright for (CeedInt k=0; k<5; k++) 824*41e73928SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 825d3b25f3aSJames Wright Grad_q[1][k][i] * dXdx[1][j]; 826d3b25f3aSJames Wright dx_i[j] = 1.; 827*41e73928SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 828d3b25f3aSJames Wright } 8298085925cSJames Wright 830d3b25f3aSJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 831d3b25f3aSJames Wright KMStrainRate(grad_s, strain_rate); 832d3b25f3aSJames Wright NewtonianStress(context, strain_rate, kmstress); 833d3b25f3aSJames Wright KMUnpack(kmstress, stress); 834d3b25f3aSJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 835d3b25f3aSJames Wright 836d3b25f3aSJames Wright StateConservative F_inviscid[3]; 837d3b25f3aSJames Wright FluxInviscid(context, s, F_inviscid); 838d3b25f3aSJames Wright 839d3b25f3aSJames Wright CeedScalar Flux[5] = {0.}; 840d3b25f3aSJames Wright for (int j=0; j<3; j++) { 841d3b25f3aSJames Wright Flux[0] += F_inviscid[j].density * norm[j]; 842d3b25f3aSJames Wright for (int k=0; k<3; k++) 843d3b25f3aSJames Wright Flux[k+1] += (F_inviscid[j].momentum[k] - stress[k][j]) * norm[j]; 844d3b25f3aSJames Wright Flux[4] += (F_inviscid[j].E_total + Fe[j])*norm[j]; 845d3b25f3aSJames Wright } 846d3b25f3aSJames Wright 8478085925cSJames Wright // -- Density 848d3b25f3aSJames Wright v[0][i] = -wdetJb * Flux[0]; 8498085925cSJames Wright 8508085925cSJames Wright // -- Momentum 8518085925cSJames Wright for (CeedInt j=0; j<3; j++) 852d3b25f3aSJames Wright v[j+1][i] = -wdetJb * Flux[j+1]; 8538085925cSJames Wright 8548085925cSJames Wright // -- Total Energy Density 855d3b25f3aSJames Wright v[4][i] = -wdetJb * Flux[4]; 85668ae065aSJames Wright 8573934e2b1SJames Wright if (context->is_primitive) { 8583934e2b1SJames Wright jac_data_sur[0][i] = s.Y.pressure; 8593934e2b1SJames Wright for (int j=0; j<3; j++) jac_data_sur[j+1][i] = s.Y.velocity[j]; 8603934e2b1SJames Wright jac_data_sur[4][i] = s.Y.temperature; 8613934e2b1SJames Wright } else { 86268ae065aSJames Wright jac_data_sur[0][i] = s.U.density; 8633934e2b1SJames Wright for (int j=0; j<3; j++) jac_data_sur[j+1][i] = s.U.momentum[j]; 86468ae065aSJames Wright jac_data_sur[4][i] = s.U.E_total; 8653934e2b1SJames Wright } 86668ae065aSJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 8678085925cSJames Wright } 8688085925cSJames Wright return 0; 8698085925cSJames Wright } 8708085925cSJames Wright 87168ae065aSJames Wright // Jacobian for "set nothing" boundary integral 87268ae065aSJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian)(void *ctx, CeedInt Q, 87368ae065aSJames Wright const CeedScalar *const *in, 87468ae065aSJames Wright CeedScalar *const *out) { 87568ae065aSJames Wright // *INDENT-OFF* 87668ae065aSJames Wright // Inputs 87768ae065aSJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 87868ae065aSJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 87968ae065aSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 88068ae065aSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 88168ae065aSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 88268ae065aSJames Wright // Outputs 88368ae065aSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 88468ae065aSJames Wright // *INDENT-ON* 88568ae065aSJames Wright 88668ae065aSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 88768ae065aSJames Wright const bool implicit = context->is_implicit; 888*41e73928SJames Wright State (*StateFromQi)(NewtonianIdealGasContext gas, 889*41e73928SJames Wright const CeedScalar qi[5], const CeedScalar x[3]); 890*41e73928SJames Wright State (*StateFromQi_fwd)(NewtonianIdealGasContext gas, 891*41e73928SJames Wright State s, const CeedScalar dqi[5], 892*41e73928SJames Wright const CeedScalar x[3], const CeedScalar dx[3]); 893*41e73928SJames Wright StateFromQi = context->is_primitive ? &StateFromY : &StateFromU; 894*41e73928SJames Wright StateFromQi_fwd = context->is_primitive ? &StateFromY_fwd : &StateFromU_fwd; 89568ae065aSJames Wright 89668ae065aSJames Wright CeedPragmaSIMD 89768ae065aSJames Wright // Quadrature Point Loop 89868ae065aSJames Wright for (CeedInt i=0; i<Q; i++) { 89968ae065aSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 90068ae065aSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 90168ae065aSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 90268ae065aSJames Wright q_data_sur[2][i], 90368ae065aSJames Wright q_data_sur[3][i] 90468ae065aSJames Wright }; 90568ae065aSJames Wright const CeedScalar dXdx[2][3] = { 90668ae065aSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 90768ae065aSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 90868ae065aSJames Wright }; 90968ae065aSJames Wright 910*41e73928SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 911*41e73928SJames Wright for (int j=0; j<5; j++) qi[j] = jac_data_sur[j][i]; 91268ae065aSJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 913*41e73928SJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 9143934e2b1SJames Wright 915*41e73928SJames Wright State s = StateFromQi(context, qi, x_i); 916*41e73928SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 91768ae065aSJames Wright 91868ae065aSJames Wright State grad_ds[3]; 91968ae065aSJames Wright for (CeedInt j=0; j<3; j++) { 920*41e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 92168ae065aSJames Wright for (CeedInt k=0; k<5; k++) 922*41e73928SJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 92368ae065aSJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 92468ae065aSJames Wright dx_i[j] = 1.; 925*41e73928SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 92668ae065aSJames Wright } 92768ae065aSJames Wright 92868ae065aSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 92968ae065aSJames Wright KMStrainRate(grad_ds, dstrain_rate); 93068ae065aSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 93168ae065aSJames Wright KMUnpack(dkmstress, dstress); 93268ae065aSJames Wright KMUnpack(kmstress, stress); 93368ae065aSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 93468ae065aSJames Wright 93568ae065aSJames Wright StateConservative dF_inviscid[3]; 93668ae065aSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 93768ae065aSJames Wright 93868ae065aSJames Wright CeedScalar dFlux[5] = {0.}; 93968ae065aSJames Wright for (int j=0; j<3; j++) { 94068ae065aSJames Wright dFlux[0] += dF_inviscid[j].density * norm[j]; 94168ae065aSJames Wright for (int k=0; k<3; k++) 94268ae065aSJames Wright dFlux[k+1] += (dF_inviscid[j].momentum[k] - dstress[k][j]) * norm[j]; 94368ae065aSJames Wright dFlux[4] += (dF_inviscid[j].E_total + dFe[j]) * norm[j]; 94468ae065aSJames Wright } 94568ae065aSJames Wright 94668ae065aSJames Wright for (int j=0; j<5; j++) 94768ae065aSJames Wright v[j][i] = -wdetJb * dFlux[j]; 94868ae065aSJames Wright } // End Quadrature Point Loop 94968ae065aSJames Wright return 0; 95068ae065aSJames Wright } 95168ae065aSJames Wright 95204b9037bSJames Wright // Outflow boundary condition, weakly setting a constant pressure 95304b9037bSJames Wright CEED_QFUNCTION(PressureOutflow)(void *ctx, CeedInt Q, 95404b9037bSJames Wright const CeedScalar *const *in, 95504b9037bSJames Wright CeedScalar *const *out) { 95604b9037bSJames Wright // *INDENT-OFF* 95704b9037bSJames Wright // Inputs 95804b9037bSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 95925bfcc41SJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 96025bfcc41SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 96125bfcc41SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 96204b9037bSJames Wright // Outputs 96304b9037bSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 96404b9037bSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 96504b9037bSJames Wright // *INDENT-ON* 96604b9037bSJames Wright 96704b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 96804b9037bSJames Wright const bool implicit = context->is_implicit; 96904b9037bSJames Wright const CeedScalar P0 = context->P0; 97004b9037bSJames Wright 971*41e73928SJames Wright State (*StateFromQi)(NewtonianIdealGasContext gas, 972*41e73928SJames Wright const CeedScalar qi[5], const CeedScalar x[3]); 973*41e73928SJames Wright State (*StateFromQi_fwd)(NewtonianIdealGasContext gas, 974*41e73928SJames Wright State s, const CeedScalar dqi[5], 975*41e73928SJames Wright const CeedScalar x[3], const CeedScalar dx[3]); 976*41e73928SJames Wright StateFromQi = context->is_primitive ? &StateFromY : &StateFromU; 977*41e73928SJames Wright StateFromQi_fwd = context->is_primitive ? &StateFromY_fwd : &StateFromU_fwd; 978*41e73928SJames Wright 97904b9037bSJames Wright CeedPragmaSIMD 98004b9037bSJames Wright // Quadrature Point Loop 98104b9037bSJames Wright for (CeedInt i=0; i<Q; i++) { 98204b9037bSJames Wright // Setup 98304b9037bSJames Wright // -- Interp in 98425bfcc41SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 985*41e73928SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 986*41e73928SJames Wright State s = StateFromQi(context, qi, x_i); 98725bfcc41SJames Wright s.Y.pressure = P0; 98804b9037bSJames Wright 98904b9037bSJames Wright // -- Interp-to-Interp q_data 99004b9037bSJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 99104b9037bSJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 99204b9037bSJames Wright // We can effect this by swapping the sign on this weight 99304b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 99404b9037bSJames Wright 99504b9037bSJames Wright // ---- Normal vect 99604b9037bSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 99704b9037bSJames Wright q_data_sur[2][i], 99804b9037bSJames Wright q_data_sur[3][i] 99904b9037bSJames Wright }; 100004b9037bSJames Wright 100125bfcc41SJames Wright const CeedScalar dXdx[2][3] = { 100225bfcc41SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 100325bfcc41SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 100425bfcc41SJames Wright }; 100504b9037bSJames Wright 100625bfcc41SJames Wright State grad_s[3]; 100725bfcc41SJames Wright for (CeedInt j=0; j<3; j++) { 1008*41e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 100925bfcc41SJames Wright for (CeedInt k=0; k<5; k++) 1010*41e73928SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 101125bfcc41SJames Wright Grad_q[1][k][i] * dXdx[1][j]; 101225bfcc41SJames Wright dx_i[j] = 1.; 1013*41e73928SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 101425bfcc41SJames Wright } 101525bfcc41SJames Wright 101625bfcc41SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 101725bfcc41SJames Wright KMStrainRate(grad_s, strain_rate); 101825bfcc41SJames Wright NewtonianStress(context, strain_rate, kmstress); 101925bfcc41SJames Wright KMUnpack(kmstress, stress); 102025bfcc41SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 102125bfcc41SJames Wright 102225bfcc41SJames Wright StateConservative F_inviscid[3]; 102325bfcc41SJames Wright FluxInviscid(context, s, F_inviscid); 102425bfcc41SJames Wright 102525bfcc41SJames Wright CeedScalar Flux[5] = {0.}; 102625bfcc41SJames Wright for (int j=0; j<3; j++) { 102725bfcc41SJames Wright Flux[0] += F_inviscid[j].density * norm[j]; 102825bfcc41SJames Wright for (int k=0; k<3; k++) 102925bfcc41SJames Wright Flux[k+1] += (F_inviscid[j].momentum[k] - stress[k][j]) * norm[j]; 103025bfcc41SJames Wright Flux[4] += (F_inviscid[j].E_total + Fe[j])*norm[j]; 103125bfcc41SJames Wright } 103204b9037bSJames Wright 103304b9037bSJames Wright // -- Density 103425bfcc41SJames Wright v[0][i] = -wdetJb * Flux[0]; 103504b9037bSJames Wright 103604b9037bSJames Wright // -- Momentum 103704b9037bSJames Wright for (CeedInt j=0; j<3; j++) 103825bfcc41SJames Wright v[j+1][i] = -wdetJb * Flux[j+1]; 103904b9037bSJames Wright 104004b9037bSJames Wright // -- Total Energy Density 104125bfcc41SJames Wright v[4][i] = -wdetJb * Flux[4]; 104204b9037bSJames Wright 104304b9037bSJames Wright // Save values for Jacobian 10443934e2b1SJames Wright if (context->is_primitive) { 10453934e2b1SJames Wright jac_data_sur[0][i] = s.Y.pressure; 10463934e2b1SJames Wright for (int j=0; j<3; j++) jac_data_sur[j+1][i] = s.Y.velocity[j]; 10473934e2b1SJames Wright jac_data_sur[4][i] = s.Y.temperature; 10483934e2b1SJames Wright } else { 104925bfcc41SJames Wright jac_data_sur[0][i] = s.U.density; 10503934e2b1SJames Wright for (int j=0; j<3; j++) jac_data_sur[j+1][i] = s.U.momentum[j]; 105125bfcc41SJames Wright jac_data_sur[4][i] = s.U.E_total; 10523934e2b1SJames Wright } 1053b01ba163SJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 105404b9037bSJames Wright } // End Quadrature Point Loop 105504b9037bSJames Wright return 0; 105604b9037bSJames Wright } 105704b9037bSJames Wright 105804b9037bSJames Wright // Jacobian for weak-pressure outflow boundary condition 105904b9037bSJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian)(void *ctx, CeedInt Q, 1060*41e73928SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 106104b9037bSJames Wright // *INDENT-OFF* 106204b9037bSJames Wright // Inputs 106304b9037bSJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 1064b01ba163SJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 1065b01ba163SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 1066b01ba163SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 1067b01ba163SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 106804b9037bSJames Wright // Outputs 106904b9037bSJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 107004b9037bSJames Wright // *INDENT-ON* 107104b9037bSJames Wright 107204b9037bSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 107304b9037bSJames Wright const bool implicit = context->is_implicit; 107404b9037bSJames Wright 1075*41e73928SJames Wright State (*StateFromQi)(NewtonianIdealGasContext gas, 1076*41e73928SJames Wright const CeedScalar qi[5], const CeedScalar x[3]); 1077*41e73928SJames Wright State (*StateFromQi_fwd)(NewtonianIdealGasContext gas, 1078*41e73928SJames Wright State s, const CeedScalar dQi[5], 1079*41e73928SJames Wright const CeedScalar x[3], const CeedScalar dx[3]); 1080*41e73928SJames Wright StateFromQi = context->is_primitive ? &StateFromY : &StateFromU; 1081*41e73928SJames Wright StateFromQi_fwd = context->is_primitive ? &StateFromY_fwd : &StateFromU_fwd; 1082*41e73928SJames Wright 108304b9037bSJames Wright CeedPragmaSIMD 108404b9037bSJames Wright // Quadrature Point Loop 108504b9037bSJames Wright for (CeedInt i=0; i<Q; i++) { 1086b01ba163SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 108704b9037bSJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 108804b9037bSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 108904b9037bSJames Wright q_data_sur[2][i], 109004b9037bSJames Wright q_data_sur[3][i] 109104b9037bSJames Wright }; 1092b01ba163SJames Wright const CeedScalar dXdx[2][3] = { 1093b01ba163SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 1094b01ba163SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 1095b01ba163SJames Wright }; 1096b01ba163SJames Wright 1097*41e73928SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 1098*41e73928SJames Wright for (int j=0; j<5; j++) qi[j] = jac_data_sur[j][i]; 1099b01ba163SJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 1100*41e73928SJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 11013934e2b1SJames Wright 1102*41e73928SJames Wright State s = StateFromQi(context, qi, x_i); 1103*41e73928SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 1104b01ba163SJames Wright s.Y.pressure = context->P0; 1105b01ba163SJames Wright ds.Y.pressure = 0.; 1106b01ba163SJames Wright 1107b01ba163SJames Wright State grad_ds[3]; 1108b01ba163SJames Wright for (CeedInt j=0; j<3; j++) { 1109*41e73928SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 1110b01ba163SJames Wright for (CeedInt k=0; k<5; k++) 1111*41e73928SJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 1112b01ba163SJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 1113b01ba163SJames Wright dx_i[j] = 1.; 1114*41e73928SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 1115b01ba163SJames Wright } 1116b01ba163SJames Wright 1117b01ba163SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 1118b01ba163SJames Wright KMStrainRate(grad_ds, dstrain_rate); 1119b01ba163SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 1120b01ba163SJames Wright KMUnpack(dkmstress, dstress); 1121b01ba163SJames Wright KMUnpack(kmstress, stress); 1122b01ba163SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 112304b9037bSJames Wright 1124e6b47afbSJames Wright StateConservative dF_inviscid[3]; 1125e6b47afbSJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 112604b9037bSJames Wright 1127e6b47afbSJames Wright CeedScalar dFlux[5] = {0.}; 1128e6b47afbSJames Wright for (int j=0; j<3; j++) { 1129e6b47afbSJames Wright dFlux[0] += dF_inviscid[j].density * norm[j]; 1130e6b47afbSJames Wright for (int k=0; k<3; k++) 1131b01ba163SJames Wright dFlux[k+1] += (dF_inviscid[j].momentum[k] - dstress[k][j]) * norm[j]; 1132b01ba163SJames Wright dFlux[4] += (dF_inviscid[j].E_total + dFe[j]) * norm[j]; 1133e6b47afbSJames Wright } 1134e6b47afbSJames Wright 1135e6b47afbSJames Wright for (int j=0; j<5; j++) 1136e6b47afbSJames Wright v[j][i] = -wdetJb * dFlux[j]; 113704b9037bSJames Wright } // End Quadrature Point Loop 113804b9037bSJames Wright return 0; 113904b9037bSJames Wright } 114004b9037bSJames Wright 11413a8779fbSJames Wright // ***************************************************************************** 1142cbe60e31SLeila Ghaffari // This QFunction implements the Navier-Stokes equations (mentioned above) in 1143cbe60e31SLeila Ghaffari // primitive variables and with implicit time stepping method 1144cbe60e31SLeila Ghaffari // 1145cbe60e31SLeila Ghaffari // ***************************************************************************** 1146cbe60e31SLeila Ghaffari CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, 1147cbe60e31SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 1148cbe60e31SLeila Ghaffari // *INDENT-OFF* 1149cbe60e31SLeila Ghaffari // Inputs 1150cbe60e31SLeila Ghaffari const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 1151cbe60e31SLeila Ghaffari (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 1152cbe60e31SLeila Ghaffari (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 1153cbe60e31SLeila Ghaffari (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 1154cbe60e31SLeila Ghaffari (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 1155cbe60e31SLeila Ghaffari // Outputs 1156cbe60e31SLeila Ghaffari CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 1157cbe60e31SLeila Ghaffari (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1], 1158cbe60e31SLeila Ghaffari (*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 1159cbe60e31SLeila Ghaffari // *INDENT-ON* 1160cbe60e31SLeila Ghaffari // Context 1161cbe60e31SLeila Ghaffari NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 1162cbe60e31SLeila Ghaffari const CeedScalar mu = context->mu; 1163cbe60e31SLeila Ghaffari const CeedScalar cv = context->cv; 1164cbe60e31SLeila Ghaffari const CeedScalar cp = context->cp; 1165cbe60e31SLeila Ghaffari const CeedScalar *g = context->g; 1166cbe60e31SLeila Ghaffari const CeedScalar dt = context->dt; 1167cbe60e31SLeila Ghaffari const CeedScalar gamma = cp / cv; 1168cbe60e31SLeila Ghaffari const CeedScalar Rd = cp - cv; 1169cbe60e31SLeila Ghaffari 1170cbe60e31SLeila Ghaffari CeedPragmaSIMD 1171cbe60e31SLeila Ghaffari // Quadrature Point Loop 1172cbe60e31SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 1173cbe60e31SLeila Ghaffari CeedScalar Y[5]; 1174cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) Y[j] = q[j][i]; 1175cbe60e31SLeila Ghaffari const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 1176cbe60e31SLeila Ghaffari State s = StateFromY(context, Y, x_i); 1177cbe60e31SLeila Ghaffari 1178cbe60e31SLeila Ghaffari // -- Interp-to-Interp q_data 1179cbe60e31SLeila Ghaffari const CeedScalar wdetJ = q_data[0][i]; 1180cbe60e31SLeila Ghaffari // -- Interp-to-Grad q_data 1181cbe60e31SLeila Ghaffari // ---- Inverse of change of coordinate matrix: X_i,j 1182cbe60e31SLeila Ghaffari // *INDENT-OFF* 1183cbe60e31SLeila Ghaffari const CeedScalar dXdx[3][3] = {{q_data[1][i], 1184cbe60e31SLeila Ghaffari q_data[2][i], 1185cbe60e31SLeila Ghaffari q_data[3][i]}, 1186cbe60e31SLeila Ghaffari {q_data[4][i], 1187cbe60e31SLeila Ghaffari q_data[5][i], 1188cbe60e31SLeila Ghaffari q_data[6][i]}, 1189cbe60e31SLeila Ghaffari {q_data[7][i], 1190cbe60e31SLeila Ghaffari q_data[8][i], 1191cbe60e31SLeila Ghaffari q_data[9][i]} 1192cbe60e31SLeila Ghaffari }; 1193cbe60e31SLeila Ghaffari // *INDENT-ON* 1194cbe60e31SLeila Ghaffari State grad_s[3]; 1195cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 1196cbe60e31SLeila Ghaffari CeedScalar dx_i[3] = {0}, dY[5]; 1197cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) 1198cbe60e31SLeila Ghaffari dY[k] = Grad_q[0][k][i] * dXdx[0][j] + 1199cbe60e31SLeila Ghaffari Grad_q[1][k][i] * dXdx[1][j] + 1200cbe60e31SLeila Ghaffari Grad_q[2][k][i] * dXdx[2][j]; 1201cbe60e31SLeila Ghaffari dx_i[j] = 1.; 1202cbe60e31SLeila Ghaffari grad_s[j] = StateFromY_fwd(context, s, dY, x_i, dx_i); 1203cbe60e31SLeila Ghaffari } 1204cbe60e31SLeila Ghaffari 1205cbe60e31SLeila Ghaffari CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 1206cbe60e31SLeila Ghaffari KMStrainRate(grad_s, strain_rate); 1207cbe60e31SLeila Ghaffari NewtonianStress(context, strain_rate, kmstress); 1208cbe60e31SLeila Ghaffari KMUnpack(kmstress, stress); 1209cbe60e31SLeila Ghaffari ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 1210cbe60e31SLeila Ghaffari 1211cbe60e31SLeila Ghaffari StateConservative F_inviscid[3]; 1212cbe60e31SLeila Ghaffari FluxInviscid(context, s, F_inviscid); 1213cbe60e31SLeila Ghaffari 1214cbe60e31SLeila Ghaffari // Total flux 1215cbe60e31SLeila Ghaffari CeedScalar Flux[5][3]; 1216cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 1217cbe60e31SLeila Ghaffari Flux[0][j] = F_inviscid[j].density; 1218cbe60e31SLeila Ghaffari for (CeedInt k=0; k<3; k++) 1219cbe60e31SLeila Ghaffari Flux[k+1][j] = F_inviscid[j].momentum[k] - stress[k][j]; 1220cbe60e31SLeila Ghaffari Flux[4][j] = F_inviscid[j].E_total + Fe[j]; 1221cbe60e31SLeila Ghaffari } 1222cbe60e31SLeila Ghaffari 1223cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 1224cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) { 1225cbe60e31SLeila Ghaffari Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + 1226cbe60e31SLeila Ghaffari dXdx[j][1] * Flux[k][1] + 1227cbe60e31SLeila Ghaffari dXdx[j][2] * Flux[k][2]); 1228cbe60e31SLeila Ghaffari } 1229cbe60e31SLeila Ghaffari } 1230cbe60e31SLeila Ghaffari 1231cbe60e31SLeila Ghaffari const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 1232cbe60e31SLeila Ghaffari 1233cbe60e31SLeila Ghaffari CeedScalar Y_dot[5], dx0[3] = {0}; 1234cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) Y_dot[j] = q_dot[j][i]; 1235cbe60e31SLeila Ghaffari State s_dot = StateFromY_fwd(context, s, Y_dot, x_i, dx0); 1236cbe60e31SLeila Ghaffari 1237cbe60e31SLeila Ghaffari CeedScalar U_dot[5] = {0.}; 1238cbe60e31SLeila Ghaffari U_dot[0] = s_dot.U.density; 1239cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1240cbe60e31SLeila Ghaffari U_dot[j+1] = s_dot.U.momentum[j]; 1241cbe60e31SLeila Ghaffari U_dot[4] = s_dot.U.E_total; 1242cbe60e31SLeila Ghaffari 1243cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 1244cbe60e31SLeila Ghaffari v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 1245cbe60e31SLeila Ghaffari 1246cbe60e31SLeila Ghaffari // jacob_F_conv[3][5][5] = dF(convective)/dq at each direction 1247cbe60e31SLeila Ghaffari CeedScalar jacob_F_conv[3][5][5] = {0}; 1248cbe60e31SLeila Ghaffari computeFluxJacobian_NS(jacob_F_conv, s.U.density, s.Y.velocity, s.U.E_total, 1249cbe60e31SLeila Ghaffari gamma, g, x_i); 1250cbe60e31SLeila Ghaffari CeedScalar grad_U[5][3]; 1251cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 1252cbe60e31SLeila Ghaffari grad_U[0][j] = grad_s[j].U.density; 1253cbe60e31SLeila Ghaffari for (CeedInt k=0; k<3; k++) grad_U[k+1][j] = grad_s[j].U.momentum[k]; 1254cbe60e31SLeila Ghaffari grad_U[4][j] = grad_s[j].U.E_total; 1255cbe60e31SLeila Ghaffari } 1256cbe60e31SLeila Ghaffari 1257cbe60e31SLeila Ghaffari // strong_conv = dF/dq * dq/dx (Strong convection) 1258cbe60e31SLeila Ghaffari CeedScalar strong_conv[5] = {0}; 1259cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1260cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) 1261cbe60e31SLeila Ghaffari for (CeedInt l=0; l<5; l++) 1262cbe60e31SLeila Ghaffari strong_conv[k] += jacob_F_conv[j][k][l] * grad_U[l][j]; 1263cbe60e31SLeila Ghaffari 1264cbe60e31SLeila Ghaffari // Strong residual 1265cbe60e31SLeila Ghaffari CeedScalar strong_res[5]; 1266cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 1267cbe60e31SLeila Ghaffari strong_res[j] = U_dot[j] + strong_conv[j] - body_force[j]; 1268cbe60e31SLeila Ghaffari 1269cbe60e31SLeila Ghaffari // -- Stabilization method: none, SU, or SUPG 1270cbe60e31SLeila Ghaffari CeedScalar stab[5][3] = {{0.}}; 1271cbe60e31SLeila Ghaffari CeedScalar tau_strong_res[5] = {0.}, tau_strong_res_conservative[5] = {0}; 1272cbe60e31SLeila Ghaffari CeedScalar tau_strong_conv[5] = {0.}, tau_strong_conv_conservative[5] = {0}; 1273cbe60e31SLeila Ghaffari CeedScalar Tau_d[3] = {0.}; 1274cbe60e31SLeila Ghaffari switch (context->stabilization) { 1275cbe60e31SLeila Ghaffari case STAB_NONE: // Galerkin 1276cbe60e31SLeila Ghaffari break; 1277cbe60e31SLeila Ghaffari case STAB_SU: // SU 1278cbe60e31SLeila Ghaffari Tau_diagPrim(Tau_d, dXdx, s.Y.velocity, cv, context, mu, dt, s.U.density); 1279cbe60e31SLeila Ghaffari tau_strong_conv[0] = Tau_d[0] * strong_conv[0]; 1280cbe60e31SLeila Ghaffari tau_strong_conv[1] = Tau_d[1] * strong_conv[1]; 1281cbe60e31SLeila Ghaffari tau_strong_conv[2] = Tau_d[1] * strong_conv[2]; 1282cbe60e31SLeila Ghaffari tau_strong_conv[3] = Tau_d[1] * strong_conv[3]; 1283cbe60e31SLeila Ghaffari tau_strong_conv[4] = Tau_d[2] * strong_conv[4]; 1284cbe60e31SLeila Ghaffari PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 1285cbe60e31SLeila Ghaffari tau_strong_conv, tau_strong_conv_conservative); 1286cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1287cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) 1288cbe60e31SLeila Ghaffari for (CeedInt l=0; l<5; l++) 1289cbe60e31SLeila Ghaffari stab[k][j] += jacob_F_conv[j][k][l] * tau_strong_conv_conservative[l]; 1290cbe60e31SLeila Ghaffari 1291cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 1292cbe60e31SLeila Ghaffari for (CeedInt k=0; k<3; k++) 1293cbe60e31SLeila Ghaffari Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 1294cbe60e31SLeila Ghaffari stab[j][1] * dXdx[k][1] + 1295cbe60e31SLeila Ghaffari stab[j][2] * dXdx[k][2]); 1296cbe60e31SLeila Ghaffari 1297cbe60e31SLeila Ghaffari break; 1298cbe60e31SLeila Ghaffari case STAB_SUPG: // SUPG 1299cbe60e31SLeila Ghaffari Tau_diagPrim(Tau_d, dXdx, s.Y.velocity, cv, context, mu, dt, s.U.density); 1300cbe60e31SLeila Ghaffari tau_strong_res[0] = Tau_d[0] * strong_res[0]; 1301cbe60e31SLeila Ghaffari tau_strong_res[1] = Tau_d[1] * strong_res[1]; 1302cbe60e31SLeila Ghaffari tau_strong_res[2] = Tau_d[1] * strong_res[2]; 1303cbe60e31SLeila Ghaffari tau_strong_res[3] = Tau_d[1] * strong_res[3]; 1304cbe60e31SLeila Ghaffari tau_strong_res[4] = Tau_d[2] * strong_res[4]; 1305cbe60e31SLeila Ghaffari 1306cbe60e31SLeila Ghaffari PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 1307cbe60e31SLeila Ghaffari tau_strong_res, tau_strong_res_conservative); 1308cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1309cbe60e31SLeila Ghaffari for (CeedInt k=0; k<5; k++) 1310cbe60e31SLeila Ghaffari for (CeedInt l=0; l<5; l++) 1311cbe60e31SLeila Ghaffari stab[k][j] += jacob_F_conv[j][k][l] * tau_strong_res_conservative[l]; 1312cbe60e31SLeila Ghaffari 1313cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) 1314cbe60e31SLeila Ghaffari for (CeedInt k=0; k<3; k++) 1315cbe60e31SLeila Ghaffari Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 1316cbe60e31SLeila Ghaffari stab[j][1] * dXdx[k][1] + 1317cbe60e31SLeila Ghaffari stab[j][2] * dXdx[k][2]); 1318cbe60e31SLeila Ghaffari break; 1319cbe60e31SLeila Ghaffari } 1320cbe60e31SLeila Ghaffari for (CeedInt j=0; j<5; j++) jac_data[j][i] = Y[j]; 1321cbe60e31SLeila Ghaffari for (CeedInt j=0; j<6; j++) jac_data[5+j][i] = kmstress[j]; 1322cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) jac_data[5+6+j][i] = Tau_d[j]; 1323cbe60e31SLeila Ghaffari 1324cbe60e31SLeila Ghaffari } // End Quadrature Point Loop 1325cbe60e31SLeila Ghaffari 1326cbe60e31SLeila Ghaffari // Return 1327cbe60e31SLeila Ghaffari return 0; 1328cbe60e31SLeila Ghaffari } 1329cbe60e31SLeila Ghaffari 1330cbe60e31SLeila Ghaffari // ***************************************************************************** 1331cbe60e31SLeila Ghaffari // This QFunction implements the jacobean of the Navier-Stokes equations 1332cbe60e31SLeila Ghaffari // in primitive variables for implicit time stepping method. 1333cbe60e31SLeila Ghaffari // 1334cbe60e31SLeila Ghaffari // ***************************************************************************** 1335cbe60e31SLeila Ghaffari CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, 1336cbe60e31SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 1337cbe60e31SLeila Ghaffari // *INDENT-OFF* 1338cbe60e31SLeila Ghaffari // Inputs 1339cbe60e31SLeila Ghaffari const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 1340cbe60e31SLeila Ghaffari (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 1341cbe60e31SLeila Ghaffari (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 1342cbe60e31SLeila Ghaffari (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 1343cbe60e31SLeila Ghaffari (*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 1344cbe60e31SLeila Ghaffari // Outputs 1345cbe60e31SLeila Ghaffari CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 1346cbe60e31SLeila Ghaffari (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 1347cbe60e31SLeila Ghaffari // *INDENT-ON* 1348cbe60e31SLeila Ghaffari // Context 1349cbe60e31SLeila Ghaffari NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 1350cbe60e31SLeila Ghaffari const CeedScalar *g = context->g; 1351cbe60e31SLeila Ghaffari const CeedScalar cp = context->cp; 1352cbe60e31SLeila Ghaffari const CeedScalar cv = context->cv; 1353cbe60e31SLeila Ghaffari const CeedScalar Rd = cp - cv; 1354cbe60e31SLeila Ghaffari const CeedScalar gamma = cp / cv; 1355cbe60e31SLeila Ghaffari 1356cbe60e31SLeila Ghaffari CeedPragmaSIMD 1357cbe60e31SLeila Ghaffari // Quadrature Point Loop 1358cbe60e31SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 1359cbe60e31SLeila Ghaffari // -- Interp-to-Interp q_data 1360cbe60e31SLeila Ghaffari const CeedScalar wdetJ = q_data[0][i]; 1361cbe60e31SLeila Ghaffari // -- Interp-to-Grad q_data 1362cbe60e31SLeila Ghaffari // ---- Inverse of change of coordinate matrix: X_i,j 1363cbe60e31SLeila Ghaffari // *INDENT-OFF* 1364cbe60e31SLeila Ghaffari const CeedScalar dXdx[3][3] = {{q_data[1][i], 1365cbe60e31SLeila Ghaffari q_data[2][i], 1366cbe60e31SLeila Ghaffari q_data[3][i]}, 1367cbe60e31SLeila Ghaffari {q_data[4][i], 1368cbe60e31SLeila Ghaffari q_data[5][i], 1369cbe60e31SLeila Ghaffari q_data[6][i]}, 1370cbe60e31SLeila Ghaffari {q_data[7][i], 1371cbe60e31SLeila Ghaffari q_data[8][i], 1372cbe60e31SLeila Ghaffari q_data[9][i]} 1373cbe60e31SLeila Ghaffari }; 1374cbe60e31SLeila Ghaffari // *INDENT-ON* 1375cbe60e31SLeila Ghaffari 1376cbe60e31SLeila Ghaffari CeedScalar Y[5], kmstress[6], Tau_d[3] __attribute((unused)); 1377cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) Y[j] = jac_data[j][i]; 1378cbe60e31SLeila Ghaffari for (int j=0; j<6; j++) kmstress[j] = jac_data[5+j][i]; 1379cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) Tau_d[j] = jac_data[5+6+j][i]; 1380cbe60e31SLeila Ghaffari const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 1381cbe60e31SLeila Ghaffari State s = StateFromY(context, Y, x_i); 1382cbe60e31SLeila Ghaffari 1383cbe60e31SLeila Ghaffari CeedScalar dY[5], dx0[3] = {0}; 1384cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) dY[j] = dq[j][i]; 1385cbe60e31SLeila Ghaffari State ds = StateFromY_fwd(context, s, dY, x_i, dx0); 1386cbe60e31SLeila Ghaffari 1387cbe60e31SLeila Ghaffari State grad_ds[3]; 1388cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) { 1389cbe60e31SLeila Ghaffari CeedScalar dYj[5]; 1390cbe60e31SLeila Ghaffari for (int k=0; k<5; k++) 1391cbe60e31SLeila Ghaffari dYj[k] = Grad_dq[0][k][i] * dXdx[0][j] + 1392cbe60e31SLeila Ghaffari Grad_dq[1][k][i] * dXdx[1][j] + 1393cbe60e31SLeila Ghaffari Grad_dq[2][k][i] * dXdx[2][j]; 1394cbe60e31SLeila Ghaffari grad_ds[j] = StateFromY_fwd(context, s, dYj, x_i, dx0); 1395cbe60e31SLeila Ghaffari } 1396cbe60e31SLeila Ghaffari 1397cbe60e31SLeila Ghaffari CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 1398cbe60e31SLeila Ghaffari KMStrainRate(grad_ds, dstrain_rate); 1399cbe60e31SLeila Ghaffari NewtonianStress(context, dstrain_rate, dkmstress); 1400cbe60e31SLeila Ghaffari KMUnpack(dkmstress, dstress); 1401cbe60e31SLeila Ghaffari KMUnpack(kmstress, stress); 1402cbe60e31SLeila Ghaffari ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 1403cbe60e31SLeila Ghaffari 1404cbe60e31SLeila Ghaffari StateConservative dF_inviscid[3]; 1405cbe60e31SLeila Ghaffari FluxInviscid_fwd(context, s, ds, dF_inviscid); 1406cbe60e31SLeila Ghaffari 1407cbe60e31SLeila Ghaffari // Total flux 1408cbe60e31SLeila Ghaffari CeedScalar dFlux[5][3]; 1409cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) { 1410cbe60e31SLeila Ghaffari dFlux[0][j] = dF_inviscid[j].density; 1411cbe60e31SLeila Ghaffari for (int k=0; k<3; k++) 1412cbe60e31SLeila Ghaffari dFlux[k+1][j] = dF_inviscid[j].momentum[k] - dstress[k][j]; 1413cbe60e31SLeila Ghaffari dFlux[4][j] = dF_inviscid[j].E_total + dFe[j]; 1414cbe60e31SLeila Ghaffari } 1415cbe60e31SLeila Ghaffari 1416cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) { 1417cbe60e31SLeila Ghaffari for (int k=0; k<5; k++) { 1418cbe60e31SLeila Ghaffari Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + 1419cbe60e31SLeila Ghaffari dXdx[j][1] * dFlux[k][1] + 1420cbe60e31SLeila Ghaffari dXdx[j][2] * dFlux[k][2]); 1421cbe60e31SLeila Ghaffari } 1422cbe60e31SLeila Ghaffari } 1423cbe60e31SLeila Ghaffari 1424cbe60e31SLeila Ghaffari const CeedScalar dbody_force[5] = {0, 1425cbe60e31SLeila Ghaffari ds.U.density *g[0], 1426cbe60e31SLeila Ghaffari ds.U.density *g[1], 1427cbe60e31SLeila Ghaffari ds.U.density *g[2], 1428cbe60e31SLeila Ghaffari 0 1429cbe60e31SLeila Ghaffari }; 1430cbe60e31SLeila Ghaffari CeedScalar dU[5] = {0.}; 1431cbe60e31SLeila Ghaffari dU[0] = ds.U.density; 1432cbe60e31SLeila Ghaffari for (CeedInt j=0; j<3; j++) 1433cbe60e31SLeila Ghaffari dU[j+1] = ds.U.momentum[j]; 1434cbe60e31SLeila Ghaffari dU[4] = ds.U.E_total; 1435cbe60e31SLeila Ghaffari 1436cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) 1437cbe60e31SLeila Ghaffari v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 1438cbe60e31SLeila Ghaffari 1439cbe60e31SLeila Ghaffari if (1) { 1440cbe60e31SLeila Ghaffari CeedScalar jacob_F_conv[3][5][5] = {0}; 1441cbe60e31SLeila Ghaffari computeFluxJacobian_NS(jacob_F_conv, s.U.density, s.Y.velocity, s.U.E_total, 1442cbe60e31SLeila Ghaffari gamma, g, x_i); 1443cbe60e31SLeila Ghaffari CeedScalar grad_dU[5][3]; 1444cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) { 1445cbe60e31SLeila Ghaffari grad_dU[0][j] = grad_ds[j].U.density; 1446cbe60e31SLeila Ghaffari for (int k=0; k<3; k++) grad_dU[k+1][j] = grad_ds[j].U.momentum[k]; 1447cbe60e31SLeila Ghaffari grad_dU[4][j] = grad_ds[j].U.E_total; 1448cbe60e31SLeila Ghaffari } 1449cbe60e31SLeila Ghaffari CeedScalar dstrong_conv[5] = {0.}; 1450cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) 1451cbe60e31SLeila Ghaffari for (int k=0; k<5; k++) 1452cbe60e31SLeila Ghaffari for (int l=0; l<5; l++) 1453cbe60e31SLeila Ghaffari dstrong_conv[k] += jacob_F_conv[j][k][l] * grad_dU[l][j]; 1454cbe60e31SLeila Ghaffari 1455cbe60e31SLeila Ghaffari CeedScalar dstrong_res[5]; 1456cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) 1457cbe60e31SLeila Ghaffari dstrong_res[j] = context->ijacobian_time_shift * dU[j] + 1458cbe60e31SLeila Ghaffari dstrong_conv[j] - 1459cbe60e31SLeila Ghaffari dbody_force[j]; 1460cbe60e31SLeila Ghaffari 1461cbe60e31SLeila Ghaffari CeedScalar dtau_strong_res[5] = {0.}, 1462cbe60e31SLeila Ghaffari dtau_strong_res_conservative[5] = {0.}; 1463cbe60e31SLeila Ghaffari dtau_strong_res[0] = Tau_d[0] * dstrong_res[0]; 1464cbe60e31SLeila Ghaffari dtau_strong_res[1] = Tau_d[1] * dstrong_res[1]; 1465cbe60e31SLeila Ghaffari dtau_strong_res[2] = Tau_d[1] * dstrong_res[2]; 1466cbe60e31SLeila Ghaffari dtau_strong_res[3] = Tau_d[1] * dstrong_res[3]; 1467cbe60e31SLeila Ghaffari dtau_strong_res[4] = Tau_d[2] * dstrong_res[4]; 1468cbe60e31SLeila Ghaffari PrimitiveToConservative_fwd(s.U.density, s.Y.velocity, s.U.E_total, Rd, cv, 1469cbe60e31SLeila Ghaffari dtau_strong_res, dtau_strong_res_conservative); 1470cbe60e31SLeila Ghaffari CeedScalar dstab[5][3] = {0}; 1471cbe60e31SLeila Ghaffari for (int j=0; j<3; j++) 1472cbe60e31SLeila Ghaffari for (int k=0; k<5; k++) 1473cbe60e31SLeila Ghaffari for (int l=0; l<5; l++) 1474cbe60e31SLeila Ghaffari dstab[k][j] += jacob_F_conv[j][k][l] * dtau_strong_res_conservative[l]; 1475cbe60e31SLeila Ghaffari 1476cbe60e31SLeila Ghaffari for (int j=0; j<5; j++) 1477cbe60e31SLeila Ghaffari for (int k=0; k<3; k++) 1478cbe60e31SLeila Ghaffari Grad_v[k][j][i] += wdetJ*(dstab[j][0] * dXdx[k][0] + 1479cbe60e31SLeila Ghaffari dstab[j][1] * dXdx[k][1] + 1480cbe60e31SLeila Ghaffari dstab[j][2] * dXdx[k][2]); 1481cbe60e31SLeila Ghaffari 1482cbe60e31SLeila Ghaffari } 1483cbe60e31SLeila Ghaffari } // End Quadrature Point Loop 1484cbe60e31SLeila Ghaffari return 0; 1485cbe60e31SLeila Ghaffari } 1486cbe60e31SLeila Ghaffari // ***************************************************************************** 1487cbe60e31SLeila Ghaffari 14883a8779fbSJames Wright #endif // newtonian_h 1489