15aed82e4SJeremy L Thompson // Copyright (c) 2017-2024, 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 10*c0b5abf0SJeremy L Thompson #include <ceed/types.h> 11*c0b5abf0SJeremy L Thompson #ifndef CEED_RUNNING_JIT_PASS 12c9c2c079SJeremy L Thompson #include <math.h> 13738af36cSAdelekeBankole #include <stdlib.h> 14*c0b5abf0SJeremy L Thompson #endif 152b730f8bSJeremy L Thompson 16c6e8c570SJames Wright #include "newtonian_state.h" 17c9c2c079SJeremy L Thompson #include "newtonian_types.h" 182b89d87eSLeila Ghaffari #include "stabilization.h" 19c9c2c079SJeremy L Thompson #include "utils.h" 2088626eedSJames Wright 211d2a9659SKenneth E. Jansen CEED_QFUNCTION_HELPER void InternalDampingLayer(const NewtonianIdealGasContext context, const State s, const CeedScalar sigma, CeedScalar damp_Y[5], 22530ad8c4SKenneth E. Jansen CeedScalar damp_residual[5]) { 23530ad8c4SKenneth E. Jansen ScaleN(damp_Y, sigma, 5); 243bd61617SKenneth E. Jansen State damp_s = StateFromY_fwd(context, s, damp_Y); 25530ad8c4SKenneth E. Jansen 26530ad8c4SKenneth E. Jansen CeedScalar U[5]; 27530ad8c4SKenneth E. Jansen UnpackState_U(damp_s.U, U); 28530ad8c4SKenneth E. Jansen for (int i = 0; i < 5; i++) damp_residual[i] += U[i]; 29530ad8c4SKenneth E. Jansen } 30530ad8c4SKenneth E. Jansen 3188626eedSJames Wright // ***************************************************************************** 3288b783a1SJames Wright // This QFunction sets a "still" initial condition for generic Newtonian IG problems 3388b783a1SJames Wright // ***************************************************************************** 34be91e165SJames Wright CEED_QFUNCTION_HELPER int ICsNewtonianIG(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 3588b783a1SJames Wright CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 3688b783a1SJames Wright 3788626eedSJames Wright const SetupContext context = (SetupContext)ctx; 3888626eedSJames Wright 392b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 4088b783a1SJames Wright CeedScalar q[5] = {0.}; 413bd61617SKenneth E. Jansen State s = StateFromPrimitive(&context->gas, context->reference); 42be91e165SJames Wright StateToQ(&context->gas, s, q, state_var); 432b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j]; 44f0b01153SJames Wright } 4588b783a1SJames Wright return 0; 4688b783a1SJames Wright } 4788b783a1SJames Wright 48a2d72b6fSJames Wright CEED_QFUNCTION(ICsNewtonianIG_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 49a2d72b6fSJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 50a2d72b6fSJames Wright } 51a2d72b6fSJames Wright 522b730f8bSJeremy L Thompson CEED_QFUNCTION(ICsNewtonianIG_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 53be91e165SJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_PRIMITIVE); 54d310b3d3SAdeleke O. Bankole } 55a2d72b6fSJames Wright 56a2d72b6fSJames Wright CEED_QFUNCTION(ICsNewtonianIG_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 57a2d72b6fSJames Wright return ICsNewtonianIG(ctx, Q, in, out, STATEVAR_ENTROPY); 58dc805cc4SLeila Ghaffari } 59dc805cc4SLeila Ghaffari 600fcbc436SJames Wright CEED_QFUNCTION_HELPER void MassFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 610fcbc436SJames Wright StateVariable state_var) { 620fcbc436SJames Wright const CeedScalar(*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 630fcbc436SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[1]; 640fcbc436SJames Wright const CeedScalar(*q_data) = in[2]; 650fcbc436SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 660fcbc436SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 670fcbc436SJames Wright 680fcbc436SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 690fcbc436SJames Wright 700fcbc436SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 710fcbc436SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 720fcbc436SJames Wright const CeedScalar qi_dot[5] = {q_dot[0][i], q_dot[1][i], q_dot[2][i], q_dot[3][i], q_dot[4][i]}; 730fcbc436SJames Wright const State s = StateFromQ(context, qi, state_var); 740fcbc436SJames Wright const State s_dot = StateFromQ(context, qi_dot, state_var); 750fcbc436SJames Wright CeedScalar wdetJ, dXdx[3][3]; 760fcbc436SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 770fcbc436SJames Wright 780fcbc436SJames Wright // Standard mass matrix term 790fcbc436SJames Wright for (CeedInt f = 0; f < 5; f++) { 800fcbc436SJames Wright v[f][i] = wdetJ * qi_dot[f]; 810fcbc436SJames Wright } 820fcbc436SJames Wright 830fcbc436SJames Wright // Stabilization method: none (Galerkin), SU, or SUPG 840fcbc436SJames Wright State grad_s[3] = {{{0.}}}; 850fcbc436SJames Wright CeedScalar Tau_d[3], stab[5][3], body_force[5] = {0.}, U_dot[5]; 860fcbc436SJames Wright UnpackState_U(s_dot.U, U_dot); 870fcbc436SJames Wright Tau_diagPrim(context, s, dXdx, context->dt, Tau_d); 880fcbc436SJames Wright Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 890fcbc436SJames Wright 900fcbc436SJames Wright // Stabilized mass term 910fcbc436SJames Wright for (CeedInt j = 0; j < 5; j++) { 920fcbc436SJames Wright for (CeedInt k = 0; k < 3; k++) { 930fcbc436SJames Wright Grad_v[k][j][i] = wdetJ * (stab[j][0] * dXdx[k][0] + stab[j][1] * dXdx[k][1] + stab[j][2] * dXdx[k][2]); 940fcbc436SJames Wright } 950fcbc436SJames Wright } 960fcbc436SJames Wright } 970fcbc436SJames Wright } 980fcbc436SJames Wright 990fcbc436SJames Wright CEED_QFUNCTION(MassFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 1000fcbc436SJames Wright MassFunction_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 1010fcbc436SJames Wright return 0; 1020fcbc436SJames Wright } 1030fcbc436SJames Wright 104dc805cc4SLeila Ghaffari // ***************************************************************************** 105ea61e9acSJeremy L Thompson // This QFunction implements the following formulation of Navier-Stokes with explicit time stepping method 10688b783a1SJames Wright // 107ea61e9acSJeremy L Thompson // This is 3D compressible Navier-Stokes in conservation form with state 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 // 146ea61e9acSJeremy L Thompson // We require the product of the inverse of the Jacobian (dXdx_j,k) and its transpose (dXdx_k,j) to properly compute integrals of the form: int( gradv 147ea61e9acSJeremy L Thompson // gradu ) 14888b783a1SJames Wright // ***************************************************************************** 1492b730f8bSJeremy L Thompson CEED_QFUNCTION(RHSFunction_Newtonian)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 15046603fc5SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 1519b6a821dSJames Wright const CeedScalar(*Grad_q) = in[1]; 152f3e15844SJames Wright const CeedScalar(*q_data) = in[2]; 1537a57a7a0SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3]; 15446603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 15546603fc5SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 15688b783a1SJames Wright 15788b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 15888626eedSJames Wright const CeedScalar *g = context->g; 15988626eedSJames Wright const CeedScalar dt = context->dt; 1607a57a7a0SJames Wright const CeedScalar P0 = context->idl_pressure; 16188b783a1SJames Wright 16246603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 163f3e15844SJames Wright CeedScalar U[5], wdetJ, dXdx[3][3]; 1647a57a7a0SJames Wright const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 1655c677226SJed Brown for (int j = 0; j < 5; j++) U[j] = q[j][i]; 16642c90babSJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 1673bd61617SKenneth E. Jansen State s = StateFromU(context, U); 1685c677226SJed Brown 1695c677226SJed Brown State grad_s[3]; 1703bd61617SKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, STATEVAR_CONSERVATIVE, Grad_q, dXdx, grad_s); 1715c677226SJed Brown 1725c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 173d08fcc28SJames Wright KMStrainRate_State(grad_s, strain_rate); 1745c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 1755c677226SJed Brown KMUnpack(kmstress, stress); 1765c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 1775c677226SJed Brown 1785c677226SJed Brown StateConservative F_inviscid[3]; 1795c677226SJed Brown FluxInviscid(context, s, F_inviscid); 1805c677226SJed Brown 1815c677226SJed Brown // Total flux 1825c677226SJed Brown CeedScalar Flux[5][3]; 1832b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 1845c677226SJed Brown 1857b69c783SJames Wright for (CeedInt j = 0; j < 5; j++) { 1867b69c783SJames Wright for (CeedInt k = 0; k < 3; k++) Grad_v[k][j][i] = wdetJ * (dXdx[k][0] * Flux[j][0] + dXdx[k][1] * Flux[j][1] + dXdx[k][2] * Flux[j][2]); 1872b730f8bSJeremy L Thompson } 1885c677226SJed Brown 189858ec087SKenneth E. Jansen const CeedScalar body_force[5] = {0, s.U.density * g[0], s.U.density * g[1], s.U.density * g[2], Dot3(s.U.momentum, g)}; 1902b730f8bSJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * body_force[j]; 19188b783a1SJames Wright 1927a57a7a0SJames Wright if (context->idl_enable) { 1937a57a7a0SJames Wright const CeedScalar sigma = LinearRampCoefficient(context->idl_amplitude, context->idl_length, context->idl_start, x_i[0]); 1947a57a7a0SJames Wright CeedScalar damp_state[5] = {s.Y.pressure - P0, 0, 0, 0, 0}, idl_residual[5] = {0.}; 1957a57a7a0SJames Wright InternalDampingLayer(context, s, sigma, damp_state, idl_residual); 1967a57a7a0SJames Wright for (int j = 0; j < 5; j++) v[j][i] -= wdetJ * idl_residual[j]; 1977a57a7a0SJames Wright } 1987a57a7a0SJames Wright 1992b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 2002b89d87eSLeila Ghaffari CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}; 2012b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 2023bd61617SKenneth E. Jansen Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 20388b783a1SJames Wright 2042b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 2052b730f8bSJeremy L Thompson for (CeedInt k = 0; k < 3; k++) Grad_v[k][j][i] -= wdetJ * (stab[j][0] * dXdx[k][0] + stab[j][1] * dXdx[k][1] + stab[j][2] * dXdx[k][2]); 2062b730f8bSJeremy L Thompson } 207f0b01153SJames Wright } 20888b783a1SJames Wright return 0; 20988b783a1SJames Wright } 21088b783a1SJames Wright 21188b783a1SJames Wright // ***************************************************************************** 212ea61e9acSJeremy L Thompson // This QFunction implements the Navier-Stokes equations (mentioned above) with implicit time stepping method 21388b783a1SJames Wright // 21488b783a1SJames Wright // SU = Galerkin + grad(v) . ( Ai^T * Tau * (Aj q,j) ) 21588b783a1SJames Wright // SUPG = Galerkin + grad(v) . ( Ai^T * Tau * (q_dot + Aj q,j - body force) ) 216ea61e9acSJeremy L Thompson // (diffusive terms will be added later) 21788b783a1SJames Wright // ***************************************************************************** 218be91e165SJames Wright CEED_QFUNCTION_HELPER int IFunction_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 21946603fc5SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 2209b6a821dSJames Wright const CeedScalar(*Grad_q) = in[1]; 22146603fc5SJames Wright const CeedScalar(*q_dot)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2]; 222f3e15844SJames Wright const CeedScalar(*q_data) = in[3]; 22346603fc5SJames Wright const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[4]; 22446603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 22546603fc5SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 226f3e15844SJames Wright CeedScalar(*jac_data) = out[2]; 22746603fc5SJames Wright 22888b783a1SJames Wright NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 22988626eedSJames Wright const CeedScalar *g = context->g; 23088626eedSJames Wright const CeedScalar dt = context->dt; 231ff9b3c0eSJames Wright const CeedScalar P0 = context->idl_pressure; 23288b783a1SJames Wright 23346603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 23446603fc5SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 2355c677226SJed Brown const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]}; 2363bd61617SKenneth E. Jansen const State s = StateFromQ(context, qi, state_var); 2375c677226SJed Brown 238f3e15844SJames Wright CeedScalar wdetJ, dXdx[3][3]; 239f3e15844SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 2405c677226SJed Brown State grad_s[3]; 2413bd61617SKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 2425c677226SJed Brown 2435c677226SJed Brown CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 244d08fcc28SJames Wright KMStrainRate_State(grad_s, strain_rate); 2455c677226SJed Brown NewtonianStress(context, strain_rate, kmstress); 2465c677226SJed Brown KMUnpack(kmstress, stress); 2475c677226SJed Brown ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 2485c677226SJed Brown 2495c677226SJed Brown StateConservative F_inviscid[3]; 2505c677226SJed Brown FluxInviscid(context, s, F_inviscid); 2515c677226SJed Brown 2525c677226SJed Brown // Total flux 2535c677226SJed Brown CeedScalar Flux[5][3]; 2542b89d87eSLeila Ghaffari FluxTotal(F_inviscid, stress, Fe, Flux); 2555c677226SJed Brown 2567b69c783SJames Wright for (CeedInt j = 0; j < 5; j++) { 2577b69c783SJames Wright for (CeedInt k = 0; k < 3; k++) { 2587b69c783SJames Wright Grad_v[k][j][i] = -wdetJ * (dXdx[k][0] * Flux[j][0] + dXdx[k][1] * Flux[j][1] + dXdx[k][2] * Flux[j][2]); 25946603fc5SJames Wright } 2602b730f8bSJeremy L Thompson } 2615c677226SJed Brown 262858ec087SKenneth E. Jansen const CeedScalar body_force[5] = {0, s.U.density * g[0], s.U.density * g[1], s.U.density * g[2], Dot3(s.U.momentum, g)}; 26388b783a1SJames Wright 2642b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 2653bd61617SKenneth E. Jansen CeedScalar Tau_d[3], stab[5][3], U_dot[5] = {0}, qi_dot[5]; 2663d02368aSJames Wright for (int j = 0; j < 5; j++) qi_dot[j] = q_dot[j][i]; 2673bd61617SKenneth E. Jansen State s_dot = StateFromQ_fwd(context, s, qi_dot, state_var); 2683d02368aSJames Wright UnpackState_U(s_dot.U, U_dot); 2693d02368aSJames Wright 2702b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) v[j][i] = wdetJ * (U_dot[j] - body_force[j]); 271530ad8c4SKenneth E. Jansen if (context->idl_enable) { 2721d2a9659SKenneth E. Jansen const CeedScalar sigma = LinearRampCoefficient(context->idl_amplitude, context->idl_length, context->idl_start, x_i[0]); 2731d2a9659SKenneth E. Jansen StoredValuesPack(Q, i, 14, 1, &sigma, jac_data); 274530ad8c4SKenneth E. Jansen CeedScalar damp_state[5] = {s.Y.pressure - P0, 0, 0, 0, 0}, idl_residual[5] = {0.}; 2751d2a9659SKenneth E. Jansen InternalDampingLayer(context, s, sigma, damp_state, idl_residual); 276530ad8c4SKenneth E. Jansen for (int j = 0; j < 5; j++) v[j][i] += wdetJ * idl_residual[j]; 277530ad8c4SKenneth E. Jansen } 278530ad8c4SKenneth E. Jansen 2792b89d87eSLeila Ghaffari Tau_diagPrim(context, s, dXdx, dt, Tau_d); 2803bd61617SKenneth E. Jansen Stabilization(context, s, Tau_d, grad_s, U_dot, body_force, stab); 28188b783a1SJames Wright 2822b730f8bSJeremy L Thompson for (CeedInt j = 0; j < 5; j++) { 28346603fc5SJames Wright for (CeedInt k = 0; k < 3; k++) { 28446603fc5SJames Wright Grad_v[k][j][i] += wdetJ * (stab[j][0] * dXdx[k][0] + stab[j][1] * dXdx[k][1] + stab[j][2] * dXdx[k][2]); 28546603fc5SJames Wright } 2862b730f8bSJeremy L Thompson } 287f3e15844SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data); 288f3e15844SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data); 289f3e15844SJames Wright StoredValuesPack(Q, i, 11, 3, Tau_d, jac_data); 290f0b01153SJames Wright } 29188b783a1SJames Wright return 0; 29288b783a1SJames Wright } 293e334ad8fSJed Brown 2942b730f8bSJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 295be91e165SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 2963d02368aSJames Wright } 2973d02368aSJames Wright 2982b730f8bSJeremy L Thompson CEED_QFUNCTION(IFunction_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 299be91e165SJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 3003d02368aSJames Wright } 3013d02368aSJames Wright 302a2d72b6fSJames Wright CEED_QFUNCTION(IFunction_Newtonian_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 303a2d72b6fSJames Wright return IFunction_Newtonian(ctx, Q, in, out, STATEVAR_ENTROPY); 304a2d72b6fSJames Wright } 305a2d72b6fSJames Wright 306dc805cc4SLeila Ghaffari // ***************************************************************************** 307ea61e9acSJeremy L Thompson // This QFunction implements the jacobian of the Navier-Stokes equations for implicit time stepping method. 308dc805cc4SLeila Ghaffari // ***************************************************************************** 309be91e165SJames Wright CEED_QFUNCTION_HELPER int IJacobian_Newtonian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 31046603fc5SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 3119b6a821dSJames Wright const CeedScalar(*Grad_dq) = in[1]; 312f3e15844SJames Wright const CeedScalar(*q_data) = in[2]; 3131d2a9659SKenneth E. Jansen const CeedScalar(*jac_data) = in[3]; 31446603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 31546603fc5SJames Wright CeedScalar(*Grad_v)[5][CEED_Q_VLA] = (CeedScalar(*)[5][CEED_Q_VLA])out[1]; 31646603fc5SJames Wright 317e334ad8fSJed Brown NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 318e334ad8fSJed Brown const CeedScalar *g = context->g; 319e334ad8fSJed Brown 32046603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 321f3e15844SJames Wright CeedScalar wdetJ, dXdx[3][3]; 322f3e15844SJames Wright QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx); 323e334ad8fSJed Brown 324c98a0616SJames Wright CeedScalar qi[5], kmstress[6], Tau_d[3]; 325f3e15844SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data, qi); 326f3e15844SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data, kmstress); 327f3e15844SJames Wright StoredValuesUnpack(Q, i, 11, 3, jac_data, Tau_d); 3283bd61617SKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 329e334ad8fSJed Brown 3303bd61617SKenneth E. Jansen CeedScalar dqi[5]; 3313d02368aSJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 3323bd61617SKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 333e334ad8fSJed Brown 334e334ad8fSJed Brown State grad_ds[3]; 3353bd61617SKenneth E. Jansen StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 336e334ad8fSJed Brown 337e334ad8fSJed Brown CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 338d08fcc28SJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 339e334ad8fSJed Brown NewtonianStress(context, dstrain_rate, dkmstress); 340e334ad8fSJed Brown KMUnpack(dkmstress, dstress); 341e334ad8fSJed Brown KMUnpack(kmstress, stress); 342e334ad8fSJed Brown ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 343e334ad8fSJed Brown 344e334ad8fSJed Brown StateConservative dF_inviscid[3]; 345e334ad8fSJed Brown FluxInviscid_fwd(context, s, ds, dF_inviscid); 346e334ad8fSJed Brown 347e334ad8fSJed Brown // Total flux 348e334ad8fSJed Brown CeedScalar dFlux[5][3]; 3492b89d87eSLeila Ghaffari FluxTotal(dF_inviscid, dstress, dFe, dFlux); 350e334ad8fSJed Brown 35151b00d91SJames Wright for (int j = 0; j < 5; j++) { 35251b00d91SJames Wright for (int k = 0; k < 3; k++) Grad_v[k][j][i] = -wdetJ * (dXdx[k][0] * dFlux[j][0] + dXdx[k][1] * dFlux[j][1] + dXdx[k][2] * dFlux[j][2]); 3532b730f8bSJeremy L Thompson } 354e334ad8fSJed Brown 355858ec087SKenneth E. Jansen const CeedScalar dbody_force[5] = {0, ds.U.density * g[0], ds.U.density * g[1], ds.U.density * g[2], Dot3(ds.U.momentum, g)}; 3563d02368aSJames Wright CeedScalar dU[5] = {0.}; 3573d02368aSJames Wright UnpackState_U(ds.U, dU); 3582b730f8bSJeremy L Thompson for (int j = 0; j < 5; j++) v[j][i] = wdetJ * (context->ijacobian_time_shift * dU[j] - dbody_force[j]); 359e334ad8fSJed Brown 360530ad8c4SKenneth E. Jansen if (context->idl_enable) { 3611d2a9659SKenneth E. Jansen const CeedScalar sigma = jac_data[14 * Q + i]; 362530ad8c4SKenneth E. Jansen CeedScalar damp_state[5] = {ds.Y.pressure, 0, 0, 0, 0}, idl_residual[5] = {0.}; 363530ad8c4SKenneth E. Jansen // This is a Picard-type linearization of the damping and could be replaced by an InternalDampingLayer_fwd that uses s and ds. 3641d2a9659SKenneth E. Jansen InternalDampingLayer(context, s, sigma, damp_state, idl_residual); 365530ad8c4SKenneth E. Jansen for (int j = 0; j < 5; j++) v[j][i] += wdetJ * idl_residual[j]; 366530ad8c4SKenneth E. Jansen } 367530ad8c4SKenneth E. Jansen 3682b89d87eSLeila Ghaffari // -- Stabilization method: none (Galerkin), SU, or SUPG 3692b89d87eSLeila Ghaffari CeedScalar dstab[5][3], U_dot[5] = {0}; 3702b89d87eSLeila Ghaffari for (CeedInt j = 0; j < 5; j++) U_dot[j] = context->ijacobian_time_shift * dU[j]; 3713bd61617SKenneth E. Jansen Stabilization(context, s, Tau_d, grad_ds, U_dot, dbody_force, dstab); 3722b89d87eSLeila Ghaffari 3732b730f8bSJeremy L Thompson for (int j = 0; j < 5; j++) { 3742b730f8bSJeremy L Thompson for (int k = 0; k < 3; k++) Grad_v[k][j][i] += wdetJ * (dstab[j][0] * dXdx[k][0] + dstab[j][1] * dXdx[k][1] + dstab[j][2] * dXdx[k][2]); 3752b730f8bSJeremy L Thompson } 376f0b01153SJames Wright } 377e334ad8fSJed Brown return 0; 378e334ad8fSJed Brown } 37965dd5cafSJames Wright 3802b730f8bSJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 381be91e165SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 3823d02368aSJames Wright } 3833d02368aSJames Wright 3842b730f8bSJeremy L Thompson CEED_QFUNCTION(IJacobian_Newtonian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 385be91e165SJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 3863d02368aSJames Wright } 3873d02368aSJames Wright 388a2d72b6fSJames Wright CEED_QFUNCTION(IJacobian_Newtonian_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 389a2d72b6fSJames Wright return IJacobian_Newtonian(ctx, Q, in, out, STATEVAR_ENTROPY); 390a2d72b6fSJames Wright } 391a2d72b6fSJames Wright 3922b89d87eSLeila Ghaffari // ***************************************************************************** 39365dd5cafSJames Wright // Compute boundary integral (ie. for strongly set inflows) 3942b89d87eSLeila Ghaffari // ***************************************************************************** 395be91e165SJames Wright CEED_QFUNCTION_HELPER int BoundaryIntegral(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 396f21e6b1cSJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 39746603fc5SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 3989b6a821dSJames Wright const CeedScalar(*Grad_q) = in[1]; 399f3e15844SJames Wright const CeedScalar(*q_data_sur) = in[2]; 40046603fc5SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 401f21e6b1cSJames Wright CeedScalar(*jac_data_sur) = context->is_implicit ? out[1] : NULL; 40265dd5cafSJames Wright 4032c4e60d7SJames Wright const bool is_implicit = context->is_implicit; 40465dd5cafSJames Wright 4052b730f8bSJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 406efe9d856SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 4073bd61617SKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 40865dd5cafSJames Wright 409f3e15844SJames Wright CeedScalar wdetJb, dXdx[2][3], norm[3]; 410f3e15844SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, norm); 411f3e15844SJames Wright wdetJb *= is_implicit ? -1. : 1.; 41265dd5cafSJames Wright 4132c4e60d7SJames Wright State grad_s[3]; 4143bd61617SKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_q, dXdx, grad_s); 41565dd5cafSJames Wright 4162c4e60d7SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 417d08fcc28SJames Wright KMStrainRate_State(grad_s, strain_rate); 4182c4e60d7SJames Wright NewtonianStress(context, strain_rate, kmstress); 4192c4e60d7SJames Wright KMUnpack(kmstress, stress); 4202c4e60d7SJames Wright ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe); 4212c4e60d7SJames Wright 4222c4e60d7SJames Wright StateConservative F_inviscid[3]; 4232c4e60d7SJames Wright FluxInviscid(context, s, F_inviscid); 4242c4e60d7SJames Wright 4255bce47c7SJames Wright CeedScalar Flux[5]; 4265bce47c7SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, norm, Flux); 4272c4e60d7SJames Wright 4285bce47c7SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 42965dd5cafSJames Wright 430f21e6b1cSJames Wright if (is_implicit) { 431f3e15844SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data_sur); 432f3e15844SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data_sur); 43365dd5cafSJames Wright } 434f21e6b1cSJames Wright } 43565dd5cafSJames Wright return 0; 43665dd5cafSJames Wright } 43765dd5cafSJames Wright 4382b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 439be91e165SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 44020840d50SJames Wright } 44120840d50SJames Wright 4422b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 443be91e165SJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_PRIMITIVE); 44420840d50SJames Wright } 44520840d50SJames Wright 446a2d72b6fSJames Wright CEED_QFUNCTION(BoundaryIntegral_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 447a2d72b6fSJames Wright return BoundaryIntegral(ctx, Q, in, out, STATEVAR_ENTROPY); 448a2d72b6fSJames Wright } 449a2d72b6fSJames Wright 4502b89d87eSLeila Ghaffari // ***************************************************************************** 451b55ac660SJames Wright // Jacobian for "set nothing" boundary integral 4522b89d87eSLeila Ghaffari // ***************************************************************************** 4532b730f8bSJeremy L Thompson CEED_QFUNCTION_HELPER int BoundaryIntegral_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 454be91e165SJames Wright StateVariable state_var) { 45546603fc5SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 4569b6a821dSJames Wright const CeedScalar(*Grad_dq) = in[1]; 457f3e15844SJames Wright const CeedScalar(*q_data_sur) = in[2]; 458c1d93bc4SKenneth E. Jansen const CeedScalar(*jac_data_sur) = in[4]; 459b55ac660SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 460b55ac660SJames Wright 461b55ac660SJames Wright const NewtonianIdealGasContext context = (NewtonianIdealGasContext)ctx; 462f3e15844SJames Wright const bool is_implicit = context->is_implicit; 463b55ac660SJames Wright 46446603fc5SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 465f3e15844SJames Wright CeedScalar wdetJb, dXdx[2][3], norm[3]; 466f3e15844SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, norm); 467f3e15844SJames Wright wdetJb *= is_implicit ? -1. : 1.; 468b55ac660SJames Wright 4693bd61617SKenneth E. Jansen CeedScalar qi[5], kmstress[6], dqi[5]; 470f3e15844SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data_sur, qi); 471f3e15844SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data_sur, kmstress); 472efe9d856SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 47357e55a1cSJames Wright 4743bd61617SKenneth E. Jansen State s = StateFromQ(context, qi, state_var); 4753bd61617SKenneth E. Jansen State ds = StateFromQ_fwd(context, s, dqi, state_var); 476b55ac660SJames Wright 477b55ac660SJames Wright State grad_ds[3]; 4783bd61617SKenneth E. Jansen StatePhysicalGradientFromReference_Boundary(Q, i, context, s, state_var, Grad_dq, dXdx, grad_ds); 479b55ac660SJames Wright 480b55ac660SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 481d08fcc28SJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 482b55ac660SJames Wright NewtonianStress(context, dstrain_rate, dkmstress); 483b55ac660SJames Wright KMUnpack(dkmstress, dstress); 484b55ac660SJames Wright KMUnpack(kmstress, stress); 485b55ac660SJames Wright ViscousEnergyFlux_fwd(context, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 486b55ac660SJames Wright 487b55ac660SJames Wright StateConservative dF_inviscid[3]; 488b55ac660SJames Wright FluxInviscid_fwd(context, s, ds, dF_inviscid); 489b55ac660SJames Wright 4905bce47c7SJames Wright CeedScalar dFlux[5]; 4915bce47c7SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, norm, dFlux); 492b55ac660SJames Wright 4935bce47c7SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 4944c0e8230SJames Wright } 495b55ac660SJames Wright return 0; 496b55ac660SJames Wright } 497b55ac660SJames Wright 4982b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 499be91e165SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 50020840d50SJames Wright } 50120840d50SJames Wright 5022b730f8bSJeremy L Thompson CEED_QFUNCTION(BoundaryIntegral_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 503be91e165SJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 50420840d50SJames Wright } 505a2d72b6fSJames Wright 506a2d72b6fSJames Wright CEED_QFUNCTION(BoundaryIntegral_Jacobian_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 507a2d72b6fSJames Wright return BoundaryIntegral_Jacobian(ctx, Q, in, out, STATEVAR_ENTROPY); 508a2d72b6fSJames Wright } 509