1224fc8c8SJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2025, HONEE contributors. 2224fc8c8SJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause 3224fc8c8SJames Wright 4224fc8c8SJames Wright /// @file 5224fc8c8SJames Wright /// QFunctions for the `bc_freestream` and `bc_outflow` boundary conditions 6224fc8c8SJames Wright #include "bc_freestream_type.h" 7224fc8c8SJames Wright #include "newtonian_state.h" 8224fc8c8SJames Wright #include "newtonian_types.h" 9224fc8c8SJames Wright #include "riemann_solver.h" 10224fc8c8SJames Wright 11224fc8c8SJames Wright // Note the identity 12224fc8c8SJames Wright // 13224fc8c8SJames Wright // softplus(x) - x = log(1 + exp(x)) - x 14224fc8c8SJames Wright // = log(1 + exp(x)) + log(exp(-x)) 15224fc8c8SJames Wright // = log((1 + exp(x)) * exp(-x)) 16224fc8c8SJames Wright // = log(exp(-x) + 1) 17224fc8c8SJames Wright // = softplus(-x) 18224fc8c8SJames Wright CEED_QFUNCTION_HELPER CeedScalar Softplus(CeedScalar x, CeedScalar width) { 19224fc8c8SJames Wright if (x > 40 * width) return x; 20224fc8c8SJames Wright return width * log1p(exp(x / width)); 21224fc8c8SJames Wright } 22224fc8c8SJames Wright 23224fc8c8SJames Wright CEED_QFUNCTION_HELPER CeedScalar Softplus_fwd(CeedScalar x, CeedScalar dx, CeedScalar width) { 24224fc8c8SJames Wright if (x > 40 * width) return 1; 25224fc8c8SJames Wright const CeedScalar t = exp(x / width); 26224fc8c8SJames Wright return t / (1 + t); 27224fc8c8SJames Wright } 28224fc8c8SJames Wright 29224fc8c8SJames Wright // Viscous Outflow boundary condition, setting a constant exterior pressure and 30224fc8c8SJames Wright // temperature as input for a Riemann solve. This condition is stable even in 31224fc8c8SJames Wright // recirculating flow so long as the exterior temperature is sensible. 32224fc8c8SJames Wright // 33224fc8c8SJames Wright // The velocity in the exterior state has optional softplus regularization to 34224fc8c8SJames Wright // keep it outflow. These parameters have been finnicky in practice and provide 35224fc8c8SJames Wright // little or no benefit in the tests we've run thus far, thus we recommend 36224fc8c8SJames Wright // skipping this feature and just allowing recirculation. 37224fc8c8SJames Wright CEED_QFUNCTION_HELPER int RiemannOutflow(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 38224fc8c8SJames Wright const OutflowContext outflow = (OutflowContext)ctx; 39224fc8c8SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 40224fc8c8SJames Wright const CeedScalar(*Grad_q) = in[1]; 41224fc8c8SJames Wright const CeedScalar(*q_data_sur) = in[2]; 42224fc8c8SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 43*cde3d787SJames Wright CeedScalar(*jac_data_sur) = outflow->newt_ctx.is_implicit ? out[1] : NULL; 44224fc8c8SJames Wright 45*cde3d787SJames Wright const NewtonianIGProperties gas = outflow->newt_ctx.gas; 46*cde3d787SJames Wright const bool is_implicit = outflow->newt_ctx.is_implicit; 47224fc8c8SJames Wright 48224fc8c8SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 49224fc8c8SJames Wright CeedScalar wdetJb, dXdx[2][3], normal[3]; 50224fc8c8SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, normal); 51224fc8c8SJames Wright wdetJb *= is_implicit ? -1. : 1.; 52224fc8c8SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 53224fc8c8SJames Wright const State s_int = StateFromQ(gas, qi, state_var); 54224fc8c8SJames Wright 55224fc8c8SJames Wright StatePrimitive y_ext = s_int.Y; 56224fc8c8SJames Wright y_ext.pressure = outflow->pressure; 57224fc8c8SJames Wright y_ext.temperature = outflow->temperature; 58224fc8c8SJames Wright const CeedScalar u_normal = Dot3(y_ext.velocity, normal); 59224fc8c8SJames Wright const CeedScalar proj = (1 - outflow->recirc) * Softplus(-u_normal, outflow->softplus_velocity); 60224fc8c8SJames Wright for (CeedInt j = 0; j < 3; j++) { 61224fc8c8SJames Wright y_ext.velocity[j] += normal[j] * proj; // (I - n n^T) projects into the plane tangent to the normal 62224fc8c8SJames Wright } 63224fc8c8SJames Wright State s_ext = StateFromPrimitive(gas, y_ext); 64224fc8c8SJames Wright 65224fc8c8SJames Wright State grad_s[3]; 66224fc8c8SJames Wright StatePhysicalGradientFromReference_Boundary(Q, i, gas, s_int, state_var, Grad_q, dXdx, grad_s); 67224fc8c8SJames Wright 68224fc8c8SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 69224fc8c8SJames Wright KMStrainRate_State(grad_s, strain_rate); 70224fc8c8SJames Wright NewtonianStress(gas, strain_rate, kmstress); 71224fc8c8SJames Wright KMUnpack(kmstress, stress); 72224fc8c8SJames Wright ViscousEnergyFlux(gas, s_int.Y, grad_s, stress, Fe); 73224fc8c8SJames Wright 74224fc8c8SJames Wright StateConservative F_inviscid_normal = RiemannFlux_HLLC(gas, s_int, s_ext, normal); 75224fc8c8SJames Wright 76224fc8c8SJames Wright CeedScalar Flux[5]; 77224fc8c8SJames Wright FluxTotal_RiemannBoundary(F_inviscid_normal, stress, Fe, normal, Flux); 78224fc8c8SJames Wright 79224fc8c8SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 80224fc8c8SJames Wright 81224fc8c8SJames Wright // Save values for Jacobian 82224fc8c8SJames Wright if (is_implicit) { 83224fc8c8SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data_sur); 84224fc8c8SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data_sur); 85224fc8c8SJames Wright } 86224fc8c8SJames Wright } 87224fc8c8SJames Wright return 0; 88224fc8c8SJames Wright } 89224fc8c8SJames Wright 90224fc8c8SJames Wright CEED_QFUNCTION(RiemannOutflow_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 91224fc8c8SJames Wright return RiemannOutflow(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 92224fc8c8SJames Wright } 93224fc8c8SJames Wright 94224fc8c8SJames Wright CEED_QFUNCTION(RiemannOutflow_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 95224fc8c8SJames Wright return RiemannOutflow(ctx, Q, in, out, STATEVAR_PRIMITIVE); 96224fc8c8SJames Wright } 97224fc8c8SJames Wright 98224fc8c8SJames Wright CEED_QFUNCTION(RiemannOutflow_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 99224fc8c8SJames Wright return RiemannOutflow(ctx, Q, in, out, STATEVAR_ENTROPY); 100224fc8c8SJames Wright } 101224fc8c8SJames Wright 102224fc8c8SJames Wright // ***************************************************************************** 103224fc8c8SJames Wright // Jacobian for Riemann pressure/temperature outflow boundary condition 104224fc8c8SJames Wright // ***************************************************************************** 105224fc8c8SJames Wright CEED_QFUNCTION_HELPER int RiemannOutflow_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 106224fc8c8SJames Wright StateVariable state_var) { 107224fc8c8SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 108224fc8c8SJames Wright const CeedScalar(*Grad_dq) = in[1]; 109224fc8c8SJames Wright const CeedScalar(*q_data_sur) = in[2]; 110224fc8c8SJames Wright const CeedScalar(*jac_data_sur) = in[4]; 111224fc8c8SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 112224fc8c8SJames Wright 113224fc8c8SJames Wright const OutflowContext outflow = (OutflowContext)ctx; 114*cde3d787SJames Wright const NewtonianIGProperties gas = outflow->newt_ctx.gas; 115*cde3d787SJames Wright const bool is_implicit = outflow->newt_ctx.is_implicit; 116224fc8c8SJames Wright 117224fc8c8SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 118224fc8c8SJames Wright CeedScalar wdetJb, dXdx[2][3], normal[3]; 119224fc8c8SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, normal); 120224fc8c8SJames Wright wdetJb *= is_implicit ? -1. : 1.; 121224fc8c8SJames Wright 122224fc8c8SJames Wright CeedScalar qi[5], kmstress[6], dqi[5]; 123224fc8c8SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data_sur, qi); 124224fc8c8SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data_sur, kmstress); 125224fc8c8SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 126224fc8c8SJames Wright 127224fc8c8SJames Wright State s_int = StateFromQ(gas, qi, state_var); 128224fc8c8SJames Wright const State ds_int = StateFromQ_fwd(gas, s_int, dqi, state_var); 129224fc8c8SJames Wright StatePrimitive y_ext = s_int.Y, dy_ext = ds_int.Y; 130224fc8c8SJames Wright y_ext.pressure = outflow->pressure; 131224fc8c8SJames Wright y_ext.temperature = outflow->temperature; 132224fc8c8SJames Wright dy_ext.pressure = 0; 133224fc8c8SJames Wright dy_ext.temperature = 0; 134224fc8c8SJames Wright const CeedScalar u_normal = Dot3(s_int.Y.velocity, normal); 135224fc8c8SJames Wright const CeedScalar du_normal = Dot3(ds_int.Y.velocity, normal); 136224fc8c8SJames Wright const CeedScalar proj = (1 - outflow->recirc) * Softplus(-u_normal, outflow->softplus_velocity); 137224fc8c8SJames Wright const CeedScalar dproj = (1 - outflow->recirc) * Softplus_fwd(-u_normal, -du_normal, outflow->softplus_velocity); 138224fc8c8SJames Wright for (CeedInt j = 0; j < 3; j++) { 139224fc8c8SJames Wright y_ext.velocity[j] += normal[j] * proj; 140224fc8c8SJames Wright dy_ext.velocity[j] += normal[j] * dproj; 141224fc8c8SJames Wright } 142224fc8c8SJames Wright 143224fc8c8SJames Wright State s_ext = StateFromPrimitive(gas, y_ext); 144224fc8c8SJames Wright State ds_ext = StateFromPrimitive_fwd(gas, s_ext, dy_ext); 145224fc8c8SJames Wright 146224fc8c8SJames Wright State grad_ds[3]; 147224fc8c8SJames Wright StatePhysicalGradientFromReference_Boundary(Q, i, gas, s_int, state_var, Grad_dq, dXdx, grad_ds); 148224fc8c8SJames Wright 149224fc8c8SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 150224fc8c8SJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 151224fc8c8SJames Wright NewtonianStress(gas, dstrain_rate, dkmstress); 152224fc8c8SJames Wright KMUnpack(dkmstress, dstress); 153224fc8c8SJames Wright KMUnpack(kmstress, stress); 154224fc8c8SJames Wright ViscousEnergyFlux_fwd(gas, s_int.Y, ds_int.Y, grad_ds, stress, dstress, dFe); 155224fc8c8SJames Wright 156224fc8c8SJames Wright StateConservative dF_inviscid_normal = RiemannFlux_HLLC_fwd(gas, s_int, ds_int, s_ext, ds_ext, normal); 157224fc8c8SJames Wright 158224fc8c8SJames Wright CeedScalar dFlux[5]; 159224fc8c8SJames Wright FluxTotal_RiemannBoundary(dF_inviscid_normal, dstress, dFe, normal, dFlux); 160224fc8c8SJames Wright 161224fc8c8SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 162224fc8c8SJames Wright } 163224fc8c8SJames Wright return 0; 164224fc8c8SJames Wright } 165224fc8c8SJames Wright 166224fc8c8SJames Wright CEED_QFUNCTION(RiemannOutflow_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 167224fc8c8SJames Wright return RiemannOutflow_Jacobian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 168224fc8c8SJames Wright } 169224fc8c8SJames Wright 170224fc8c8SJames Wright CEED_QFUNCTION(RiemannOutflow_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 171224fc8c8SJames Wright return RiemannOutflow_Jacobian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 172224fc8c8SJames Wright } 173224fc8c8SJames Wright 174224fc8c8SJames Wright CEED_QFUNCTION(RiemannOutflow_Jacobian_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 175224fc8c8SJames Wright return RiemannOutflow_Jacobian(ctx, Q, in, out, STATEVAR_ENTROPY); 176224fc8c8SJames Wright } 177224fc8c8SJames Wright 178224fc8c8SJames Wright // ***************************************************************************** 179224fc8c8SJames Wright // Outflow boundary condition, weakly setting a constant pressure. This is the 180224fc8c8SJames Wright // classic outflow condition used by PHASTA-C and retained largely for 181224fc8c8SJames Wright // comparison. In our experiments, it is never better than RiemannOutflow, and 182224fc8c8SJames Wright // will crash if outflow ever becomes an inflow, as occurs with strong 183224fc8c8SJames Wright // acoustics, vortices, etc. 184224fc8c8SJames Wright // ***************************************************************************** 185224fc8c8SJames Wright CEED_QFUNCTION_HELPER int PressureOutflow(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) { 186224fc8c8SJames Wright const OutflowContext outflow = (OutflowContext)ctx; 187224fc8c8SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 188224fc8c8SJames Wright const CeedScalar(*Grad_q) = in[1]; 189224fc8c8SJames Wright const CeedScalar(*q_data_sur) = in[2]; 190224fc8c8SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 191*cde3d787SJames Wright CeedScalar(*jac_data_sur) = outflow->newt_ctx.is_implicit ? out[1] : NULL; 192224fc8c8SJames Wright 193*cde3d787SJames Wright const NewtonianIGProperties gas = outflow->newt_ctx.gas; 194*cde3d787SJames Wright const bool is_implicit = outflow->newt_ctx.is_implicit; 195224fc8c8SJames Wright 196224fc8c8SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 197224fc8c8SJames Wright const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]}; 198224fc8c8SJames Wright State s = StateFromQ(gas, qi, state_var); 199224fc8c8SJames Wright s.Y.pressure = outflow->pressure; 200224fc8c8SJames Wright 201224fc8c8SJames Wright CeedScalar wdetJb, dXdx[2][3], normal[3]; 202224fc8c8SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, normal); 203224fc8c8SJames Wright wdetJb *= is_implicit ? -1. : 1.; 204224fc8c8SJames Wright 205224fc8c8SJames Wright State grad_s[3]; 206224fc8c8SJames Wright StatePhysicalGradientFromReference_Boundary(Q, i, gas, s, state_var, Grad_q, dXdx, grad_s); 207224fc8c8SJames Wright 208224fc8c8SJames Wright CeedScalar strain_rate[6], kmstress[6], stress[3][3], Fe[3]; 209224fc8c8SJames Wright KMStrainRate_State(grad_s, strain_rate); 210224fc8c8SJames Wright NewtonianStress(gas, strain_rate, kmstress); 211224fc8c8SJames Wright KMUnpack(kmstress, stress); 212224fc8c8SJames Wright ViscousEnergyFlux(gas, s.Y, grad_s, stress, Fe); 213224fc8c8SJames Wright 214224fc8c8SJames Wright StateConservative F_inviscid[3]; 215224fc8c8SJames Wright FluxInviscid(gas, s, F_inviscid); 216224fc8c8SJames Wright 217224fc8c8SJames Wright CeedScalar Flux[5]; 218224fc8c8SJames Wright FluxTotal_Boundary(F_inviscid, stress, Fe, normal, Flux); 219224fc8c8SJames Wright 220224fc8c8SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = -wdetJb * Flux[j]; 221224fc8c8SJames Wright 222224fc8c8SJames Wright // Save values for Jacobian 223224fc8c8SJames Wright if (is_implicit) { 224224fc8c8SJames Wright StoredValuesPack(Q, i, 0, 5, qi, jac_data_sur); 225224fc8c8SJames Wright StoredValuesPack(Q, i, 5, 6, kmstress, jac_data_sur); 226224fc8c8SJames Wright } 227224fc8c8SJames Wright } 228224fc8c8SJames Wright return 0; 229224fc8c8SJames Wright } 230224fc8c8SJames Wright 231224fc8c8SJames Wright CEED_QFUNCTION(PressureOutflow_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 232224fc8c8SJames Wright return PressureOutflow(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 233224fc8c8SJames Wright } 234224fc8c8SJames Wright 235224fc8c8SJames Wright CEED_QFUNCTION(PressureOutflow_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 236224fc8c8SJames Wright return PressureOutflow(ctx, Q, in, out, STATEVAR_PRIMITIVE); 237224fc8c8SJames Wright } 238224fc8c8SJames Wright 239224fc8c8SJames Wright CEED_QFUNCTION(PressureOutflow_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 240224fc8c8SJames Wright return PressureOutflow(ctx, Q, in, out, STATEVAR_ENTROPY); 241224fc8c8SJames Wright } 242224fc8c8SJames Wright 243224fc8c8SJames Wright // ***************************************************************************** 244224fc8c8SJames Wright // Jacobian for weak-pressure outflow boundary condition 245224fc8c8SJames Wright // ***************************************************************************** 246224fc8c8SJames Wright CEED_QFUNCTION_HELPER int PressureOutflow_Jacobian(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, 247224fc8c8SJames Wright StateVariable state_var) { 248224fc8c8SJames Wright const CeedScalar(*dq)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0]; 249224fc8c8SJames Wright const CeedScalar(*Grad_dq) = in[1]; 250224fc8c8SJames Wright const CeedScalar(*q_data_sur) = in[2]; 251224fc8c8SJames Wright const CeedScalar(*jac_data_sur) = in[4]; 252224fc8c8SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0]; 253224fc8c8SJames Wright 254224fc8c8SJames Wright const OutflowContext outflow = (OutflowContext)ctx; 255*cde3d787SJames Wright const NewtonianIGProperties gas = outflow->newt_ctx.gas; 256*cde3d787SJames Wright const bool is_implicit = outflow->newt_ctx.is_implicit; 257224fc8c8SJames Wright 258224fc8c8SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) { 259224fc8c8SJames Wright CeedScalar wdetJb, dXdx[2][3], normal[3]; 260224fc8c8SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, dXdx, normal); 261224fc8c8SJames Wright wdetJb *= is_implicit ? -1. : 1.; 262224fc8c8SJames Wright 263224fc8c8SJames Wright CeedScalar qi[5], kmstress[6], dqi[5]; 264224fc8c8SJames Wright StoredValuesUnpack(Q, i, 0, 5, jac_data_sur, qi); 265224fc8c8SJames Wright StoredValuesUnpack(Q, i, 5, 6, jac_data_sur, kmstress); 266224fc8c8SJames Wright for (int j = 0; j < 5; j++) dqi[j] = dq[j][i]; 267224fc8c8SJames Wright 268224fc8c8SJames Wright State s = StateFromQ(gas, qi, state_var); 269224fc8c8SJames Wright State ds = StateFromQ_fwd(gas, s, dqi, state_var); 270224fc8c8SJames Wright s.Y.pressure = outflow->pressure; 271224fc8c8SJames Wright ds.Y.pressure = 0.; 272224fc8c8SJames Wright 273224fc8c8SJames Wright State grad_ds[3]; 274224fc8c8SJames Wright StatePhysicalGradientFromReference_Boundary(Q, i, gas, s, state_var, Grad_dq, dXdx, grad_ds); 275224fc8c8SJames Wright 276224fc8c8SJames Wright CeedScalar dstrain_rate[6], dkmstress[6], stress[3][3], dstress[3][3], dFe[3]; 277224fc8c8SJames Wright KMStrainRate_State(grad_ds, dstrain_rate); 278224fc8c8SJames Wright NewtonianStress(gas, dstrain_rate, dkmstress); 279224fc8c8SJames Wright KMUnpack(dkmstress, dstress); 280224fc8c8SJames Wright KMUnpack(kmstress, stress); 281224fc8c8SJames Wright ViscousEnergyFlux_fwd(gas, s.Y, ds.Y, grad_ds, stress, dstress, dFe); 282224fc8c8SJames Wright 283224fc8c8SJames Wright StateConservative dF_inviscid[3]; 284224fc8c8SJames Wright FluxInviscid_fwd(gas, s, ds, dF_inviscid); 285224fc8c8SJames Wright 286224fc8c8SJames Wright CeedScalar dFlux[5]; 287224fc8c8SJames Wright FluxTotal_Boundary(dF_inviscid, dstress, dFe, normal, dFlux); 288224fc8c8SJames Wright 289224fc8c8SJames Wright for (int j = 0; j < 5; j++) v[j][i] = -wdetJb * dFlux[j]; 290224fc8c8SJames Wright } 291224fc8c8SJames Wright return 0; 292224fc8c8SJames Wright } 293224fc8c8SJames Wright 294224fc8c8SJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 295224fc8c8SJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, STATEVAR_CONSERVATIVE); 296224fc8c8SJames Wright } 297224fc8c8SJames Wright 298224fc8c8SJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 299224fc8c8SJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, STATEVAR_PRIMITIVE); 300224fc8c8SJames Wright } 301224fc8c8SJames Wright 302224fc8c8SJames Wright CEED_QFUNCTION(PressureOutflow_Jacobian_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) { 303224fc8c8SJames Wright return PressureOutflow_Jacobian(ctx, Q, in, out, STATEVAR_ENTROPY); 304224fc8c8SJames Wright } 305