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 // ***************************************************************************** 247*3d02368aSJames Wright CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, 248*3d02368aSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 249*3d02368aSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 25088b783a1SJames Wright // *INDENT-OFF* 25188b783a1SJames Wright // Inputs 25288b783a1SJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 253a3ae0734SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 25488b783a1SJames Wright (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 25588b783a1SJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 25688b783a1SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 25788b783a1SJames Wright // Outputs 25888b783a1SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 259a3ae0734SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1], 260a3ae0734SJed Brown (*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 26188b783a1SJames Wright // *INDENT-ON* 26288b783a1SJames Wright // Context 26388b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 26488626eedSJames Wright const CeedScalar *g = context->g; 26588626eedSJames Wright const CeedScalar dt = context->dt; 26688b783a1SJames Wright 26788b783a1SJames Wright CeedPragmaSIMD 26888b783a1SJames Wright // Quadrature Point Loop 26988b783a1SJames Wright for (CeedInt i=0; i<Q; i++) { 270*3d02368aSJames Wright CeedScalar qi[5]; 271*3d02368aSJames Wright for (CeedInt j=0; j<5; j++) qi[j] = q[j][i]; 2725c677226SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 273*3d02368aSJames Wright State s = StateFromQi(context, qi, x_i); 2745c677226SJed Brown 27588b783a1SJames Wright // -- Interp-to-Interp q_data 27688b783a1SJames Wright const CeedScalar wdetJ = q_data[0][i]; 27788b783a1SJames Wright // -- Interp-to-Grad q_data 27888b783a1SJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 27988b783a1SJames Wright // *INDENT-OFF* 28023d6ba15SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 28123d6ba15SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 28223d6ba15SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 28388b783a1SJames Wright }; 28488b783a1SJames Wright // *INDENT-ON* 2855c677226SJed Brown State grad_s[3]; 286ba6664aeSJames Wright for (CeedInt j=0; j<3; j++) { 287*3d02368aSJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 28839c69132SJed Brown for (CeedInt k=0; k<5; k++) 289*3d02368aSJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 29039c69132SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 29139c69132SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 2925c677226SJed Brown dx_i[j] = 1.; 293*3d02368aSJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 29488b783a1SJames Wright } 2955c677226SJed Brown 2965c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 2975c677226SJed Brown KMStrainRate(grad_s, strain_rate); 2985c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 2995c677226SJed Brown KMUnpack(kmstress, stress); 3005c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 3015c677226SJed Brown 3025c677226SJed Brown StateConservative F_inviscid[3]; 3035c677226SJed Brown FluxInviscid(context, s, F_inviscid); 3045c677226SJed Brown 3055c677226SJed Brown // Total flux 3065c677226SJed Brown CeedScalar Flux[5][3]; 3072b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 3085c677226SJed Brown 3092b89d87eSLeila Ghaffari for (CeedInt j=0; j<3; j++) 3102b89d87eSLeila Ghaffari for (CeedInt k=0; k<5; k++) 311a3ae0734SJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + 3125c677226SJed Brown dXdx[j][1] * Flux[k][1] + 3135c677226SJed Brown dXdx[j][2] * Flux[k][2]); 3145c677226SJed Brown 3155c677226SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 31688b783a1SJames Wright 3172b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 318*3d02368aSJames Wright CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}, qi_dot[5], dx0[3] = {0}; 319*3d02368aSJames Wright for (int j=0; j<5; j++) qi_dot[j] = q_dot[j][i]; 320*3d02368aSJames Wright State s_dot = StateFromQi_fwd(context, s, qi_dot, x_i, dx0); 321*3d02368aSJames Wright UnpackState_U(s_dot.U, U_dot); 322*3d02368aSJames Wright 323*3d02368aSJames Wright for (CeedInt j=0; j<5; j++) 324*3d02368aSJames Wright v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 3252b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 3262b89d87eSLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 32788b783a1SJames Wright 328ba6664aeSJames Wright for (CeedInt j=0; j<5; j++) 329ba6664aeSJames Wright for (CeedInt k=0; k<3; k++) 330a3ae0734SJed Brown Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 33188b783a1SJames Wright stab[j][1] * dXdx[k][1] + 33288b783a1SJames Wright stab[j][2] * dXdx[k][2]); 3333c4b7af6SJed Brown 334*3d02368aSJames Wright for (CeedInt j=0; j<5; j++) jac_data[j][i] = qi[j]; 3353c4b7af6SJed Brown for (CeedInt j=0; j<6; j++) jac_data[5+j][i] = kmstress[j]; 3363c4b7af6SJed Brown for (CeedInt j=0; j<3; j++) jac_data[5+6+j][i] = Tau_d[j]; 33788b783a1SJames Wright 33888b783a1SJames Wright } // End Quadrature Point Loop 33988b783a1SJames Wright 34088b783a1SJames Wright // Return 34188b783a1SJames Wright return 0; 34288b783a1SJames Wright } 343e334ad8fSJed Brown 344*3d02368aSJames Wright CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, 345*3d02368aSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 346*3d02368aSJames Wright return IFunction_Newtonian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 347*3d02368aSJames Wright } 348*3d02368aSJames Wright 349*3d02368aSJames Wright CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, 350*3d02368aSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 351*3d02368aSJames Wright return IFunction_Newtonian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 352*3d02368aSJames Wright } 353*3d02368aSJames Wright 354dc805cc4SLeila Ghaffari // ***************************************************************************** 355*3d02368aSJames Wright // This QFunction implements the jacobian of the Navier-Stokes equations 356dc805cc4SLeila Ghaffari // for implicit time stepping method. 357dc805cc4SLeila Ghaffari // ***************************************************************************** 358*3d02368aSJames Wright CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, 359*3d02368aSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 360*3d02368aSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 361e334ad8fSJed Brown // *INDENT-OFF* 362e334ad8fSJed Brown // Inputs 363e334ad8fSJed Brown const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 364e334ad8fSJed Brown (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 365e334ad8fSJed Brown (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 366e334ad8fSJed Brown (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 367e334ad8fSJed Brown (*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 368e334ad8fSJed Brown // Outputs 369e334ad8fSJed Brown CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 370e334ad8fSJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 371e334ad8fSJed Brown // *INDENT-ON* 372e334ad8fSJed Brown // Context 373e334ad8fSJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 374e334ad8fSJed Brown const CeedScalar *g = context->g; 375e334ad8fSJed Brown 376e334ad8fSJed Brown CeedPragmaSIMD 377e334ad8fSJed Brown // Quadrature Point Loop 378e334ad8fSJed Brown for (CeedInt i=0; i<Q; i++) { 379e334ad8fSJed Brown // -- Interp-to-Interp q_data 380e334ad8fSJed Brown const CeedScalar wdetJ = q_data[0][i]; 381e334ad8fSJed Brown // -- Interp-to-Grad q_data 382e334ad8fSJed Brown // ---- Inverse of change of coordinate matrix: X_i,j 383e334ad8fSJed Brown // *INDENT-OFF* 38423d6ba15SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 38523d6ba15SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 38623d6ba15SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 387e334ad8fSJed Brown }; 388e334ad8fSJed Brown // *INDENT-ON* 389e334ad8fSJed Brown 390*3d02368aSJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3] __attribute((unused)); 391*3d02368aSJames Wright for (int j=0; j<5; j++) qi[j] = jac_data[j][i]; 392e334ad8fSJed Brown for (int j=0; j<6; j++) kmstress[j] = jac_data[5+j][i]; 393e334ad8fSJed Brown for (int j=0; j<3; j++) Tau_d[j] = jac_data[5+6+j][i]; 394e334ad8fSJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 395*3d02368aSJames Wright State s = StateFromQi(context, qi, x_i); 396e334ad8fSJed Brown 397*3d02368aSJames Wright CeedScalar dqi[5], dx0[3] = {0}; 398*3d02368aSJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 399*3d02368aSJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx0); 400e334ad8fSJed Brown 401e334ad8fSJed Brown State grad_ds[3]; 402e334ad8fSJed Brown for (int j=0; j<3; j++) { 403*3d02368aSJames Wright CeedScalar dqi_j[5]; 4042b89d87eSLeila Ghaffari for (int k=0; k<5; k++) 405*3d02368aSJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 4062b89d87eSLeila Ghaffari Grad_dq[1][k][i] * dXdx[1][j] + 4072b89d87eSLeila Ghaffari Grad_dq[2][k][i] * dXdx[2][j]; 408*3d02368aSJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx0); 409e334ad8fSJed Brown } 410e334ad8fSJed Brown 411e334ad8fSJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 412e334ad8fSJed Brown KMStrainRate(grad_ds, dstrain_rate); 413e334ad8fSJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 414e334ad8fSJed Brown KMUnpack(dkmstress, dstress); 415e334ad8fSJed Brown KMUnpack(kmstress, stress); 416e334ad8fSJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 417e334ad8fSJed Brown 418e334ad8fSJed Brown StateConservative dF_inviscid[3]; 419e334ad8fSJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 420e334ad8fSJed Brown 421e334ad8fSJed Brown // Total flux 422e334ad8fSJed Brown CeedScalar dFlux[5][3]; 4232b89d87eSLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 424e334ad8fSJed Brown 4252b89d87eSLeila Ghaffari for (int j=0; j<3; j++) 4262b89d87eSLeila Ghaffari for (int k=0; k<5; k++) 427e334ad8fSJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + 428e334ad8fSJed Brown dXdx[j][1] * dFlux[k][1] + 429e334ad8fSJed Brown dXdx[j][2] * dFlux[k][2]); 430e334ad8fSJed Brown 431e334ad8fSJed Brown const CeedScalar dbody_force[5] = {0, ds.U.density *g[0], ds.U.density *g[1], ds.U.density *g[2], 0}; 432*3d02368aSJames Wright CeedScalar dU[5] = {0.}; 433*3d02368aSJames Wright UnpackState_U(ds.U, dU); 434e334ad8fSJed Brown for (int j=0; j<5; j++) 435e334ad8fSJed Brown v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 436e334ad8fSJed Brown 4372b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 4382b89d87eSLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 4392b89d87eSLeila Ghaffari for (CeedInt j=0; j<5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 4402b89d87eSLeila Ghaffari Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, x_i, dstab); 4412b89d87eSLeila Ghaffari 442e334ad8fSJed Brown for (int j=0; j<5; j++) 443e334ad8fSJed Brown for (int k=0; k<3; k++) 444e334ad8fSJed Brown Grad_v[k][j][i] += wdetJ*(dstab[j][0] * dXdx[k][0] + 445e334ad8fSJed Brown dstab[j][1] * dXdx[k][1] + 446e334ad8fSJed Brown dstab[j][2] * dXdx[k][2]); 447e334ad8fSJed Brown 448e334ad8fSJed Brown } // End Quadrature Point Loop 449e334ad8fSJed Brown return 0; 450e334ad8fSJed Brown } 45165dd5cafSJames Wright 452*3d02368aSJames Wright CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, 453*3d02368aSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 454*3d02368aSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 455*3d02368aSJames Wright } 456*3d02368aSJames Wright 457*3d02368aSJames Wright CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, 458*3d02368aSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 459*3d02368aSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 460*3d02368aSJames Wright } 461*3d02368aSJames Wright 4622b89d87eSLeila Ghaffari // ***************************************************************************** 46365dd5cafSJames Wright // Compute boundary integral (ie. for strongly set inflows) 4642b89d87eSLeila Ghaffari // ***************************************************************************** 46520840d50SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, 46620840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out, 46720840d50SJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 46865dd5cafSJames Wright 46965dd5cafSJames Wright //*INDENT-OFF* 47065dd5cafSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 4712c4e60d7SJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 4722c4e60d7SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 4732c4e60d7SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 47465dd5cafSJames Wright 475b55ac660SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[0], 476b55ac660SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[1]; 47765dd5cafSJames Wright 47865dd5cafSJames Wright //*INDENT-ON* 47965dd5cafSJames Wright 4802c4e60d7SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext) ctx; 4812c4e60d7SJames Wright const bool is_implicit = context->is_implicit; 48265dd5cafSJames Wright 48365dd5cafSJames Wright CeedPragmaSIMD 48465dd5cafSJames Wright for(CeedInt i=0; i<Q; i++) { 4852c4e60d7SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 486efe9d856SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 487efe9d856SJames Wright State s = StateFromQi(context, qi, x_i); 48865dd5cafSJames Wright 48965dd5cafSJames Wright const CeedScalar wdetJb = (is_implicit ? -1. : 1.) * q_data_sur[0][i]; 4905bce47c7SJames Wright // ---- Normal vector 49165dd5cafSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 49265dd5cafSJames Wright q_data_sur[2][i], 49365dd5cafSJames Wright q_data_sur[3][i] 49465dd5cafSJames Wright }; 49565dd5cafSJames Wright 4962c4e60d7SJames Wright const CeedScalar dXdx[2][3] = { 4972c4e60d7SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 4982c4e60d7SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 4992c4e60d7SJames Wright }; 50065dd5cafSJames Wright 5012c4e60d7SJames Wright State grad_s[3]; 5022c4e60d7SJames Wright for (CeedInt j=0; j<3; j++) { 503efe9d856SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 5042c4e60d7SJames Wright for (CeedInt k=0; k<5; k++) 505efe9d856SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 5062c4e60d7SJames Wright Grad_q[1][k][i] * dXdx[1][j]; 5072c4e60d7SJames Wright dx_i[j] = 1.; 508efe9d856SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 5092c4e60d7SJames Wright } 51065dd5cafSJames Wright 5112c4e60d7SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 5122c4e60d7SJames Wright KMStrainRate(grad_s, strain_rate); 5132c4e60d7SJames Wright NewtonianStress(context, strain_rate, kmstress); 5142c4e60d7SJames Wright KMUnpack(kmstress, stress); 5152c4e60d7SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 5162c4e60d7SJames Wright 5172c4e60d7SJames Wright StateConservative F_inviscid[3]; 5182c4e60d7SJames Wright FluxInviscid(context, s, F_inviscid); 5192c4e60d7SJames Wright 5205bce47c7SJames Wright CeedScalar Flux[5]; 5215bce47c7SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 5222c4e60d7SJames Wright 5235bce47c7SJames Wright for (CeedInt j=0; j<5; j++) v[j][i] = -wdetJb * Flux[j]; 52465dd5cafSJames Wright 5255bce47c7SJames Wright for (int j=0; j<5; j++) jac_data_sur[j][i] = qi[j]; 526b55ac660SJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 52765dd5cafSJames Wright } 52865dd5cafSJames Wright return 0; 52965dd5cafSJames Wright } 53065dd5cafSJames Wright 53120840d50SJames Wright CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, 53220840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 53320840d50SJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromU, StateFromU_fwd); 53420840d50SJames Wright } 53520840d50SJames Wright 53620840d50SJames Wright CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, 53720840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 53820840d50SJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromY, StateFromY_fwd); 53920840d50SJames Wright } 54020840d50SJames Wright 5412b89d87eSLeila Ghaffari // ***************************************************************************** 542b55ac660SJames Wright // Jacobian for "set nothing" boundary integral 5432b89d87eSLeila Ghaffari // ***************************************************************************** 54420840d50SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, 54520840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out, 54620840d50SJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 547b55ac660SJames Wright // *INDENT-OFF* 548b55ac660SJames Wright // Inputs 549b55ac660SJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 550b55ac660SJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 551b55ac660SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 552b55ac660SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 553b55ac660SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 554b55ac660SJames Wright // Outputs 555b55ac660SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 556b55ac660SJames Wright // *INDENT-ON* 557b55ac660SJames Wright 558b55ac660SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 559b55ac660SJames Wright const bool implicit = context->is_implicit; 560b55ac660SJames Wright 561b55ac660SJames Wright CeedPragmaSIMD 562b55ac660SJames Wright // Quadrature Point Loop 563b55ac660SJames Wright for (CeedInt i=0; i<Q; i++) { 564b55ac660SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 565b55ac660SJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 566b55ac660SJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 567b55ac660SJames Wright q_data_sur[2][i], 568b55ac660SJames Wright q_data_sur[3][i] 569b55ac660SJames Wright }; 570b55ac660SJames Wright const CeedScalar dXdx[2][3] = { 571b55ac660SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 572b55ac660SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 573b55ac660SJames Wright }; 574b55ac660SJames Wright 575efe9d856SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 576efe9d856SJames Wright for (int j=0; j<5; j++) qi[j] = jac_data_sur[j][i]; 577b55ac660SJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 578efe9d856SJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 57957e55a1cSJames Wright 580efe9d856SJames Wright State s = StateFromQi(context, qi, x_i); 581efe9d856SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 582b55ac660SJames Wright 583b55ac660SJames Wright State grad_ds[3]; 584b55ac660SJames Wright for (CeedInt j=0; j<3; j++) { 585efe9d856SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 586b55ac660SJames Wright for (CeedInt k=0; k<5; k++) 587efe9d856SJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 588b55ac660SJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 589b55ac660SJames Wright dx_i[j] = 1.; 590efe9d856SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 591b55ac660SJames Wright } 592b55ac660SJames Wright 593b55ac660SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 594b55ac660SJames Wright KMStrainRate(grad_ds, dstrain_rate); 595b55ac660SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 596b55ac660SJames Wright KMUnpack(dkmstress, dstress); 597b55ac660SJames Wright KMUnpack(kmstress, stress); 598b55ac660SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 599b55ac660SJames Wright 600b55ac660SJames Wright StateConservative dF_inviscid[3]; 601b55ac660SJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 602b55ac660SJames Wright 6035bce47c7SJames Wright CeedScalar dFlux[5]; 6045bce47c7SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 605b55ac660SJames Wright 6065bce47c7SJames Wright for (int j=0; j<5; j++) v[j][i] = -wdetJb * dFlux[j]; 607b55ac660SJames Wright } // End Quadrature Point Loop 608b55ac660SJames Wright return 0; 609b55ac660SJames Wright } 610b55ac660SJames Wright 61120840d50SJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, 61220840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 61320840d50SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 61420840d50SJames Wright } 61520840d50SJames Wright 61620840d50SJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, 61720840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 61820840d50SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 61920840d50SJames Wright } 62020840d50SJames Wright 6212b89d87eSLeila Ghaffari // ***************************************************************************** 62230e9fa81SJames Wright // Outflow boundary condition, weakly setting a constant pressure 6232b89d87eSLeila Ghaffari // ***************************************************************************** 62420840d50SJames Wright CEED_QFUNCTION_HELPER int PressureOutflow(void *ctx, CeedInt Q, 62520840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out, 62620840d50SJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 62730e9fa81SJames Wright // *INDENT-OFF* 62830e9fa81SJames Wright // Inputs 62930e9fa81SJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 630ce9b5c20SJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 631ce9b5c20SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 632ce9b5c20SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 63330e9fa81SJames Wright // Outputs 63430e9fa81SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 63530e9fa81SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 63630e9fa81SJames Wright // *INDENT-ON* 63730e9fa81SJames Wright 63830e9fa81SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 63930e9fa81SJames Wright const bool implicit = context->is_implicit; 64030e9fa81SJames Wright const CeedScalar P0 = context->P0; 64130e9fa81SJames Wright 64230e9fa81SJames Wright CeedPragmaSIMD 64330e9fa81SJames Wright // Quadrature Point Loop 64430e9fa81SJames Wright for (CeedInt i=0; i<Q; i++) { 64530e9fa81SJames Wright // Setup 64630e9fa81SJames Wright // -- Interp in 647ce9b5c20SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 648efe9d856SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 649efe9d856SJames Wright State s = StateFromQi(context, qi, x_i); 650ce9b5c20SJames Wright s.Y.pressure = P0; 65130e9fa81SJames Wright 65230e9fa81SJames Wright // -- Interp-to-Interp q_data 65330e9fa81SJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 65430e9fa81SJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 65530e9fa81SJames Wright // We can effect this by swapping the sign on this weight 65630e9fa81SJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 65730e9fa81SJames Wright 6585bce47c7SJames Wright // ---- Normal vector 65920840d50SJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 66030e9fa81SJames Wright 661ce9b5c20SJames Wright const CeedScalar dXdx[2][3] = { 662ce9b5c20SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 663ce9b5c20SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 664ce9b5c20SJames Wright }; 66530e9fa81SJames Wright 666ce9b5c20SJames Wright State grad_s[3]; 667ce9b5c20SJames Wright for (CeedInt j=0; j<3; j++) { 668efe9d856SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 669ce9b5c20SJames Wright for (CeedInt k=0; k<5; k++) 670efe9d856SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 671ce9b5c20SJames Wright Grad_q[1][k][i] * dXdx[1][j]; 672ce9b5c20SJames Wright dx_i[j] = 1.; 673efe9d856SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 674ce9b5c20SJames Wright } 675ce9b5c20SJames Wright 676ce9b5c20SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 677ce9b5c20SJames Wright KMStrainRate(grad_s, strain_rate); 678ce9b5c20SJames Wright NewtonianStress(context, strain_rate, kmstress); 679ce9b5c20SJames Wright KMUnpack(kmstress, stress); 680ce9b5c20SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 681ce9b5c20SJames Wright 682ce9b5c20SJames Wright StateConservative F_inviscid[3]; 683ce9b5c20SJames Wright FluxInviscid(context, s, F_inviscid); 684ce9b5c20SJames Wright 6855bce47c7SJames Wright CeedScalar Flux[5]; 6865bce47c7SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 68730e9fa81SJames Wright 6885bce47c7SJames Wright for (CeedInt j=0; j<5; j++) v[j][i] = -wdetJb * Flux[j]; 68930e9fa81SJames Wright 69030e9fa81SJames Wright // Save values for Jacobian 6915bce47c7SJames Wright for (int j=0; j<5; j++) jac_data_sur[j][i] = qi[j]; 6920ec2498eSJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 69330e9fa81SJames Wright } // End Quadrature Point Loop 69430e9fa81SJames Wright return 0; 69530e9fa81SJames Wright } 69630e9fa81SJames Wright 69720840d50SJames Wright CEED_QFUNCTION(PressureOutflow_Conserv)(void *ctx, CeedInt Q, 69820840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 69920840d50SJames Wright return PressureOutflow(ctx, Q, in, out, StateFromU, StateFromU_fwd); 70020840d50SJames Wright } 70120840d50SJames Wright 70220840d50SJames Wright CEED_QFUNCTION(PressureOutflow_Prim)(void *ctx, CeedInt Q, 70320840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 70420840d50SJames Wright return PressureOutflow(ctx, Q, in, out, StateFromY, StateFromY_fwd); 70520840d50SJames Wright } 70620840d50SJames Wright 7072b89d87eSLeila Ghaffari // ***************************************************************************** 70830e9fa81SJames Wright // Jacobian for weak-pressure outflow boundary condition 7092b89d87eSLeila Ghaffari // ***************************************************************************** 71020840d50SJames Wright CEED_QFUNCTION_HELPER int PressureOutflow_Jacobian(void *ctx, CeedInt Q, 71120840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out, 71220840d50SJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 71330e9fa81SJames Wright // *INDENT-OFF* 71430e9fa81SJames Wright // Inputs 71530e9fa81SJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 7160ec2498eSJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 7170ec2498eSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 7180ec2498eSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 7190ec2498eSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 72030e9fa81SJames Wright // Outputs 72130e9fa81SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 72230e9fa81SJames Wright // *INDENT-ON* 72330e9fa81SJames Wright 72430e9fa81SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 72530e9fa81SJames Wright const bool implicit = context->is_implicit; 72630e9fa81SJames Wright 72730e9fa81SJames Wright CeedPragmaSIMD 72830e9fa81SJames Wright // Quadrature Point Loop 72930e9fa81SJames Wright for (CeedInt i=0; i<Q; i++) { 7300ec2498eSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 73130e9fa81SJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 73220840d50SJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 7330ec2498eSJames Wright const CeedScalar dXdx[2][3] = { 7340ec2498eSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 7350ec2498eSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 7360ec2498eSJames Wright }; 7370ec2498eSJames Wright 738efe9d856SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 739efe9d856SJames Wright for (int j=0; j<5; j++) qi[j] = jac_data_sur[j][i]; 7400ec2498eSJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 741efe9d856SJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 74257e55a1cSJames Wright 743efe9d856SJames Wright State s = StateFromQi(context, qi, x_i); 744efe9d856SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 7450ec2498eSJames Wright s.Y.pressure = context->P0; 7460ec2498eSJames Wright ds.Y.pressure = 0.; 7470ec2498eSJames Wright 7480ec2498eSJames Wright State grad_ds[3]; 7490ec2498eSJames Wright for (CeedInt j=0; j<3; j++) { 750efe9d856SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 7510ec2498eSJames Wright for (CeedInt k=0; k<5; k++) 752efe9d856SJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 7530ec2498eSJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 7540ec2498eSJames Wright dx_i[j] = 1.; 755efe9d856SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 7560ec2498eSJames Wright } 7570ec2498eSJames Wright 7580ec2498eSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 7590ec2498eSJames Wright KMStrainRate(grad_ds, dstrain_rate); 7600ec2498eSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 7610ec2498eSJames Wright KMUnpack(dkmstress, dstress); 7620ec2498eSJames Wright KMUnpack(kmstress, stress); 7630ec2498eSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 76430e9fa81SJames Wright 765b5d317f8SJames Wright StateConservative dF_inviscid[3]; 766b5d317f8SJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 76730e9fa81SJames Wright 7685bce47c7SJames Wright CeedScalar dFlux[5]; 7695bce47c7SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 770b5d317f8SJames Wright 7715bce47c7SJames Wright for (int j=0; j<5; j++) v[j][i] = -wdetJb * dFlux[j]; 77230e9fa81SJames Wright } // End Quadrature Point Loop 77330e9fa81SJames Wright return 0; 77430e9fa81SJames Wright } 77530e9fa81SJames Wright 77620840d50SJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Conserv)(void *ctx, CeedInt Q, 77720840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 77820840d50SJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 77920840d50SJames Wright } 78020840d50SJames Wright 78120840d50SJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Prim)(void *ctx, CeedInt Q, 78220840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 78320840d50SJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 78420840d50SJames Wright } 78520840d50SJames Wright 78688b783a1SJames Wright #endif // newtonian_h 787