13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 388b783a1SJames Wright // 43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 588b783a1SJames Wright // 63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 788b783a1SJames Wright 888b783a1SJames Wright /// @file 988b783a1SJames Wright /// Operator for Navier-Stokes example using PETSc 1088b783a1SJames Wright 1188b783a1SJames Wright 1288b783a1SJames Wright #ifndef newtonian_h 1388b783a1SJames Wright #define newtonian_h 1488b783a1SJames Wright 1588b783a1SJames Wright #include <ceed.h> 16c9c2c079SJeremy L Thompson #include <math.h> 17c6e8c570SJames Wright #include "newtonian_state.h" 18c9c2c079SJeremy L Thompson #include "newtonian_types.h" 192b89d87eSLeila Ghaffari #include "stabilization.h" 20c9c2c079SJeremy L Thompson #include "utils.h" 2188626eedSJames Wright 2288626eedSJames Wright // ***************************************************************************** 2388b783a1SJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 2488b783a1SJames Wright // ***************************************************************************** 2588b783a1SJames Wright CEED_QFUNCTION(ICsNewtonianIG)(void *ctx, CeedInt Q, 2688b783a1SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 2788b783a1SJames Wright // Inputs 2888b783a1SJames Wright const CeedScalar (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 2988b783a1SJames Wright 3088b783a1SJames Wright // Outputs 3188b783a1SJames Wright CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 3288b783a1SJames Wright 3388626eedSJames Wright // Context 3488626eedSJames Wright const SetupContext context = (SetupContext)ctx; 3588626eedSJames Wright const CeedScalar theta0 = context->theta0; 3688626eedSJames Wright const CeedScalar P0 = context->P0; 3788626eedSJames Wright const CeedScalar cv = context->cv; 3888626eedSJames Wright const CeedScalar cp = context->cp; 3988626eedSJames Wright const CeedScalar *g = context->g; 4088626eedSJames Wright const CeedScalar Rd = cp - cv; 4188626eedSJames Wright 4288b783a1SJames Wright // Quadrature Point Loop 4388b783a1SJames Wright CeedPragmaSIMD 4488b783a1SJames Wright for (CeedInt i=0; i<Q; i++) { 4588b783a1SJames Wright CeedScalar q[5] = {0.}; 4688b783a1SJames Wright 4788b783a1SJames Wright // Setup 4888b783a1SJames Wright // -- Coordinates 4988626eedSJames Wright const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]}; 502b89d87eSLeila Ghaffari const CeedScalar e_potential = -Dot3(g, x); 5188b783a1SJames Wright 5288b783a1SJames Wright // -- Density 5388626eedSJames Wright const CeedScalar rho = P0 / (Rd*theta0); 5488b783a1SJames Wright 5588b783a1SJames Wright // Initial Conditions 5688b783a1SJames Wright q[0] = rho; 5788b783a1SJames Wright q[1] = 0.0; 5888b783a1SJames Wright q[2] = 0.0; 5988b783a1SJames Wright q[3] = 0.0; 6088626eedSJames Wright q[4] = rho * (cv*theta0 + e_potential); 6188b783a1SJames Wright 6288b783a1SJames Wright for (CeedInt j=0; j<5; j++) 6388b783a1SJames Wright q0[j][i] = q[j]; 642b89d87eSLeila Ghaffari 6588b783a1SJames Wright } // End of Quadrature Point Loop 6688b783a1SJames Wright return 0; 6788b783a1SJames Wright } 6888b783a1SJames Wright 6988b783a1SJames Wright // ***************************************************************************** 70dc805cc4SLeila Ghaffari // This QFunction sets a "still" initial condition for generic Newtonian IG 71dc805cc4SLeila Ghaffari // problems in primitive variables 72dc805cc4SLeila Ghaffari // ***************************************************************************** 73dc805cc4SLeila Ghaffari CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, 74dc805cc4SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 75dc805cc4SLeila Ghaffari // Outputs 76dc805cc4SLeila Ghaffari CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 77dc805cc4SLeila Ghaffari 78dc805cc4SLeila Ghaffari // Context 79dc805cc4SLeila Ghaffari const SetupContext context = (SetupContext)ctx; 80dc805cc4SLeila Ghaffari const CeedScalar theta0 = context->theta0; 81dc805cc4SLeila Ghaffari const CeedScalar P0 = context->P0; 82dc805cc4SLeila Ghaffari 83dc805cc4SLeila Ghaffari // Quadrature Point Loop 84dc805cc4SLeila Ghaffari CeedPragmaSIMD 85dc805cc4SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 86dc805cc4SLeila Ghaffari CeedScalar q[5] = {0.}; 87dc805cc4SLeila Ghaffari 88dc805cc4SLeila Ghaffari // Initial Conditions 89dc805cc4SLeila Ghaffari q[0] = P0; 90dc805cc4SLeila Ghaffari q[1] = 0.0; 91dc805cc4SLeila Ghaffari q[2] = 0.0; 92dc805cc4SLeila Ghaffari q[3] = 0.0; 93dc805cc4SLeila Ghaffari q[4] = theta0; 94dc805cc4SLeila Ghaffari 95dc805cc4SLeila Ghaffari for (CeedInt j=0; j<5; j++) 96dc805cc4SLeila Ghaffari q0[j][i] = q[j]; 97dc805cc4SLeila Ghaffari 98dc805cc4SLeila Ghaffari } // End of Quadrature Point Loop 99dc805cc4SLeila Ghaffari return 0; 100dc805cc4SLeila Ghaffari } 101dc805cc4SLeila Ghaffari 102dc805cc4SLeila Ghaffari // ***************************************************************************** 10388b783a1SJames Wright // This QFunction implements the following formulation of Navier-Stokes with 10488b783a1SJames Wright // explicit time stepping method 10588b783a1SJames Wright // 10688b783a1SJames Wright // This is 3D compressible Navier-Stokes in conservation form with state 10788b783a1SJames Wright // variables of density, momentum density, and total energy density. 10888b783a1SJames Wright // 10988b783a1SJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 11088b783a1SJames Wright // rho - Mass Density 11188b783a1SJames Wright // Ui - Momentum Density, Ui = rho ui 11288b783a1SJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 11388b783a1SJames Wright // 11488b783a1SJames Wright // Navier-Stokes Equations: 11588b783a1SJames Wright // drho/dt + div( U ) = 0 11688b783a1SJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 11788b783a1SJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 11888b783a1SJames Wright // 11988b783a1SJames Wright // Viscous Stress: 12088b783a1SJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 12188b783a1SJames Wright // 12288b783a1SJames Wright // Thermal Stress: 12388b783a1SJames Wright // Fe = u Fu + k grad( T ) 12488626eedSJames Wright // Equation of State 12588b783a1SJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 12688b783a1SJames Wright // 12788b783a1SJames Wright // Stabilization: 12888b783a1SJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 12988b783a1SJames Wright // f1 = rho sqrt(ui uj gij) 13088b783a1SJames Wright // gij = dXi/dX * dXi/dX 13188b783a1SJames Wright // TauC = Cc f1 / (8 gii) 13288b783a1SJames Wright // TauM = min( 1 , 1 / f1 ) 13388b783a1SJames Wright // TauE = TauM / (Ce cv) 13488b783a1SJames Wright // 13588b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 13688b783a1SJames Wright // 13788b783a1SJames Wright // Constants: 13888b783a1SJames Wright // lambda = - 2 / 3, From Stokes hypothesis 13988b783a1SJames Wright // mu , Dynamic viscosity 14088b783a1SJames Wright // k , Thermal conductivity 14188b783a1SJames Wright // cv , Specific heat, constant volume 14288b783a1SJames Wright // cp , Specific heat, constant pressure 14388b783a1SJames Wright // g , Gravity 14488b783a1SJames Wright // gamma = cp / cv, Specific heat ratio 14588b783a1SJames Wright // 14688b783a1SJames Wright // We require the product of the inverse of the Jacobian (dXdx_j,k) and 14788b783a1SJames Wright // its transpose (dXdx_k,j) to properly compute integrals of the form: 14888b783a1SJames Wright // int( gradv gradu ) 14988b783a1SJames Wright // 15088b783a1SJames Wright // ***************************************************************************** 1515c677226SJed Brown CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, 15288b783a1SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 15388b783a1SJames Wright // *INDENT-OFF* 15488b783a1SJames Wright // Inputs 15588b783a1SJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 156a3ae0734SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 15788b783a1SJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 15888b783a1SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 15988b783a1SJames Wright // Outputs 16088b783a1SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 161a3ae0734SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 16288b783a1SJames Wright // *INDENT-ON* 16388b783a1SJames Wright 16488b783a1SJames Wright // Context 16588b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 16688626eedSJames Wright const CeedScalar *g = context->g; 16788626eedSJames Wright const CeedScalar dt = context->dt; 16888b783a1SJames Wright 16988b783a1SJames Wright CeedPragmaSIMD 17088b783a1SJames Wright // Quadrature Point Loop 17188b783a1SJames Wright for (CeedInt i=0; i<Q; i++) { 1725c677226SJed Brown CeedScalar U[5]; 1735c677226SJed Brown for (int j=0; j<5; j++) U[j] = q[j][i]; 1745c677226SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 1755c677226SJed Brown State s = StateFromU(context, U, x_i); 1765c677226SJed Brown 17788b783a1SJames Wright // -- Interp-to-Interp q_data 17888b783a1SJames Wright const CeedScalar wdetJ = q_data[0][i]; 17988b783a1SJames Wright // -- Interp-to-Grad q_data 18088b783a1SJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 18188b783a1SJames Wright // *INDENT-OFF* 18223d6ba15SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 18323d6ba15SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 18423d6ba15SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 18588b783a1SJames Wright }; 18688b783a1SJames Wright // *INDENT-ON* 1875c677226SJed Brown State grad_s[3]; 1883c4b7af6SJed Brown for (CeedInt j=0; j<3; j++) { 1896f00d0e6SJed Brown CeedScalar dx_i[3] = {0}, dU[5]; 19039c69132SJed Brown for (CeedInt k=0; k<5; k++) 19139c69132SJed Brown dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 19239c69132SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 19339c69132SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 1945c677226SJed Brown dx_i[j] = 1.; 1956f00d0e6SJed Brown grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 1965c677226SJed Brown } 1975c677226SJed Brown 1985c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 1995c677226SJed Brown KMStrainRate(grad_s, strain_rate); 2005c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 2015c677226SJed Brown KMUnpack(kmstress, stress); 2025c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 2035c677226SJed Brown 2045c677226SJed Brown StateConservative F_inviscid[3]; 2055c677226SJed Brown FluxInviscid(context, s, F_inviscid); 2065c677226SJed Brown 2075c677226SJed Brown // Total flux 2085c677226SJed Brown CeedScalar Flux[5][3]; 2092b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 2105c677226SJed Brown 2112b89d87eSLeila Ghaffari for (CeedInt j=0; j<3; j++) 2122b89d87eSLeila Ghaffari for (CeedInt k=0; k<5; k++) 213a3ae0734SJed Brown Grad_v[j][k][i] = wdetJ * (dXdx[j][0] * Flux[k][0] + 2145c677226SJed Brown dXdx[j][1] * Flux[k][1] + 2155c677226SJed Brown dXdx[j][2] * Flux[k][2]); 2165c677226SJed Brown 2175c677226SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 2185c677226SJed Brown for (int j=0; j<5; j++) 2195c677226SJed Brown v[j][i] = wdetJ * body_force[j]; 22088b783a1SJames Wright 2212b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 2222b89d87eSLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 2232b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 2242b89d87eSLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 22588b783a1SJames Wright 226ba6664aeSJames Wright for (CeedInt j=0; j<5; j++) 227ba6664aeSJames Wright for (CeedInt k=0; k<3; k++) 228a3ae0734SJed Brown Grad_v[k][j][i] -= wdetJ*(stab[j][0] * dXdx[k][0] + 22988b783a1SJames Wright stab[j][1] * dXdx[k][1] + 23088b783a1SJames Wright stab[j][2] * dXdx[k][2]); 23188b783a1SJames Wright 23288b783a1SJames Wright } // End Quadrature Point Loop 23388b783a1SJames Wright 23488b783a1SJames Wright // Return 23588b783a1SJames Wright return 0; 23688b783a1SJames Wright } 23788b783a1SJames Wright 23888b783a1SJames Wright // ***************************************************************************** 23988b783a1SJames Wright // This QFunction implements the Navier-Stokes equations (mentioned above) with 24088b783a1SJames Wright // implicit time stepping method 24188b783a1SJames Wright // 24288b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 24388b783a1SJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 24488b783a1SJames Wright // (diffussive terms will be added later) 24588b783a1SJames Wright // 24688b783a1SJames Wright // ***************************************************************************** 24788b783a1SJames Wright CEED_QFUNCTION(IFunction_Newtonian)(void *ctx, CeedInt Q, 248dc805cc4SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 24988b783a1SJames Wright // *INDENT-OFF* 25088b783a1SJames Wright // Inputs 25188b783a1SJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 252a3ae0734SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 25388b783a1SJames Wright (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 25488b783a1SJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 25588b783a1SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 25688b783a1SJames Wright // Outputs 25788b783a1SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 258a3ae0734SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1], 259a3ae0734SJed Brown (*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 26088b783a1SJames Wright // *INDENT-ON* 26188b783a1SJames Wright // Context 26288b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 26388626eedSJames Wright const CeedScalar *g = context->g; 26488626eedSJames Wright const CeedScalar dt = context->dt; 26588b783a1SJames Wright 26688b783a1SJames Wright CeedPragmaSIMD 26788b783a1SJames Wright // Quadrature Point Loop 26888b783a1SJames Wright for (CeedInt i=0; i<Q; i++) { 2695c677226SJed Brown CeedScalar U[5]; 2703c4b7af6SJed Brown for (CeedInt j=0; j<5; j++) U[j] = q[j][i]; 2715c677226SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 2725c677226SJed Brown State s = StateFromU(context, U, x_i); 2735c677226SJed Brown 27488b783a1SJames Wright // -- Interp-to-Interp q_data 27588b783a1SJames Wright const CeedScalar wdetJ = q_data[0][i]; 27688b783a1SJames Wright // -- Interp-to-Grad q_data 27788b783a1SJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 27888b783a1SJames Wright // *INDENT-OFF* 27923d6ba15SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 28023d6ba15SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 28123d6ba15SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 28288b783a1SJames Wright }; 28388b783a1SJames Wright // *INDENT-ON* 2845c677226SJed Brown State grad_s[3]; 285ba6664aeSJames Wright for (CeedInt j=0; j<3; j++) { 2866f00d0e6SJed Brown CeedScalar dx_i[3] = {0}, dU[5]; 28739c69132SJed Brown for (CeedInt k=0; k<5; k++) 28839c69132SJed Brown dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 28939c69132SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 29039c69132SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 2915c677226SJed Brown dx_i[j] = 1.; 2926f00d0e6SJed Brown grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 29388b783a1SJames Wright } 2945c677226SJed Brown 2955c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 2965c677226SJed Brown KMStrainRate(grad_s, strain_rate); 2975c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 2985c677226SJed Brown KMUnpack(kmstress, stress); 2995c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 3005c677226SJed Brown 3015c677226SJed Brown StateConservative F_inviscid[3]; 3025c677226SJed Brown FluxInviscid(context, s, F_inviscid); 3035c677226SJed Brown 3045c677226SJed Brown // Total flux 3055c677226SJed Brown CeedScalar Flux[5][3]; 3062b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 3075c677226SJed Brown 3082b89d87eSLeila Ghaffari for (CeedInt j=0; j<3; j++) 3092b89d87eSLeila Ghaffari for (CeedInt k=0; k<5; k++) 310a3ae0734SJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + 3115c677226SJed Brown dXdx[j][1] * Flux[k][1] + 3125c677226SJed Brown dXdx[j][2] * Flux[k][2]); 3135c677226SJed Brown 3145c677226SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 3153c4b7af6SJed Brown for (CeedInt j=0; j<5; j++) 3165c677226SJed Brown v[j][i] = wdetJ * (q_dot[j][i] - body_force[j]); 31788b783a1SJames Wright 3182b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 3192b89d87eSLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 3202b89d87eSLeila Ghaffari for (CeedInt j=0; j<5; j++) U_dot[j] = q_dot[j][i]; 3212b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 3222b89d87eSLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 32388b783a1SJames Wright 324ba6664aeSJames Wright for (CeedInt j=0; j<5; j++) 325ba6664aeSJames Wright for (CeedInt k=0; k<3; k++) 326a3ae0734SJed Brown Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 32788b783a1SJames Wright stab[j][1] * dXdx[k][1] + 32888b783a1SJames Wright stab[j][2] * dXdx[k][2]); 3293c4b7af6SJed Brown 3303c4b7af6SJed Brown for (CeedInt j=0; j<5; j++) jac_data[j][i] = U[j]; 3313c4b7af6SJed Brown for (CeedInt j=0; j<6; j++) jac_data[5+j][i] = kmstress[j]; 3323c4b7af6SJed Brown for (CeedInt j=0; j<3; j++) jac_data[5+6+j][i] = Tau_d[j]; 33388b783a1SJames Wright 33488b783a1SJames Wright } // End Quadrature Point Loop 33588b783a1SJames Wright 33688b783a1SJames Wright // Return 33788b783a1SJames Wright return 0; 33888b783a1SJames Wright } 339e334ad8fSJed Brown 340dc805cc4SLeila Ghaffari // ***************************************************************************** 341dc805cc4SLeila Ghaffari // This QFunction implements the jacobean of the Navier-Stokes equations 342dc805cc4SLeila Ghaffari // for implicit time stepping method. 343dc805cc4SLeila Ghaffari // 344dc805cc4SLeila Ghaffari // ***************************************************************************** 345e334ad8fSJed Brown CEED_QFUNCTION(IJacobian_Newtonian)(void *ctx, CeedInt Q, 346e334ad8fSJed Brown const CeedScalar *const *in, 347e334ad8fSJed Brown CeedScalar *const *out) { 348e334ad8fSJed Brown // *INDENT-OFF* 349e334ad8fSJed Brown // Inputs 350e334ad8fSJed Brown const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 351e334ad8fSJed Brown (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 352e334ad8fSJed Brown (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 353e334ad8fSJed Brown (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 354e334ad8fSJed Brown (*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 355e334ad8fSJed Brown // Outputs 356e334ad8fSJed Brown CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 357e334ad8fSJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 358e334ad8fSJed Brown // *INDENT-ON* 359e334ad8fSJed Brown // Context 360e334ad8fSJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 361e334ad8fSJed Brown const CeedScalar *g = context->g; 362e334ad8fSJed Brown 363e334ad8fSJed Brown CeedPragmaSIMD 364e334ad8fSJed Brown // Quadrature Point Loop 365e334ad8fSJed Brown for (CeedInt i=0; i<Q; i++) { 366e334ad8fSJed Brown // -- Interp-to-Interp q_data 367e334ad8fSJed Brown const CeedScalar wdetJ = q_data[0][i]; 368e334ad8fSJed Brown // -- Interp-to-Grad q_data 369e334ad8fSJed Brown // ---- Inverse of change of coordinate matrix: X_i,j 370e334ad8fSJed Brown // *INDENT-OFF* 37123d6ba15SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 37223d6ba15SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 37323d6ba15SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 374e334ad8fSJed Brown }; 375e334ad8fSJed Brown // *INDENT-ON* 376e334ad8fSJed Brown 377e334ad8fSJed Brown CeedScalar U[5], kmstress[6], Tau_d[3] __attribute((unused)); 378e334ad8fSJed Brown for (int j=0; j<5; j++) U[j] = jac_data[j][i]; 379e334ad8fSJed Brown for (int j=0; j<6; j++) kmstress[j] = jac_data[5+j][i]; 380e334ad8fSJed Brown for (int j=0; j<3; j++) Tau_d[j] = jac_data[5+6+j][i]; 381e334ad8fSJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 382e334ad8fSJed Brown State s = StateFromU(context, U, x_i); 383e334ad8fSJed Brown 384e334ad8fSJed Brown CeedScalar dU[5], dx0[3] = {0}; 385e334ad8fSJed Brown for (int j=0; j<5; j++) dU[j] = dq[j][i]; 386e334ad8fSJed Brown State ds = StateFromU_fwd(context, s, dU, x_i, dx0); 387e334ad8fSJed Brown 388e334ad8fSJed Brown State grad_ds[3]; 389e334ad8fSJed Brown for (int j=0; j<3; j++) { 390e334ad8fSJed Brown CeedScalar dUj[5]; 3912b89d87eSLeila Ghaffari for (int k=0; k<5; k++) 3922b89d87eSLeila Ghaffari dUj[k] = Grad_dq[0][k][i] * dXdx[0][j] + 3932b89d87eSLeila Ghaffari Grad_dq[1][k][i] * dXdx[1][j] + 3942b89d87eSLeila Ghaffari Grad_dq[2][k][i] * dXdx[2][j]; 395e334ad8fSJed Brown grad_ds[j] = StateFromU_fwd(context, s, dUj, x_i, dx0); 396e334ad8fSJed Brown } 397e334ad8fSJed Brown 398e334ad8fSJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 399e334ad8fSJed Brown KMStrainRate(grad_ds, dstrain_rate); 400e334ad8fSJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 401e334ad8fSJed Brown KMUnpack(dkmstress, dstress); 402e334ad8fSJed Brown KMUnpack(kmstress, stress); 403e334ad8fSJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 404e334ad8fSJed Brown 405e334ad8fSJed Brown StateConservative dF_inviscid[3]; 406e334ad8fSJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 407e334ad8fSJed Brown 408e334ad8fSJed Brown // Total flux 409e334ad8fSJed Brown CeedScalar dFlux[5][3]; 4102b89d87eSLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 411e334ad8fSJed Brown 4122b89d87eSLeila Ghaffari for (int j=0; j<3; j++) 4132b89d87eSLeila Ghaffari for (int k=0; k<5; k++) 414e334ad8fSJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + 415e334ad8fSJed Brown dXdx[j][1] * dFlux[k][1] + 416e334ad8fSJed Brown dXdx[j][2] * dFlux[k][2]); 417e334ad8fSJed Brown 418e334ad8fSJed Brown const CeedScalar dbody_force[5] = {0, ds.U.density *g[0], ds.U.density *g[1], ds.U.density *g[2], 0}; 419e334ad8fSJed Brown for (int j=0; j<5; j++) 420e334ad8fSJed Brown v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 421e334ad8fSJed Brown 4222b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 4232b89d87eSLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 4242b89d87eSLeila Ghaffari for (CeedInt j=0; j<5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 4252b89d87eSLeila Ghaffari Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, x_i, dstab); 4262b89d87eSLeila Ghaffari 427e334ad8fSJed Brown for (int j=0; j<5; j++) 428e334ad8fSJed Brown for (int k=0; k<3; k++) 429e334ad8fSJed Brown Grad_v[k][j][i] += wdetJ*(dstab[j][0] * dXdx[k][0] + 430e334ad8fSJed Brown dstab[j][1] * dXdx[k][1] + 431e334ad8fSJed Brown dstab[j][2] * dXdx[k][2]); 432e334ad8fSJed Brown 433e334ad8fSJed Brown } // End Quadrature Point Loop 434e334ad8fSJed Brown return 0; 435e334ad8fSJed Brown } 43665dd5cafSJames Wright 4372b89d87eSLeila Ghaffari // ***************************************************************************** 43865dd5cafSJames Wright // Compute boundary integral (ie. for strongly set inflows) 4392b89d87eSLeila Ghaffari // ***************************************************************************** 440*20840d50SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, 441*20840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out, 442*20840d50SJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 44365dd5cafSJames Wright 44465dd5cafSJames Wright //*INDENT-OFF* 44565dd5cafSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 4462c4e60d7SJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 4472c4e60d7SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 4482c4e60d7SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 44965dd5cafSJames Wright 450b55ac660SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[0], 451b55ac660SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[1]; 45265dd5cafSJames Wright 45365dd5cafSJames Wright //*INDENT-ON* 45465dd5cafSJames Wright 4552c4e60d7SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext) ctx; 4562c4e60d7SJames Wright const bool is_implicit = context->is_implicit; 45765dd5cafSJames Wright 45865dd5cafSJames Wright CeedPragmaSIMD 45965dd5cafSJames Wright for(CeedInt i=0; i<Q; i++) { 4602c4e60d7SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 461efe9d856SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 462efe9d856SJames Wright State s = StateFromQi(context, qi, x_i); 46365dd5cafSJames Wright 46465dd5cafSJames Wright const CeedScalar wdetJb = (is_implicit ? -1. : 1.) * q_data_sur[0][i]; 4655bce47c7SJames Wright // ---- Normal vector 46665dd5cafSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 46765dd5cafSJames Wright q_data_sur[2][i], 46865dd5cafSJames Wright q_data_sur[3][i] 46965dd5cafSJames Wright }; 47065dd5cafSJames Wright 4712c4e60d7SJames Wright const CeedScalar dXdx[2][3] = { 4722c4e60d7SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 4732c4e60d7SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 4742c4e60d7SJames Wright }; 47565dd5cafSJames Wright 4762c4e60d7SJames Wright State grad_s[3]; 4772c4e60d7SJames Wright for (CeedInt j=0; j<3; j++) { 478efe9d856SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 4792c4e60d7SJames Wright for (CeedInt k=0; k<5; k++) 480efe9d856SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 4812c4e60d7SJames Wright Grad_q[1][k][i] * dXdx[1][j]; 4822c4e60d7SJames Wright dx_i[j] = 1.; 483efe9d856SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 4842c4e60d7SJames Wright } 48565dd5cafSJames Wright 4862c4e60d7SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 4872c4e60d7SJames Wright KMStrainRate(grad_s, strain_rate); 4882c4e60d7SJames Wright NewtonianStress(context, strain_rate, kmstress); 4892c4e60d7SJames Wright KMUnpack(kmstress, stress); 4902c4e60d7SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 4912c4e60d7SJames Wright 4922c4e60d7SJames Wright StateConservative F_inviscid[3]; 4932c4e60d7SJames Wright FluxInviscid(context, s, F_inviscid); 4942c4e60d7SJames Wright 4955bce47c7SJames Wright CeedScalar Flux[5]; 4965bce47c7SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 4972c4e60d7SJames Wright 4985bce47c7SJames Wright for (CeedInt j=0; j<5; j++) v[j][i] = -wdetJb * Flux[j]; 49965dd5cafSJames Wright 5005bce47c7SJames Wright for (int j=0; j<5; j++) jac_data_sur[j][i] = qi[j]; 501b55ac660SJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 50265dd5cafSJames Wright } 50365dd5cafSJames Wright return 0; 50465dd5cafSJames Wright } 50565dd5cafSJames Wright 506*20840d50SJames Wright CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, 507*20840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 508*20840d50SJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromU, StateFromU_fwd); 509*20840d50SJames Wright } 510*20840d50SJames Wright 511*20840d50SJames Wright CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, 512*20840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 513*20840d50SJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromY, StateFromY_fwd); 514*20840d50SJames Wright } 515*20840d50SJames Wright 5162b89d87eSLeila Ghaffari // ***************************************************************************** 517b55ac660SJames Wright // Jacobian for "set nothing" boundary integral 5182b89d87eSLeila Ghaffari // ***************************************************************************** 519*20840d50SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, 520*20840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out, 521*20840d50SJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 522b55ac660SJames Wright // *INDENT-OFF* 523b55ac660SJames Wright // Inputs 524b55ac660SJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 525b55ac660SJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 526b55ac660SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 527b55ac660SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 528b55ac660SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 529b55ac660SJames Wright // Outputs 530b55ac660SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 531b55ac660SJames Wright // *INDENT-ON* 532b55ac660SJames Wright 533b55ac660SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 534b55ac660SJames Wright const bool implicit = context->is_implicit; 535b55ac660SJames Wright 536b55ac660SJames Wright CeedPragmaSIMD 537b55ac660SJames Wright // Quadrature Point Loop 538b55ac660SJames Wright for (CeedInt i=0; i<Q; i++) { 539b55ac660SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 540b55ac660SJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 541b55ac660SJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 542b55ac660SJames Wright q_data_sur[2][i], 543b55ac660SJames Wright q_data_sur[3][i] 544b55ac660SJames Wright }; 545b55ac660SJames Wright const CeedScalar dXdx[2][3] = { 546b55ac660SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 547b55ac660SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 548b55ac660SJames Wright }; 549b55ac660SJames Wright 550efe9d856SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 551efe9d856SJames Wright for (int j=0; j<5; j++) qi[j] = jac_data_sur[j][i]; 552b55ac660SJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 553efe9d856SJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 55457e55a1cSJames Wright 555efe9d856SJames Wright State s = StateFromQi(context, qi, x_i); 556efe9d856SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 557b55ac660SJames Wright 558b55ac660SJames Wright State grad_ds[3]; 559b55ac660SJames Wright for (CeedInt j=0; j<3; j++) { 560efe9d856SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 561b55ac660SJames Wright for (CeedInt k=0; k<5; k++) 562efe9d856SJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 563b55ac660SJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 564b55ac660SJames Wright dx_i[j] = 1.; 565efe9d856SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 566b55ac660SJames Wright } 567b55ac660SJames Wright 568b55ac660SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 569b55ac660SJames Wright KMStrainRate(grad_ds, dstrain_rate); 570b55ac660SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 571b55ac660SJames Wright KMUnpack(dkmstress, dstress); 572b55ac660SJames Wright KMUnpack(kmstress, stress); 573b55ac660SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 574b55ac660SJames Wright 575b55ac660SJames Wright StateConservative dF_inviscid[3]; 576b55ac660SJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 577b55ac660SJames Wright 5785bce47c7SJames Wright CeedScalar dFlux[5]; 5795bce47c7SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 580b55ac660SJames Wright 5815bce47c7SJames Wright for (int j=0; j<5; j++) v[j][i] = -wdetJb * dFlux[j]; 582b55ac660SJames Wright } // End Quadrature Point Loop 583b55ac660SJames Wright return 0; 584b55ac660SJames Wright } 585b55ac660SJames Wright 586*20840d50SJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, 587*20840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 588*20840d50SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 589*20840d50SJames Wright } 590*20840d50SJames Wright 591*20840d50SJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, 592*20840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 593*20840d50SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 594*20840d50SJames Wright } 595*20840d50SJames Wright 5962b89d87eSLeila Ghaffari // ***************************************************************************** 59730e9fa81SJames Wright // Outflow boundary condition, weakly setting a constant pressure 5982b89d87eSLeila Ghaffari // ***************************************************************************** 599*20840d50SJames Wright CEED_QFUNCTION_HELPER int PressureOutflow(void *ctx, CeedInt Q, 600*20840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out, 601*20840d50SJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 60230e9fa81SJames Wright // *INDENT-OFF* 60330e9fa81SJames Wright // Inputs 60430e9fa81SJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 605ce9b5c20SJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 606ce9b5c20SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 607ce9b5c20SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 60830e9fa81SJames Wright // Outputs 60930e9fa81SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 61030e9fa81SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 61130e9fa81SJames Wright // *INDENT-ON* 61230e9fa81SJames Wright 61330e9fa81SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 61430e9fa81SJames Wright const bool implicit = context->is_implicit; 61530e9fa81SJames Wright const CeedScalar P0 = context->P0; 61630e9fa81SJames Wright 61730e9fa81SJames Wright CeedPragmaSIMD 61830e9fa81SJames Wright // Quadrature Point Loop 61930e9fa81SJames Wright for (CeedInt i=0; i<Q; i++) { 62030e9fa81SJames Wright // Setup 62130e9fa81SJames Wright // -- Interp in 622ce9b5c20SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 623efe9d856SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 624efe9d856SJames Wright State s = StateFromQi(context, qi, x_i); 625ce9b5c20SJames Wright s.Y.pressure = P0; 62630e9fa81SJames Wright 62730e9fa81SJames Wright // -- Interp-to-Interp q_data 62830e9fa81SJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 62930e9fa81SJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 63030e9fa81SJames Wright // We can effect this by swapping the sign on this weight 63130e9fa81SJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 63230e9fa81SJames Wright 6335bce47c7SJames Wright // ---- Normal vector 634*20840d50SJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 63530e9fa81SJames Wright 636ce9b5c20SJames Wright const CeedScalar dXdx[2][3] = { 637ce9b5c20SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 638ce9b5c20SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 639ce9b5c20SJames Wright }; 64030e9fa81SJames Wright 641ce9b5c20SJames Wright State grad_s[3]; 642ce9b5c20SJames Wright for (CeedInt j=0; j<3; j++) { 643efe9d856SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 644ce9b5c20SJames Wright for (CeedInt k=0; k<5; k++) 645efe9d856SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 646ce9b5c20SJames Wright Grad_q[1][k][i] * dXdx[1][j]; 647ce9b5c20SJames Wright dx_i[j] = 1.; 648efe9d856SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 649ce9b5c20SJames Wright } 650ce9b5c20SJames Wright 651ce9b5c20SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 652ce9b5c20SJames Wright KMStrainRate(grad_s, strain_rate); 653ce9b5c20SJames Wright NewtonianStress(context, strain_rate, kmstress); 654ce9b5c20SJames Wright KMUnpack(kmstress, stress); 655ce9b5c20SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 656ce9b5c20SJames Wright 657ce9b5c20SJames Wright StateConservative F_inviscid[3]; 658ce9b5c20SJames Wright FluxInviscid(context, s, F_inviscid); 659ce9b5c20SJames Wright 6605bce47c7SJames Wright CeedScalar Flux[5]; 6615bce47c7SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 66230e9fa81SJames Wright 6635bce47c7SJames Wright for (CeedInt j=0; j<5; j++) v[j][i] = -wdetJb * Flux[j]; 66430e9fa81SJames Wright 66530e9fa81SJames Wright // Save values for Jacobian 6665bce47c7SJames Wright for (int j=0; j<5; j++) jac_data_sur[j][i] = qi[j]; 6670ec2498eSJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 66830e9fa81SJames Wright } // End Quadrature Point Loop 66930e9fa81SJames Wright return 0; 67030e9fa81SJames Wright } 67130e9fa81SJames Wright 672*20840d50SJames Wright CEED_QFUNCTION(PressureOutflow_Conserv)(void *ctx, CeedInt Q, 673*20840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 674*20840d50SJames Wright return PressureOutflow(ctx, Q, in, out, StateFromU, StateFromU_fwd); 675*20840d50SJames Wright } 676*20840d50SJames Wright 677*20840d50SJames Wright CEED_QFUNCTION(PressureOutflow_Prim)(void *ctx, CeedInt Q, 678*20840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 679*20840d50SJames Wright return PressureOutflow(ctx, Q, in, out, StateFromY, StateFromY_fwd); 680*20840d50SJames Wright } 681*20840d50SJames Wright 6822b89d87eSLeila Ghaffari // ***************************************************************************** 68330e9fa81SJames Wright // Jacobian for weak-pressure outflow boundary condition 6842b89d87eSLeila Ghaffari // ***************************************************************************** 685*20840d50SJames Wright CEED_QFUNCTION_HELPER int PressureOutflow_Jacobian(void *ctx, CeedInt Q, 686*20840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out, 687*20840d50SJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 68830e9fa81SJames Wright // *INDENT-OFF* 68930e9fa81SJames Wright // Inputs 69030e9fa81SJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 6910ec2498eSJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 6920ec2498eSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 6930ec2498eSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 6940ec2498eSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 69530e9fa81SJames Wright // Outputs 69630e9fa81SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 69730e9fa81SJames Wright // *INDENT-ON* 69830e9fa81SJames Wright 69930e9fa81SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 70030e9fa81SJames Wright const bool implicit = context->is_implicit; 70130e9fa81SJames Wright 70230e9fa81SJames Wright CeedPragmaSIMD 70330e9fa81SJames Wright // Quadrature Point Loop 70430e9fa81SJames Wright for (CeedInt i=0; i<Q; i++) { 7050ec2498eSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 70630e9fa81SJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 707*20840d50SJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 7080ec2498eSJames Wright const CeedScalar dXdx[2][3] = { 7090ec2498eSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 7100ec2498eSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 7110ec2498eSJames Wright }; 7120ec2498eSJames Wright 713efe9d856SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 714efe9d856SJames Wright for (int j=0; j<5; j++) qi[j] = jac_data_sur[j][i]; 7150ec2498eSJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 716efe9d856SJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 71757e55a1cSJames Wright 718efe9d856SJames Wright State s = StateFromQi(context, qi, x_i); 719efe9d856SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 7200ec2498eSJames Wright s.Y.pressure = context->P0; 7210ec2498eSJames Wright ds.Y.pressure = 0.; 7220ec2498eSJames Wright 7230ec2498eSJames Wright State grad_ds[3]; 7240ec2498eSJames Wright for (CeedInt j=0; j<3; j++) { 725efe9d856SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 7260ec2498eSJames Wright for (CeedInt k=0; k<5; k++) 727efe9d856SJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 7280ec2498eSJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 7290ec2498eSJames Wright dx_i[j] = 1.; 730efe9d856SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 7310ec2498eSJames Wright } 7320ec2498eSJames Wright 7330ec2498eSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 7340ec2498eSJames Wright KMStrainRate(grad_ds, dstrain_rate); 7350ec2498eSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 7360ec2498eSJames Wright KMUnpack(dkmstress, dstress); 7370ec2498eSJames Wright KMUnpack(kmstress, stress); 7380ec2498eSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 73930e9fa81SJames Wright 740b5d317f8SJames Wright StateConservative dF_inviscid[3]; 741b5d317f8SJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 74230e9fa81SJames Wright 7435bce47c7SJames Wright CeedScalar dFlux[5]; 7445bce47c7SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 745b5d317f8SJames Wright 7465bce47c7SJames Wright for (int j=0; j<5; j++) v[j][i] = -wdetJb * dFlux[j]; 74730e9fa81SJames Wright } // End Quadrature Point Loop 74830e9fa81SJames Wright return 0; 74930e9fa81SJames Wright } 75030e9fa81SJames Wright 751*20840d50SJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Conserv)(void *ctx, CeedInt Q, 752*20840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 753*20840d50SJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 754*20840d50SJames Wright } 755*20840d50SJames Wright 756*20840d50SJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Prim)(void *ctx, CeedInt Q, 757*20840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 758*20840d50SJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 759*20840d50SJames Wright } 760*20840d50SJames Wright 76188b783a1SJames Wright // ***************************************************************************** 762dc805cc4SLeila Ghaffari // This QFunction implements the Navier-Stokes equations (mentioned above) in 763dc805cc4SLeila Ghaffari // primitive variables and with implicit time stepping method 764dc805cc4SLeila Ghaffari // 765dc805cc4SLeila Ghaffari // ***************************************************************************** 766dc805cc4SLeila Ghaffari CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, 767dc805cc4SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 768dc805cc4SLeila Ghaffari // *INDENT-OFF* 769dc805cc4SLeila Ghaffari // Inputs 770dc805cc4SLeila Ghaffari const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 771dc805cc4SLeila Ghaffari (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 772dc805cc4SLeila Ghaffari (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 773dc805cc4SLeila Ghaffari (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 774dc805cc4SLeila Ghaffari (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 775dc805cc4SLeila Ghaffari // Outputs 776dc805cc4SLeila Ghaffari CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 777dc805cc4SLeila Ghaffari (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1], 778dc805cc4SLeila Ghaffari (*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 779dc805cc4SLeila Ghaffari // *INDENT-ON* 780dc805cc4SLeila Ghaffari // Context 781dc805cc4SLeila Ghaffari NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 782dc805cc4SLeila Ghaffari const CeedScalar *g = context->g; 783dc805cc4SLeila Ghaffari const CeedScalar dt = context->dt; 784dc805cc4SLeila Ghaffari 785dc805cc4SLeila Ghaffari CeedPragmaSIMD 786dc805cc4SLeila Ghaffari // Quadrature Point Loop 787dc805cc4SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 788dc805cc4SLeila Ghaffari CeedScalar Y[5]; 789dc805cc4SLeila Ghaffari for (CeedInt j=0; j<5; j++) Y[j] = q[j][i]; 790dc805cc4SLeila Ghaffari const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 791dc805cc4SLeila Ghaffari State s = StateFromY(context, Y, x_i); 792dc805cc4SLeila Ghaffari 793dc805cc4SLeila Ghaffari // -- Interp-to-Interp q_data 794dc805cc4SLeila Ghaffari const CeedScalar wdetJ = q_data[0][i]; 795dc805cc4SLeila Ghaffari // -- Interp-to-Grad q_data 796dc805cc4SLeila Ghaffari // ---- Inverse of change of coordinate matrix: X_i,j 797dc805cc4SLeila Ghaffari // *INDENT-OFF* 79823d6ba15SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 79923d6ba15SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 80023d6ba15SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 801dc805cc4SLeila Ghaffari }; 802dc805cc4SLeila Ghaffari // *INDENT-ON* 803dc805cc4SLeila Ghaffari State grad_s[3]; 804dc805cc4SLeila Ghaffari for (CeedInt j=0; j<3; j++) { 805dc805cc4SLeila Ghaffari CeedScalar dx_i[3] = {0}, dY[5]; 806dc805cc4SLeila Ghaffari for (CeedInt k=0; k<5; k++) 807dc805cc4SLeila Ghaffari dY[k] = Grad_q[0][k][i] * dXdx[0][j] + 808dc805cc4SLeila Ghaffari Grad_q[1][k][i] * dXdx[1][j] + 809dc805cc4SLeila Ghaffari Grad_q[2][k][i] * dXdx[2][j]; 810dc805cc4SLeila Ghaffari dx_i[j] = 1.; 811dc805cc4SLeila Ghaffari grad_s[j] = StateFromY_fwd(context, s, dY, x_i, dx_i); 812dc805cc4SLeila Ghaffari } 813dc805cc4SLeila Ghaffari 814dc805cc4SLeila Ghaffari CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 815dc805cc4SLeila Ghaffari KMStrainRate(grad_s, strain_rate); 816dc805cc4SLeila Ghaffari NewtonianStress(context, strain_rate, kmstress); 817dc805cc4SLeila Ghaffari KMUnpack(kmstress, stress); 818dc805cc4SLeila Ghaffari ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 819dc805cc4SLeila Ghaffari 820dc805cc4SLeila Ghaffari StateConservative F_inviscid[3]; 821dc805cc4SLeila Ghaffari FluxInviscid(context, s, F_inviscid); 822dc805cc4SLeila Ghaffari 823dc805cc4SLeila Ghaffari // Total flux 824dc805cc4SLeila Ghaffari CeedScalar Flux[5][3]; 8252b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 826dc805cc4SLeila Ghaffari 8272b89d87eSLeila Ghaffari for (CeedInt j=0; j<3; j++) 8282b89d87eSLeila Ghaffari for (CeedInt k=0; k<5; k++) 829dc805cc4SLeila Ghaffari Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + 830dc805cc4SLeila Ghaffari dXdx[j][1] * Flux[k][1] + 831dc805cc4SLeila Ghaffari dXdx[j][2] * Flux[k][2]); 832dc805cc4SLeila Ghaffari 833dc805cc4SLeila Ghaffari const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 834dc805cc4SLeila Ghaffari 835dc805cc4SLeila Ghaffari CeedScalar Y_dot[5], dx0[3] = {0}; 836dc805cc4SLeila Ghaffari for (int j=0; j<5; j++) Y_dot[j] = q_dot[j][i]; 837dc805cc4SLeila Ghaffari State s_dot = StateFromY_fwd(context, s, Y_dot, x_i, dx0); 838dc805cc4SLeila Ghaffari 839dc805cc4SLeila Ghaffari CeedScalar U_dot[5] = {0.}; 8402b89d87eSLeila Ghaffari UnpackState_U(s_dot.U, U_dot); 841dc805cc4SLeila Ghaffari 842dc805cc4SLeila Ghaffari for (CeedInt j=0; j<5; j++) 843dc805cc4SLeila Ghaffari v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 844dc805cc4SLeila Ghaffari 8452b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 8462b89d87eSLeila Ghaffari CeedScalar Tau_d[3], stab[5][3]; 8472b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 8482b89d87eSLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 849dc805cc4SLeila Ghaffari 850dc805cc4SLeila Ghaffari for (CeedInt j=0; j<5; j++) 851dc805cc4SLeila Ghaffari for (CeedInt k=0; k<3; k++) 852dc805cc4SLeila Ghaffari Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 853dc805cc4SLeila Ghaffari stab[j][1] * dXdx[k][1] + 854dc805cc4SLeila Ghaffari stab[j][2] * dXdx[k][2]); 855dc805cc4SLeila Ghaffari 856dc805cc4SLeila Ghaffari for (CeedInt j=0; j<5; j++) jac_data[j][i] = Y[j]; 857dc805cc4SLeila Ghaffari for (CeedInt j=0; j<6; j++) jac_data[5+j][i] = kmstress[j]; 858dc805cc4SLeila Ghaffari for (CeedInt j=0; j<3; j++) jac_data[5+6+j][i] = Tau_d[j]; 859dc805cc4SLeila Ghaffari 860dc805cc4SLeila Ghaffari } // End Quadrature Point Loop 861dc805cc4SLeila Ghaffari 862dc805cc4SLeila Ghaffari // Return 863dc805cc4SLeila Ghaffari return 0; 864dc805cc4SLeila Ghaffari } 865dc805cc4SLeila Ghaffari 866dc805cc4SLeila Ghaffari // ***************************************************************************** 867dc805cc4SLeila Ghaffari // This QFunction implements the jacobean of the Navier-Stokes equations 868dc805cc4SLeila Ghaffari // in primitive variables for implicit time stepping method. 869dc805cc4SLeila Ghaffari // 870dc805cc4SLeila Ghaffari // ***************************************************************************** 871dc805cc4SLeila Ghaffari CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, 872dc805cc4SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 873dc805cc4SLeila Ghaffari // *INDENT-OFF* 874dc805cc4SLeila Ghaffari // Inputs 875dc805cc4SLeila Ghaffari const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 876dc805cc4SLeila Ghaffari (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 877dc805cc4SLeila Ghaffari (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 878dc805cc4SLeila Ghaffari (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 879dc805cc4SLeila Ghaffari (*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 880dc805cc4SLeila Ghaffari // Outputs 881dc805cc4SLeila Ghaffari CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 882dc805cc4SLeila Ghaffari (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 883dc805cc4SLeila Ghaffari // *INDENT-ON* 884dc805cc4SLeila Ghaffari // Context 885dc805cc4SLeila Ghaffari NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 886dc805cc4SLeila Ghaffari const CeedScalar *g = context->g; 887dc805cc4SLeila Ghaffari 888dc805cc4SLeila Ghaffari CeedPragmaSIMD 889dc805cc4SLeila Ghaffari // Quadrature Point Loop 890dc805cc4SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 891dc805cc4SLeila Ghaffari // -- Interp-to-Interp q_data 892dc805cc4SLeila Ghaffari const CeedScalar wdetJ = q_data[0][i]; 893dc805cc4SLeila Ghaffari // -- Interp-to-Grad q_data 894dc805cc4SLeila Ghaffari // ---- Inverse of change of coordinate matrix: X_i,j 895dc805cc4SLeila Ghaffari // *INDENT-OFF* 89623d6ba15SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 89723d6ba15SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 89823d6ba15SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 899dc805cc4SLeila Ghaffari }; 900dc805cc4SLeila Ghaffari // *INDENT-ON* 901dc805cc4SLeila Ghaffari 902dc805cc4SLeila Ghaffari CeedScalar Y[5], kmstress[6], Tau_d[3] __attribute((unused)); 903dc805cc4SLeila Ghaffari for (int j=0; j<5; j++) Y[j] = jac_data[j][i]; 904dc805cc4SLeila Ghaffari for (int j=0; j<6; j++) kmstress[j] = jac_data[5+j][i]; 905dc805cc4SLeila Ghaffari for (int j=0; j<3; j++) Tau_d[j] = jac_data[5+6+j][i]; 906dc805cc4SLeila Ghaffari const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 907dc805cc4SLeila Ghaffari State s = StateFromY(context, Y, x_i); 908dc805cc4SLeila Ghaffari 909dc805cc4SLeila Ghaffari CeedScalar dY[5], dx0[3] = {0}; 910dc805cc4SLeila Ghaffari for (int j=0; j<5; j++) dY[j] = dq[j][i]; 911dc805cc4SLeila Ghaffari State ds = StateFromY_fwd(context, s, dY, x_i, dx0); 912dc805cc4SLeila Ghaffari 913dc805cc4SLeila Ghaffari State grad_ds[3]; 914dc805cc4SLeila Ghaffari for (int j=0; j<3; j++) { 915dc805cc4SLeila Ghaffari CeedScalar dYj[5]; 916dc805cc4SLeila Ghaffari for (int k=0; k<5; k++) 917dc805cc4SLeila Ghaffari dYj[k] = Grad_dq[0][k][i] * dXdx[0][j] + 918dc805cc4SLeila Ghaffari Grad_dq[1][k][i] * dXdx[1][j] + 919dc805cc4SLeila Ghaffari Grad_dq[2][k][i] * dXdx[2][j]; 920dc805cc4SLeila Ghaffari grad_ds[j] = StateFromY_fwd(context, s, dYj, x_i, dx0); 921dc805cc4SLeila Ghaffari } 922dc805cc4SLeila Ghaffari 923dc805cc4SLeila Ghaffari CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 924dc805cc4SLeila Ghaffari KMStrainRate(grad_ds, dstrain_rate); 925dc805cc4SLeila Ghaffari NewtonianStress(context, dstrain_rate, dkmstress); 926dc805cc4SLeila Ghaffari KMUnpack(dkmstress, dstress); 927dc805cc4SLeila Ghaffari KMUnpack(kmstress, stress); 928dc805cc4SLeila Ghaffari ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 929dc805cc4SLeila Ghaffari 930dc805cc4SLeila Ghaffari StateConservative dF_inviscid[3]; 931dc805cc4SLeila Ghaffari FluxInviscid_fwd(context, s, ds, dF_inviscid); 932dc805cc4SLeila Ghaffari 933dc805cc4SLeila Ghaffari // Total flux 934dc805cc4SLeila Ghaffari CeedScalar dFlux[5][3]; 9352b89d87eSLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 936dc805cc4SLeila Ghaffari 9372b89d87eSLeila Ghaffari for (int j=0; j<3; j++) 9382b89d87eSLeila Ghaffari for (int k=0; k<5; k++) 939dc805cc4SLeila Ghaffari Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + 940dc805cc4SLeila Ghaffari dXdx[j][1] * dFlux[k][1] + 941dc805cc4SLeila Ghaffari dXdx[j][2] * dFlux[k][2]); 942dc805cc4SLeila Ghaffari 9432b89d87eSLeila Ghaffari const CeedScalar dbody_force[5] = {0, ds.U.density *g[0], ds.U.density *g[1], ds.U.density *g[2], 0}; 944dc805cc4SLeila Ghaffari CeedScalar dU[5] = {0.}; 9452b89d87eSLeila Ghaffari UnpackState_U(ds.U, dU); 946dc805cc4SLeila Ghaffari 947dc805cc4SLeila Ghaffari for (int j=0; j<5; j++) 948dc805cc4SLeila Ghaffari v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 949dc805cc4SLeila Ghaffari 9502b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 9512b89d87eSLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 9522b89d87eSLeila Ghaffari for (CeedInt j=0; j<5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 9532b89d87eSLeila Ghaffari Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, x_i, dstab); 954dc805cc4SLeila Ghaffari 955dc805cc4SLeila Ghaffari for (int j=0; j<5; j++) 956dc805cc4SLeila Ghaffari for (int k=0; k<3; k++) 957dc805cc4SLeila Ghaffari Grad_v[k][j][i] += wdetJ*(dstab[j][0] * dXdx[k][0] + 958dc805cc4SLeila Ghaffari dstab[j][1] * dXdx[k][1] + 959dc805cc4SLeila Ghaffari dstab[j][2] * dXdx[k][2]); 960dc805cc4SLeila Ghaffari 961dc805cc4SLeila Ghaffari } // End Quadrature Point Loop 962dc805cc4SLeila Ghaffari return 0; 963dc805cc4SLeila Ghaffari } 964dc805cc4SLeila Ghaffari // ***************************************************************************** 965dc805cc4SLeila Ghaffari 96688b783a1SJames Wright #endif // newtonian_h 967