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> 17738af36cSAdelekeBankole #include <stdlib.h> 18738af36cSAdelekeBankole #include "ceed/types.h" 19c6e8c570SJames Wright #include "newtonian_state.h" 20c9c2c079SJeremy L Thompson #include "newtonian_types.h" 212b89d87eSLeila Ghaffari #include "stabilization.h" 22c9c2c079SJeremy L Thompson #include "utils.h" 2388626eedSJames Wright 2488626eedSJames Wright // ***************************************************************************** 2588b783a1SJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 2688b783a1SJames Wright // ***************************************************************************** 2788b783a1SJames Wright CEED_QFUNCTION(ICsNewtonianIG)(void *ctx, CeedInt Q, 2888b783a1SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 2988b783a1SJames Wright // Inputs 3088b783a1SJames Wright const CeedScalar (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 3188b783a1SJames Wright 3288b783a1SJames Wright // Outputs 3388b783a1SJames Wright CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 3488b783a1SJames Wright 3588626eedSJames Wright // Context 3688626eedSJames Wright const SetupContext context = (SetupContext)ctx; 3788626eedSJames Wright const CeedScalar theta0 = context->theta0; 3888626eedSJames Wright const CeedScalar P0 = context->P0; 3988626eedSJames Wright const CeedScalar cv = context->cv; 4088626eedSJames Wright const CeedScalar cp = context->cp; 4188626eedSJames Wright const CeedScalar *g = context->g; 4288626eedSJames Wright const CeedScalar Rd = cp - cv; 4388626eedSJames Wright 4488b783a1SJames Wright // Quadrature Point Loop 4588b783a1SJames Wright CeedPragmaSIMD 4688b783a1SJames Wright for (CeedInt i=0; i<Q; i++) { 4788b783a1SJames Wright CeedScalar q[5] = {0.}; 4888b783a1SJames Wright 4988b783a1SJames Wright // Setup 5088b783a1SJames Wright // -- Coordinates 5188626eedSJames Wright const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]}; 522b89d87eSLeila Ghaffari const CeedScalar e_potential = -Dot3(g, x); 5388b783a1SJames Wright 5488b783a1SJames Wright // -- Density 5588626eedSJames Wright const CeedScalar rho = P0 / (Rd*theta0); 5688b783a1SJames Wright 5788b783a1SJames Wright // Initial Conditions 5888b783a1SJames Wright q[0] = rho; 5988b783a1SJames Wright q[1] = 0.0; 6088b783a1SJames Wright q[2] = 0.0; 6188b783a1SJames Wright q[3] = 0.0; 6288626eedSJames Wright q[4] = rho * (cv*theta0 + e_potential); 6388b783a1SJames Wright 6488b783a1SJames Wright for (CeedInt j=0; j<5; j++) 6588b783a1SJames Wright q0[j][i] = q[j]; 662b89d87eSLeila Ghaffari 6788b783a1SJames Wright } // End of Quadrature Point Loop 6888b783a1SJames Wright return 0; 6988b783a1SJames Wright } 7088b783a1SJames Wright 7188b783a1SJames Wright // ***************************************************************************** 72dc805cc4SLeila Ghaffari // This QFunction sets a "still" initial condition for generic Newtonian IG 73dc805cc4SLeila Ghaffari // problems in primitive variables 74dc805cc4SLeila Ghaffari // ***************************************************************************** 75dc805cc4SLeila Ghaffari CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, 76dc805cc4SLeila Ghaffari const CeedScalar *const *in, CeedScalar *const *out) { 77dc805cc4SLeila Ghaffari // Outputs 78dc805cc4SLeila Ghaffari CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 79dc805cc4SLeila Ghaffari 80dc805cc4SLeila Ghaffari // Context 81dc805cc4SLeila Ghaffari const SetupContext context = (SetupContext)ctx; 82dc805cc4SLeila Ghaffari const CeedScalar theta0 = context->theta0; 83dc805cc4SLeila Ghaffari const CeedScalar P0 = context->P0; 84dc805cc4SLeila Ghaffari 85dc805cc4SLeila Ghaffari // Quadrature Point Loop 86dc805cc4SLeila Ghaffari CeedPragmaSIMD 87dc805cc4SLeila Ghaffari for (CeedInt i=0; i<Q; i++) { 88dc805cc4SLeila Ghaffari CeedScalar q[5] = {0.}; 89dc805cc4SLeila Ghaffari 90dc805cc4SLeila Ghaffari // Initial Conditions 91dc805cc4SLeila Ghaffari q[0] = P0; 92dc805cc4SLeila Ghaffari q[1] = 0.0; 93dc805cc4SLeila Ghaffari q[2] = 0.0; 94dc805cc4SLeila Ghaffari q[3] = 0.0; 95dc805cc4SLeila Ghaffari q[4] = theta0; 96dc805cc4SLeila Ghaffari 97dc805cc4SLeila Ghaffari for (CeedInt j=0; j<5; j++) 98dc805cc4SLeila Ghaffari q0[j][i] = q[j]; 99dc805cc4SLeila Ghaffari 100dc805cc4SLeila Ghaffari } // End of Quadrature Point Loop 101dc805cc4SLeila Ghaffari return 0; 102dc805cc4SLeila Ghaffari } 103dc805cc4SLeila Ghaffari 104dc805cc4SLeila Ghaffari // ***************************************************************************** 10588b783a1SJames Wright // This QFunction implements the following formulation of Navier-Stokes with 10688b783a1SJames Wright // explicit time stepping method 10788b783a1SJames Wright // 10888b783a1SJames Wright // This is 3D compressible Navier-Stokes in conservation form with state 10988b783a1SJames Wright // variables of density, momentum density, and total energy density. 11088b783a1SJames Wright // 11188b783a1SJames Wright // State Variables: q = ( rho, U1, U2, U3, E ) 11288b783a1SJames Wright // rho - Mass Density 11388b783a1SJames Wright // Ui - Momentum Density, Ui = rho ui 11488b783a1SJames Wright // E - Total Energy Density, E = rho (cv T + (u u)/2 + g z) 11588b783a1SJames Wright // 11688b783a1SJames Wright // Navier-Stokes Equations: 11788b783a1SJames Wright // drho/dt + div( U ) = 0 11888b783a1SJames Wright // dU/dt + div( rho (u x u) + P I3 ) + rho g khat = div( Fu ) 11988b783a1SJames Wright // dE/dt + div( (E + P) u ) = div( Fe ) 12088b783a1SJames Wright // 12188b783a1SJames Wright // Viscous Stress: 12288b783a1SJames Wright // Fu = mu (grad( u ) + grad( u )^T + lambda div ( u ) I3) 12388b783a1SJames Wright // 12488b783a1SJames Wright // Thermal Stress: 12588b783a1SJames Wright // Fe = u Fu + k grad( T ) 12688626eedSJames Wright // Equation of State 12788b783a1SJames Wright // P = (gamma - 1) (E - rho (u u) / 2 - rho g z) 12888b783a1SJames Wright // 12988b783a1SJames Wright // Stabilization: 13088b783a1SJames Wright // Tau = diag(TauC, TauM, TauM, TauM, TauE) 13188b783a1SJames Wright // f1 = rho sqrt(ui uj gij) 13288b783a1SJames Wright // gij = dXi/dX * dXi/dX 13388b783a1SJames Wright // TauC = Cc f1 / (8 gii) 13488b783a1SJames Wright // TauM = min( 1 , 1 / f1 ) 13588b783a1SJames Wright // TauE = TauM / (Ce cv) 13688b783a1SJames Wright // 13788b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 13888b783a1SJames Wright // 13988b783a1SJames Wright // Constants: 14088b783a1SJames Wright // lambda = - 2 / 3, From Stokes hypothesis 14188b783a1SJames Wright // mu , Dynamic viscosity 14288b783a1SJames Wright // k , Thermal conductivity 14388b783a1SJames Wright // cv , Specific heat, constant volume 14488b783a1SJames Wright // cp , Specific heat, constant pressure 14588b783a1SJames Wright // g , Gravity 14688b783a1SJames Wright // gamma = cp / cv, Specific heat ratio 14788b783a1SJames Wright // 14888b783a1SJames Wright // We require the product of the inverse of the Jacobian (dXdx_j,k) and 14988b783a1SJames Wright // its transpose (dXdx_k,j) to properly compute integrals of the form: 15088b783a1SJames Wright // int( gradv gradu ) 15188b783a1SJames Wright // 15288b783a1SJames Wright // ***************************************************************************** 1535c677226SJed Brown CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, 15488b783a1SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 15588b783a1SJames Wright // *INDENT-OFF* 15688b783a1SJames Wright // Inputs 15788b783a1SJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 158a3ae0734SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 15988b783a1SJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 16088b783a1SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 16188b783a1SJames Wright // Outputs 16288b783a1SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 163a3ae0734SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 16488b783a1SJames Wright // *INDENT-ON* 16588b783a1SJames Wright 16688b783a1SJames Wright // Context 16788b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 16888626eedSJames Wright const CeedScalar *g = context->g; 16988626eedSJames Wright const CeedScalar dt = context->dt; 17088b783a1SJames Wright 17188b783a1SJames Wright CeedPragmaSIMD 17288b783a1SJames Wright // Quadrature Point Loop 17388b783a1SJames Wright for (CeedInt i=0; i<Q; i++) { 1745c677226SJed Brown CeedScalar U[5]; 1755c677226SJed Brown for (int j=0; j<5; j++) U[j] = q[j][i]; 1765c677226SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 1775c677226SJed Brown State s = StateFromU(context, U, x_i); 1785c677226SJed Brown 17988b783a1SJames Wright // -- Interp-to-Interp q_data 18088b783a1SJames Wright const CeedScalar wdetJ = q_data[0][i]; 18188b783a1SJames Wright // -- Interp-to-Grad q_data 18288b783a1SJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 18388b783a1SJames Wright // *INDENT-OFF* 18423d6ba15SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 18523d6ba15SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 18623d6ba15SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 18788b783a1SJames Wright }; 18888b783a1SJames Wright // *INDENT-ON* 1895c677226SJed Brown State grad_s[3]; 1903c4b7af6SJed Brown for (CeedInt j=0; j<3; j++) { 1916f00d0e6SJed Brown CeedScalar dx_i[3] = {0}, dU[5]; 19239c69132SJed Brown for (CeedInt k=0; k<5; k++) 19339c69132SJed Brown dU[k] = Grad_q[0][k][i] * dXdx[0][j] + 19439c69132SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 19539c69132SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 1965c677226SJed Brown dx_i[j] = 1.; 1976f00d0e6SJed Brown grad_s[j] = StateFromU_fwd(context, s, dU, x_i, dx_i); 1985c677226SJed Brown } 1995c677226SJed Brown 2005c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 2015c677226SJed Brown KMStrainRate(grad_s, strain_rate); 2025c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 2035c677226SJed Brown KMUnpack(kmstress, stress); 2045c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 2055c677226SJed Brown 2065c677226SJed Brown StateConservative F_inviscid[3]; 2075c677226SJed Brown FluxInviscid(context, s, F_inviscid); 2085c677226SJed Brown 2095c677226SJed Brown // Total flux 2105c677226SJed Brown CeedScalar Flux[5][3]; 2112b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 2125c677226SJed Brown 2132b89d87eSLeila Ghaffari for (CeedInt j=0; j<3; j++) 2142b89d87eSLeila Ghaffari for (CeedInt k=0; k<5; k++) 215a3ae0734SJed Brown Grad_v[j][k][i] = wdetJ * (dXdx[j][0] * Flux[k][0] + 2165c677226SJed Brown dXdx[j][1] * Flux[k][1] + 2175c677226SJed Brown dXdx[j][2] * Flux[k][2]); 2185c677226SJed Brown 2195c677226SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 2205c677226SJed Brown for (int j=0; j<5; j++) 2215c677226SJed Brown v[j][i] = wdetJ * body_force[j]; 22288b783a1SJames Wright 2232b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 2242b89d87eSLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 2252b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 2262b89d87eSLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 22788b783a1SJames Wright 228ba6664aeSJames Wright for (CeedInt j=0; j<5; j++) 229ba6664aeSJames Wright for (CeedInt k=0; k<3; k++) 230a3ae0734SJed Brown Grad_v[k][j][i] -= wdetJ*(stab[j][0] * dXdx[k][0] + 23188b783a1SJames Wright stab[j][1] * dXdx[k][1] + 23288b783a1SJames Wright stab[j][2] * dXdx[k][2]); 23388b783a1SJames Wright 23488b783a1SJames Wright } // End Quadrature Point Loop 23588b783a1SJames Wright 23688b783a1SJames Wright // Return 23788b783a1SJames Wright return 0; 23888b783a1SJames Wright } 23988b783a1SJames Wright 24088b783a1SJames Wright // ***************************************************************************** 24188b783a1SJames Wright // This QFunction implements the Navier-Stokes equations (mentioned above) with 24288b783a1SJames Wright // implicit time stepping method 24388b783a1SJames Wright // 24488b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 24588b783a1SJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 24688b783a1SJames Wright // (diffussive terms will be added later) 24788b783a1SJames Wright // 24888b783a1SJames Wright // ***************************************************************************** 2493d02368aSJames Wright CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, 2503d02368aSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 2513d02368aSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 25288b783a1SJames Wright // *INDENT-OFF* 25388b783a1SJames Wright // Inputs 25488b783a1SJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 255a3ae0734SJed Brown (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 25688b783a1SJames Wright (*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 25788b783a1SJames Wright (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 25888b783a1SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 25988b783a1SJames Wright // Outputs 26088b783a1SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 261a3ae0734SJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1], 262a3ae0734SJed Brown (*jac_data)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[2]; 26388b783a1SJames Wright // *INDENT-ON* 26488b783a1SJames Wright // Context 26588b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 26688626eedSJames Wright const CeedScalar *g = context->g; 26788626eedSJames Wright const CeedScalar dt = context->dt; 26888b783a1SJames Wright 26988b783a1SJames Wright CeedPragmaSIMD 27088b783a1SJames Wright // Quadrature Point Loop 27188b783a1SJames Wright for (CeedInt i=0; i<Q; i++) { 2723d02368aSJames Wright CeedScalar qi[5]; 2733d02368aSJames Wright for (CeedInt j=0; j<5; j++) qi[j] = q[j][i]; 2745c677226SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 2753d02368aSJames Wright State s = StateFromQi(context, qi, x_i); 2765c677226SJed Brown 27788b783a1SJames Wright // -- Interp-to-Interp q_data 27888b783a1SJames Wright const CeedScalar wdetJ = q_data[0][i]; 27988b783a1SJames Wright // -- Interp-to-Grad q_data 28088b783a1SJames Wright // ---- Inverse of change of coordinate matrix: X_i,j 28188b783a1SJames Wright // *INDENT-OFF* 28223d6ba15SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 28323d6ba15SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 28423d6ba15SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 28588b783a1SJames Wright }; 28688b783a1SJames Wright // *INDENT-ON* 2875c677226SJed Brown State grad_s[3]; 288ba6664aeSJames Wright for (CeedInt j=0; j<3; j++) { 2893d02368aSJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 29039c69132SJed Brown for (CeedInt k=0; k<5; k++) 2913d02368aSJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 29239c69132SJed Brown Grad_q[1][k][i] * dXdx[1][j] + 29339c69132SJed Brown Grad_q[2][k][i] * dXdx[2][j]; 2945c677226SJed Brown dx_i[j] = 1.; 2953d02368aSJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 29688b783a1SJames Wright } 2975c677226SJed Brown 2985c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 2995c677226SJed Brown KMStrainRate(grad_s, strain_rate); 3005c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 3015c677226SJed Brown KMUnpack(kmstress, stress); 3025c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 3035c677226SJed Brown 3045c677226SJed Brown StateConservative F_inviscid[3]; 3055c677226SJed Brown FluxInviscid(context, s, F_inviscid); 3065c677226SJed Brown 3075c677226SJed Brown // Total flux 3085c677226SJed Brown CeedScalar Flux[5][3]; 3092b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 3105c677226SJed Brown 3112b89d87eSLeila Ghaffari for (CeedInt j=0; j<3; j++) 3122b89d87eSLeila Ghaffari for (CeedInt k=0; k<5; k++) 313a3ae0734SJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * Flux[k][0] + 3145c677226SJed Brown dXdx[j][1] * Flux[k][1] + 3155c677226SJed Brown dXdx[j][2] * Flux[k][2]); 3165c677226SJed Brown 3175c677226SJed Brown const CeedScalar body_force[5] = {0, s.U.density *g[0], s.U.density *g[1], s.U.density *g[2], 0}; 31888b783a1SJames Wright 3192b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 3203d02368aSJames Wright CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}, qi_dot[5], dx0[3] = {0}; 3213d02368aSJames Wright for (int j=0; j<5; j++) qi_dot[j] = q_dot[j][i]; 3223d02368aSJames Wright State s_dot = StateFromQi_fwd(context, s, qi_dot, x_i, dx0); 3233d02368aSJames Wright UnpackState_U(s_dot.U, U_dot); 3243d02368aSJames Wright 3253d02368aSJames Wright for (CeedInt j=0; j<5; j++) 3263d02368aSJames Wright v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 3272b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 3282b89d87eSLeila Ghaffari Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, x_i, stab); 32988b783a1SJames Wright 330ba6664aeSJames Wright for (CeedInt j=0; j<5; j++) 331ba6664aeSJames Wright for (CeedInt k=0; k<3; k++) 332a3ae0734SJed Brown Grad_v[k][j][i] += wdetJ*(stab[j][0] * dXdx[k][0] + 33388b783a1SJames Wright stab[j][1] * dXdx[k][1] + 33488b783a1SJames Wright stab[j][2] * dXdx[k][2]); 3353c4b7af6SJed Brown 3363d02368aSJames Wright for (CeedInt j=0; j<5; j++) jac_data[j][i] = qi[j]; 3373c4b7af6SJed Brown for (CeedInt j=0; j<6; j++) jac_data[5+j][i] = kmstress[j]; 3383c4b7af6SJed Brown for (CeedInt j=0; j<3; j++) jac_data[5+6+j][i] = Tau_d[j]; 33988b783a1SJames Wright 34088b783a1SJames Wright } // End Quadrature Point Loop 34188b783a1SJames Wright 34288b783a1SJames Wright // Return 34388b783a1SJames Wright return 0; 34488b783a1SJames Wright } 345e334ad8fSJed Brown 3463d02368aSJames Wright CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, 3473d02368aSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 3483d02368aSJames Wright return IFunction_Newtonian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 3493d02368aSJames Wright } 3503d02368aSJames Wright 3513d02368aSJames Wright CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, 3523d02368aSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 3533d02368aSJames Wright return IFunction_Newtonian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 3543d02368aSJames Wright } 3553d02368aSJames Wright 356dc805cc4SLeila Ghaffari // ***************************************************************************** 3573d02368aSJames Wright // This QFunction implements the jacobian of the Navier-Stokes equations 358dc805cc4SLeila Ghaffari // for implicit time stepping method. 359dc805cc4SLeila Ghaffari // ***************************************************************************** 3603d02368aSJames Wright CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, 3613d02368aSJames Wright const CeedScalar *const *in, CeedScalar *const *out, 3623d02368aSJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 363e334ad8fSJed Brown // *INDENT-OFF* 364e334ad8fSJed Brown // Inputs 365e334ad8fSJed Brown const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 366e334ad8fSJed Brown (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 367e334ad8fSJed Brown (*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 368e334ad8fSJed Brown (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 369e334ad8fSJed Brown (*jac_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 370e334ad8fSJed Brown // Outputs 371e334ad8fSJed Brown CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 372e334ad8fSJed Brown (*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 373e334ad8fSJed Brown // *INDENT-ON* 374e334ad8fSJed Brown // Context 375e334ad8fSJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 376e334ad8fSJed Brown const CeedScalar *g = context->g; 377e334ad8fSJed Brown 378e334ad8fSJed Brown CeedPragmaSIMD 379e334ad8fSJed Brown // Quadrature Point Loop 380e334ad8fSJed Brown for (CeedInt i=0; i<Q; i++) { 381e334ad8fSJed Brown // -- Interp-to-Interp q_data 382e334ad8fSJed Brown const CeedScalar wdetJ = q_data[0][i]; 383e334ad8fSJed Brown // -- Interp-to-Grad q_data 384e334ad8fSJed Brown // ---- Inverse of change of coordinate matrix: X_i,j 385e334ad8fSJed Brown // *INDENT-OFF* 38623d6ba15SJames Wright const CeedScalar dXdx[3][3] = {{q_data[1][i], q_data[2][i], q_data[3][i]}, 38723d6ba15SJames Wright {q_data[4][i], q_data[5][i], q_data[6][i]}, 38823d6ba15SJames Wright {q_data[7][i], q_data[8][i], q_data[9][i]} 389e334ad8fSJed Brown }; 390e334ad8fSJed Brown // *INDENT-ON* 391e334ad8fSJed Brown 392*c98a0616SJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3]; 3933d02368aSJames Wright for (int j=0; j<5; j++) qi[j] = jac_data[j][i]; 394e334ad8fSJed Brown for (int j=0; j<6; j++) kmstress[j] = jac_data[5+j][i]; 395e334ad8fSJed Brown for (int j=0; j<3; j++) Tau_d[j] = jac_data[5+6+j][i]; 396e334ad8fSJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 3973d02368aSJames Wright State s = StateFromQi(context, qi, x_i); 398e334ad8fSJed Brown 3993d02368aSJames Wright CeedScalar dqi[5], dx0[3] = {0}; 4003d02368aSJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 4013d02368aSJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx0); 402e334ad8fSJed Brown 403e334ad8fSJed Brown State grad_ds[3]; 404e334ad8fSJed Brown for (int j=0; j<3; j++) { 4053d02368aSJames Wright CeedScalar dqi_j[5]; 4062b89d87eSLeila Ghaffari for (int k=0; k<5; k++) 4073d02368aSJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 4082b89d87eSLeila Ghaffari Grad_dq[1][k][i] * dXdx[1][j] + 4092b89d87eSLeila Ghaffari Grad_dq[2][k][i] * dXdx[2][j]; 4103d02368aSJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx0); 411e334ad8fSJed Brown } 412e334ad8fSJed Brown 413e334ad8fSJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 414e334ad8fSJed Brown KMStrainRate(grad_ds, dstrain_rate); 415e334ad8fSJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 416e334ad8fSJed Brown KMUnpack(dkmstress, dstress); 417e334ad8fSJed Brown KMUnpack(kmstress, stress); 418e334ad8fSJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 419e334ad8fSJed Brown 420e334ad8fSJed Brown StateConservative dF_inviscid[3]; 421e334ad8fSJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 422e334ad8fSJed Brown 423e334ad8fSJed Brown // Total flux 424e334ad8fSJed Brown CeedScalar dFlux[5][3]; 4252b89d87eSLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 426e334ad8fSJed Brown 4272b89d87eSLeila Ghaffari for (int j=0; j<3; j++) 4282b89d87eSLeila Ghaffari for (int k=0; k<5; k++) 429e334ad8fSJed Brown Grad_v[j][k][i] = -wdetJ * (dXdx[j][0] * dFlux[k][0] + 430e334ad8fSJed Brown dXdx[j][1] * dFlux[k][1] + 431e334ad8fSJed Brown dXdx[j][2] * dFlux[k][2]); 432e334ad8fSJed Brown 433e334ad8fSJed Brown const CeedScalar dbody_force[5] = {0, ds.U.density *g[0], ds.U.density *g[1], ds.U.density *g[2], 0}; 4343d02368aSJames Wright CeedScalar dU[5] = {0.}; 4353d02368aSJames Wright UnpackState_U(ds.U, dU); 436e334ad8fSJed Brown for (int j=0; j<5; j++) 437e334ad8fSJed Brown v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 438e334ad8fSJed Brown 4392b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 4402b89d87eSLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 4412b89d87eSLeila Ghaffari for (CeedInt j=0; j<5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 4422b89d87eSLeila Ghaffari Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, x_i, dstab); 4432b89d87eSLeila Ghaffari 444e334ad8fSJed Brown for (int j=0; j<5; j++) 445e334ad8fSJed Brown for (int k=0; k<3; k++) 446e334ad8fSJed Brown Grad_v[k][j][i] += wdetJ*(dstab[j][0] * dXdx[k][0] + 447e334ad8fSJed Brown dstab[j][1] * dXdx[k][1] + 448e334ad8fSJed Brown dstab[j][2] * dXdx[k][2]); 449e334ad8fSJed Brown 450e334ad8fSJed Brown } // End Quadrature Point Loop 451e334ad8fSJed Brown return 0; 452e334ad8fSJed Brown } 45365dd5cafSJames Wright 4543d02368aSJames Wright CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, 4553d02368aSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 4563d02368aSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 4573d02368aSJames Wright } 4583d02368aSJames Wright 4593d02368aSJames Wright CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, 4603d02368aSJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 4613d02368aSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 4623d02368aSJames Wright } 4633d02368aSJames Wright 4642b89d87eSLeila Ghaffari // ***************************************************************************** 46565dd5cafSJames Wright // Compute boundary integral (ie. for strongly set inflows) 4662b89d87eSLeila Ghaffari // ***************************************************************************** 46720840d50SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, 46820840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out, 46920840d50SJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 47065dd5cafSJames Wright 47165dd5cafSJames Wright //*INDENT-OFF* 47265dd5cafSJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 4732c4e60d7SJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 4742c4e60d7SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 4752c4e60d7SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 47665dd5cafSJames Wright 477b55ac660SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[0], 478b55ac660SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA]) out[1]; 47965dd5cafSJames Wright 48065dd5cafSJames Wright //*INDENT-ON* 48165dd5cafSJames Wright 4822c4e60d7SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext) ctx; 4832c4e60d7SJames Wright const bool is_implicit = context->is_implicit; 48465dd5cafSJames Wright 48565dd5cafSJames Wright CeedPragmaSIMD 48665dd5cafSJames Wright for(CeedInt i=0; i<Q; i++) { 4872c4e60d7SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 488efe9d856SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 489efe9d856SJames Wright State s = StateFromQi(context, qi, x_i); 49065dd5cafSJames Wright 49165dd5cafSJames Wright const CeedScalar wdetJb = (is_implicit ? -1. : 1.) * q_data_sur[0][i]; 4925bce47c7SJames Wright // ---- Normal vector 49365dd5cafSJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 49465dd5cafSJames Wright q_data_sur[2][i], 49565dd5cafSJames Wright q_data_sur[3][i] 49665dd5cafSJames Wright }; 49765dd5cafSJames Wright 4982c4e60d7SJames Wright const CeedScalar dXdx[2][3] = { 4992c4e60d7SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 5002c4e60d7SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 5012c4e60d7SJames Wright }; 50265dd5cafSJames Wright 5032c4e60d7SJames Wright State grad_s[3]; 5042c4e60d7SJames Wright for (CeedInt j=0; j<3; j++) { 505efe9d856SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 5062c4e60d7SJames Wright for (CeedInt k=0; k<5; k++) 507efe9d856SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 5082c4e60d7SJames Wright Grad_q[1][k][i] * dXdx[1][j]; 5092c4e60d7SJames Wright dx_i[j] = 1.; 510efe9d856SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 5112c4e60d7SJames Wright } 51265dd5cafSJames Wright 5132c4e60d7SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 5142c4e60d7SJames Wright KMStrainRate(grad_s, strain_rate); 5152c4e60d7SJames Wright NewtonianStress(context, strain_rate, kmstress); 5162c4e60d7SJames Wright KMUnpack(kmstress, stress); 5172c4e60d7SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 5182c4e60d7SJames Wright 5192c4e60d7SJames Wright StateConservative F_inviscid[3]; 5202c4e60d7SJames Wright FluxInviscid(context, s, F_inviscid); 5212c4e60d7SJames Wright 5225bce47c7SJames Wright CeedScalar Flux[5]; 5235bce47c7SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 5242c4e60d7SJames Wright 5255bce47c7SJames Wright for (CeedInt j=0; j<5; j++) v[j][i] = -wdetJb * Flux[j]; 52665dd5cafSJames Wright 5275bce47c7SJames Wright for (int j=0; j<5; j++) jac_data_sur[j][i] = qi[j]; 528b55ac660SJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 52965dd5cafSJames Wright } 53065dd5cafSJames Wright return 0; 53165dd5cafSJames Wright } 53265dd5cafSJames Wright 53320840d50SJames Wright CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, 53420840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 53520840d50SJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromU, StateFromU_fwd); 53620840d50SJames Wright } 53720840d50SJames Wright 53820840d50SJames Wright CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, 53920840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 54020840d50SJames Wright return BoundaryIntegral(ctx, Q, in, out, StateFromY, StateFromY_fwd); 54120840d50SJames Wright } 54220840d50SJames Wright 5432b89d87eSLeila Ghaffari // ***************************************************************************** 544b55ac660SJames Wright // Jacobian for "set nothing" boundary integral 5452b89d87eSLeila Ghaffari // ***************************************************************************** 54620840d50SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, 54720840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out, 54820840d50SJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 549b55ac660SJames Wright // *INDENT-OFF* 550b55ac660SJames Wright // Inputs 551b55ac660SJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 552b55ac660SJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 553b55ac660SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 554b55ac660SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 555b55ac660SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 556b55ac660SJames Wright // Outputs 557b55ac660SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 558b55ac660SJames Wright // *INDENT-ON* 559b55ac660SJames Wright 560b55ac660SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 561b55ac660SJames Wright const bool implicit = context->is_implicit; 562b55ac660SJames Wright 563b55ac660SJames Wright CeedPragmaSIMD 564b55ac660SJames Wright // Quadrature Point Loop 565b55ac660SJames Wright for (CeedInt i=0; i<Q; i++) { 566b55ac660SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 567b55ac660SJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 568b55ac660SJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], 569b55ac660SJames Wright q_data_sur[2][i], 570b55ac660SJames Wright q_data_sur[3][i] 571b55ac660SJames Wright }; 572b55ac660SJames Wright const CeedScalar dXdx[2][3] = { 573b55ac660SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 574b55ac660SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 575b55ac660SJames Wright }; 576b55ac660SJames Wright 577efe9d856SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 578efe9d856SJames Wright for (int j=0; j<5; j++) qi[j] = jac_data_sur[j][i]; 579b55ac660SJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 580efe9d856SJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 58157e55a1cSJames Wright 582efe9d856SJames Wright State s = StateFromQi(context, qi, x_i); 583efe9d856SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 584b55ac660SJames Wright 585b55ac660SJames Wright State grad_ds[3]; 586b55ac660SJames Wright for (CeedInt j=0; j<3; j++) { 587efe9d856SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 588b55ac660SJames Wright for (CeedInt k=0; k<5; k++) 589efe9d856SJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 590b55ac660SJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 591b55ac660SJames Wright dx_i[j] = 1.; 592efe9d856SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 593b55ac660SJames Wright } 594b55ac660SJames Wright 595b55ac660SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 596b55ac660SJames Wright KMStrainRate(grad_ds, dstrain_rate); 597b55ac660SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 598b55ac660SJames Wright KMUnpack(dkmstress, dstress); 599b55ac660SJames Wright KMUnpack(kmstress, stress); 600b55ac660SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 601b55ac660SJames Wright 602b55ac660SJames Wright StateConservative dF_inviscid[3]; 603b55ac660SJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 604b55ac660SJames Wright 6055bce47c7SJames Wright CeedScalar dFlux[5]; 6065bce47c7SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 607b55ac660SJames Wright 6085bce47c7SJames Wright for (int j=0; j<5; j++) v[j][i] = -wdetJb * dFlux[j]; 609b55ac660SJames Wright } // End Quadrature Point Loop 610b55ac660SJames Wright return 0; 611b55ac660SJames Wright } 612b55ac660SJames Wright 61320840d50SJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, 61420840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 61520840d50SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 61620840d50SJames Wright } 61720840d50SJames Wright 61820840d50SJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, 61920840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 62020840d50SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 62120840d50SJames Wright } 62220840d50SJames Wright 6232b89d87eSLeila Ghaffari // ***************************************************************************** 62430e9fa81SJames Wright // Outflow boundary condition, weakly setting a constant pressure 6252b89d87eSLeila Ghaffari // ***************************************************************************** 62620840d50SJames Wright CEED_QFUNCTION_HELPER int PressureOutflow(void *ctx, CeedInt Q, 62720840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out, 62820840d50SJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 62930e9fa81SJames Wright // *INDENT-OFF* 63030e9fa81SJames Wright // Inputs 63130e9fa81SJames Wright const CeedScalar (*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 632ce9b5c20SJames Wright (*Grad_q)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 633ce9b5c20SJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 634ce9b5c20SJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 63530e9fa81SJames Wright // Outputs 63630e9fa81SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0], 63730e9fa81SJames Wright (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1]; 63830e9fa81SJames Wright // *INDENT-ON* 63930e9fa81SJames Wright 64030e9fa81SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 64130e9fa81SJames Wright const bool implicit = context->is_implicit; 64230e9fa81SJames Wright const CeedScalar P0 = context->P0; 64330e9fa81SJames Wright 64430e9fa81SJames Wright CeedPragmaSIMD 64530e9fa81SJames Wright // Quadrature Point Loop 64630e9fa81SJames Wright for (CeedInt i=0; i<Q; i++) { 64730e9fa81SJames Wright // Setup 64830e9fa81SJames Wright // -- Interp in 649ce9b5c20SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 650efe9d856SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 651efe9d856SJames Wright State s = StateFromQi(context, qi, x_i); 652ce9b5c20SJames Wright s.Y.pressure = P0; 65330e9fa81SJames Wright 65430e9fa81SJames Wright // -- Interp-to-Interp q_data 65530e9fa81SJames Wright // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q). 65630e9fa81SJames Wright // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q). 65730e9fa81SJames Wright // We can effect this by swapping the sign on this weight 65830e9fa81SJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 65930e9fa81SJames Wright 6605bce47c7SJames Wright // ---- Normal vector 66120840d50SJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 66230e9fa81SJames Wright 663ce9b5c20SJames Wright const CeedScalar dXdx[2][3] = { 664ce9b5c20SJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 665ce9b5c20SJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 666ce9b5c20SJames Wright }; 66730e9fa81SJames Wright 668ce9b5c20SJames Wright State grad_s[3]; 669ce9b5c20SJames Wright for (CeedInt j=0; j<3; j++) { 670efe9d856SJames Wright CeedScalar dx_i[3] = {0}, dqi[5]; 671ce9b5c20SJames Wright for (CeedInt k=0; k<5; k++) 672efe9d856SJames Wright dqi[k] = Grad_q[0][k][i] * dXdx[0][j] + 673ce9b5c20SJames Wright Grad_q[1][k][i] * dXdx[1][j]; 674ce9b5c20SJames Wright dx_i[j] = 1.; 675efe9d856SJames Wright grad_s[j] = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 676ce9b5c20SJames Wright } 677ce9b5c20SJames Wright 678ce9b5c20SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 679ce9b5c20SJames Wright KMStrainRate(grad_s, strain_rate); 680ce9b5c20SJames Wright NewtonianStress(context, strain_rate, kmstress); 681ce9b5c20SJames Wright KMUnpack(kmstress, stress); 682ce9b5c20SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 683ce9b5c20SJames Wright 684ce9b5c20SJames Wright StateConservative F_inviscid[3]; 685ce9b5c20SJames Wright FluxInviscid(context, s, F_inviscid); 686ce9b5c20SJames Wright 6875bce47c7SJames Wright CeedScalar Flux[5]; 6885bce47c7SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 68930e9fa81SJames Wright 6905bce47c7SJames Wright for (CeedInt j=0; j<5; j++) v[j][i] = -wdetJb * Flux[j]; 69130e9fa81SJames Wright 69230e9fa81SJames Wright // Save values for Jacobian 6935bce47c7SJames Wright for (int j=0; j<5; j++) jac_data_sur[j][i] = qi[j]; 6940ec2498eSJames Wright for (int j=0; j<6; j++) jac_data_sur[5+j][i] = kmstress[j]; 69530e9fa81SJames Wright } // End Quadrature Point Loop 69630e9fa81SJames Wright return 0; 69730e9fa81SJames Wright } 69830e9fa81SJames Wright 69920840d50SJames Wright CEED_QFUNCTION(PressureOutflow_Conserv)(void *ctx, CeedInt Q, 70020840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 70120840d50SJames Wright return PressureOutflow(ctx, Q, in, out, StateFromU, StateFromU_fwd); 70220840d50SJames Wright } 70320840d50SJames Wright 70420840d50SJames Wright CEED_QFUNCTION(PressureOutflow_Prim)(void *ctx, CeedInt Q, 70520840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 70620840d50SJames Wright return PressureOutflow(ctx, Q, in, out, StateFromY, StateFromY_fwd); 70720840d50SJames Wright } 70820840d50SJames Wright 7092b89d87eSLeila Ghaffari // ***************************************************************************** 71030e9fa81SJames Wright // Jacobian for weak-pressure outflow boundary condition 7112b89d87eSLeila Ghaffari // ***************************************************************************** 71220840d50SJames Wright CEED_QFUNCTION_HELPER int PressureOutflow_Jacobian(void *ctx, CeedInt Q, 71320840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out, 71420840d50SJames Wright StateFromQi_t StateFromQi, StateFromQi_fwd_t StateFromQi_fwd) { 71530e9fa81SJames Wright // *INDENT-OFF* 71630e9fa81SJames Wright // Inputs 71730e9fa81SJames Wright const CeedScalar (*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0], 7180ec2498eSJames Wright (*Grad_dq)[5][CEED_Q_VLA] = (const CeedScalar(*)[5][CEED_Q_VLA])in[1], 7190ec2498eSJames Wright (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2], 7200ec2498eSJames Wright (*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3], 7210ec2498eSJames Wright (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 72230e9fa81SJames Wright // Outputs 72330e9fa81SJames Wright CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 72430e9fa81SJames Wright // *INDENT-ON* 72530e9fa81SJames Wright 72630e9fa81SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 72730e9fa81SJames Wright const bool implicit = context->is_implicit; 72830e9fa81SJames Wright 72930e9fa81SJames Wright CeedPragmaSIMD 73030e9fa81SJames Wright // Quadrature Point Loop 73130e9fa81SJames Wright for (CeedInt i=0; i<Q; i++) { 7320ec2498eSJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 73330e9fa81SJames Wright const CeedScalar wdetJb = (implicit ? -1. : 1.) * q_data_sur[0][i]; 73420840d50SJames Wright const CeedScalar norm[3] = {q_data_sur[1][i], q_data_sur[2][i], q_data_sur[3][i]}; 7350ec2498eSJames Wright const CeedScalar dXdx[2][3] = { 7360ec2498eSJames Wright {q_data_sur[4][i], q_data_sur[5][i], q_data_sur[6][i]}, 7370ec2498eSJames Wright {q_data_sur[7][i], q_data_sur[8][i], q_data_sur[9][i]} 7380ec2498eSJames Wright }; 7390ec2498eSJames Wright 740efe9d856SJames Wright CeedScalar qi[5], kmstress[6], dqi[5], dx_i[3] = {0.}; 741efe9d856SJames Wright for (int j=0; j<5; j++) qi[j] = jac_data_sur[j][i]; 7420ec2498eSJames Wright for (int j=0; j<6; j++) kmstress[j] = jac_data_sur[5+j][i]; 743efe9d856SJames Wright for (int j=0; j<5; j++) dqi[j] = dq[j][i]; 74457e55a1cSJames Wright 745efe9d856SJames Wright State s = StateFromQi(context, qi, x_i); 746efe9d856SJames Wright State ds = StateFromQi_fwd(context, s, dqi, x_i, dx_i); 7470ec2498eSJames Wright s.Y.pressure = context->P0; 7480ec2498eSJames Wright ds.Y.pressure = 0.; 7490ec2498eSJames Wright 7500ec2498eSJames Wright State grad_ds[3]; 7510ec2498eSJames Wright for (CeedInt j=0; j<3; j++) { 752efe9d856SJames Wright CeedScalar dx_i[3] = {0}, dqi_j[5]; 7530ec2498eSJames Wright for (CeedInt k=0; k<5; k++) 754efe9d856SJames Wright dqi_j[k] = Grad_dq[0][k][i] * dXdx[0][j] + 7550ec2498eSJames Wright Grad_dq[1][k][i] * dXdx[1][j]; 7560ec2498eSJames Wright dx_i[j] = 1.; 757efe9d856SJames Wright grad_ds[j] = StateFromQi_fwd(context, s, dqi_j, x_i, dx_i); 7580ec2498eSJames Wright } 7590ec2498eSJames Wright 7600ec2498eSJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 7610ec2498eSJames Wright KMStrainRate(grad_ds, dstrain_rate); 7620ec2498eSJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 7630ec2498eSJames Wright KMUnpack(dkmstress, dstress); 7640ec2498eSJames Wright KMUnpack(kmstress, stress); 7650ec2498eSJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 76630e9fa81SJames Wright 767b5d317f8SJames Wright StateConservative dF_inviscid[3]; 768b5d317f8SJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 76930e9fa81SJames Wright 7705bce47c7SJames Wright CeedScalar dFlux[5]; 7715bce47c7SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 772b5d317f8SJames Wright 7735bce47c7SJames Wright for (int j=0; j<5; j++) v[j][i] = -wdetJb * dFlux[j]; 77430e9fa81SJames Wright } // End Quadrature Point Loop 77530e9fa81SJames Wright return 0; 77630e9fa81SJames Wright } 77730e9fa81SJames Wright 77820840d50SJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Conserv)(void *ctx, CeedInt Q, 77920840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 78020840d50SJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromU, StateFromU_fwd); 78120840d50SJames Wright } 78220840d50SJames Wright 78320840d50SJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Prim)(void *ctx, CeedInt Q, 78420840d50SJames Wright const CeedScalar *const *in, CeedScalar *const *out) { 78520840d50SJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, StateFromY, StateFromY_fwd); 78620840d50SJames Wright } 78720840d50SJames Wright 788738af36cSAdelekeBankole // ***************************************************************************** 789738af36cSAdelekeBankole // Harten Lax VanLeer (HLL) approximate Riemann solver. 790738af36cSAdelekeBankole // Taking in two states (left, right) and returns RiemannFlux_HLL 791738af36cSAdelekeBankole // ***************************************************************************** 792*c98a0616SJames Wright CEED_QFUNCTION_HELPER StateConservative Harten_Lax_VanLeer_Flux( 793*c98a0616SJames Wright NewtonianIdealGasContext gas, State left, State right, 794*c98a0616SJames Wright const CeedScalar normal[3]) { 795738af36cSAdelekeBankole 796738af36cSAdelekeBankole StateConservative flux_left = FluxInviscidDotNormal(gas, left, normal); 797738af36cSAdelekeBankole StateConservative flux_right = FluxInviscidDotNormal(gas, right, normal); 798738af36cSAdelekeBankole StateConservative RiemannFlux_HLL; 799738af36cSAdelekeBankole // compute speed. 800738af36cSAdelekeBankole // TODO: This is only stable for subsonic flows. We need to include a Roe average 801738af36cSAdelekeBankole // or other technique to handle sonic flows. Stability requires that these speed estimates 802738af36cSAdelekeBankole // are *at least* as fast as the physical wave speeds. 803*c98a0616SJames Wright CeedScalar s_left = Dot3(left.Y.velocity, normal) 804*c98a0616SJames Wright - SoundSpeed(gas, left.Y.temperature); 805*c98a0616SJames Wright CeedScalar s_right = Dot3(right.Y.velocity, normal) 806*c98a0616SJames Wright + SoundSpeed(gas, right.Y.temperature); 807738af36cSAdelekeBankole // Compute HLL flux 808738af36cSAdelekeBankole if (0 <= s_left) { 809738af36cSAdelekeBankole RiemannFlux_HLL = flux_left; 810738af36cSAdelekeBankole } else if (s_right <= 0) { 811738af36cSAdelekeBankole RiemannFlux_HLL = flux_right; 812738af36cSAdelekeBankole } else { 813738af36cSAdelekeBankole RiemannFlux_HLL.density = 814738af36cSAdelekeBankole (s_right * flux_left.density - s_left * flux_right.density + 815738af36cSAdelekeBankole s_left * s_right * (right.U.density - left.U.density)) / 816738af36cSAdelekeBankole (s_right - s_left); 817738af36cSAdelekeBankole for (int i = 0; i < 3; i++) 818738af36cSAdelekeBankole RiemannFlux_HLL.momentum[i] = 819738af36cSAdelekeBankole (s_right * flux_left.momentum[i] - s_left * flux_right.momentum[i] + 820738af36cSAdelekeBankole s_left * s_right * (right.U.momentum[i] - left.U.momentum[i])) / 821738af36cSAdelekeBankole (s_right - s_left); 822738af36cSAdelekeBankole RiemannFlux_HLL.E_total = 823738af36cSAdelekeBankole (s_right * flux_left.E_total - s_left * flux_right.E_total + 824738af36cSAdelekeBankole s_left * s_right * (right.U.E_total - left.U.E_total)) / 825738af36cSAdelekeBankole (s_right - s_left); 826738af36cSAdelekeBankole } 827738af36cSAdelekeBankole // Return 828738af36cSAdelekeBankole return RiemannFlux_HLL; 829738af36cSAdelekeBankole } 830738af36cSAdelekeBankole 83188b783a1SJames Wright #endif // newtonian_h 832