xref: /honee/qfunctions/riemann_solver.h (revision 9ed3d70d58d93bd474ae216081539cf94addd4d0)
1*9ed3d70dSJames Wright // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2*9ed3d70dSJames Wright // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3*9ed3d70dSJames Wright //
4*9ed3d70dSJames Wright // SPDX-License-Identifier: BSD-2-Clause
5*9ed3d70dSJames Wright //
6*9ed3d70dSJames Wright // This file is part of CEED:  http://github.com/ceed
7*9ed3d70dSJames Wright 
8*9ed3d70dSJames Wright /// @file
9*9ed3d70dSJames Wright /// Helper functions for solving the Riemann problem.
10*9ed3d70dSJames Wright // The left and right states are specified from the perspective of an outward-facing normal vector pointing left to right:
11*9ed3d70dSJames Wright //
12*9ed3d70dSJames Wright //     (domain)
13*9ed3d70dSJames Wright //    /               (outward facing normal)
14*9ed3d70dSJames Wright // |------------|   /
15*9ed3d70dSJames Wright // |            |  /
16*9ed3d70dSJames Wright // |    Left    |---->  Right
17*9ed3d70dSJames Wright // | (Interior) |    (Exterior)
18*9ed3d70dSJames Wright // |------------|
19*9ed3d70dSJames Wright //
20*9ed3d70dSJames Wright // The right state is exterior to the domain and the left state is the interior to the domain.
21*9ed3d70dSJames Wright // Much of the work references Eleuterio F. Toro's "Riemann Solvers and Numerical Methods for Fluid Dynamics", 2009
22*9ed3d70dSJames Wright 
23*9ed3d70dSJames Wright #ifndef riemann_solver_h
24*9ed3d70dSJames Wright #define riemann_solver_h
25*9ed3d70dSJames Wright 
26*9ed3d70dSJames Wright #include "newtonian_state.h"
27*9ed3d70dSJames Wright #include "newtonian_types.h"
28*9ed3d70dSJames Wright 
29*9ed3d70dSJames Wright enum RiemannFluxType_ { RIEMANN_HLL, RIEMANN_HLLC };
30*9ed3d70dSJames Wright typedef enum RiemannFluxType_ RiemannFluxType;
31*9ed3d70dSJames Wright 
32*9ed3d70dSJames Wright typedef struct {
33*9ed3d70dSJames Wright   CeedScalar left, right;
34*9ed3d70dSJames Wright } RoeWeights;
35*9ed3d70dSJames Wright 
36*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER RoeWeights RoeSetup(CeedScalar rho_left, CeedScalar rho_right) {
37*9ed3d70dSJames Wright   CeedScalar sqrt_left = sqrt(rho_left), sqrt_right = sqrt(rho_right);
38*9ed3d70dSJames Wright   RoeWeights w = {sqrt_left / (sqrt_left + sqrt_right), sqrt_right / (sqrt_left + sqrt_right)};
39*9ed3d70dSJames Wright   return w;
40*9ed3d70dSJames Wright }
41*9ed3d70dSJames Wright 
42*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER RoeWeights RoeSetup_fwd(CeedScalar rho_left, CeedScalar rho_right, CeedScalar drho_left, CeedScalar drho_right) {
43*9ed3d70dSJames Wright   CeedScalar sqrt_left = sqrt(rho_left), sqrt_right = sqrt(rho_right);
44*9ed3d70dSJames Wright   CeedScalar square_sum_root = Square(sqrt_left + sqrt_right);
45*9ed3d70dSJames Wright   CeedScalar r_right = (sqrt_left / (2 * sqrt_right * square_sum_root)) * drho_right - (sqrt_right / (2 * sqrt_left * square_sum_root)) * drho_left;
46*9ed3d70dSJames Wright   CeedScalar r_left  = (sqrt_right / (2 * sqrt_left * square_sum_root)) * drho_left - (sqrt_left / (2 * sqrt_right * square_sum_root)) * drho_right;
47*9ed3d70dSJames Wright   RoeWeights dw      = {r_left, r_right};
48*9ed3d70dSJames Wright   return dw;
49*9ed3d70dSJames Wright }
50*9ed3d70dSJames Wright 
51*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER CeedScalar RoeAverage(RoeWeights r, CeedScalar q_left, CeedScalar q_right) { return r.left * q_left + r.right * q_right; }
52*9ed3d70dSJames Wright 
53*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER CeedScalar RoeAverage_fwd(RoeWeights r, RoeWeights dr, CeedScalar q_left, CeedScalar q_right, CeedScalar dq_left,
54*9ed3d70dSJames Wright                                                 CeedScalar dq_right) {
55*9ed3d70dSJames Wright   return q_right * dr.right + q_left * dr.left + r.right * dq_right + r.left * dq_left;
56*9ed3d70dSJames Wright }
57*9ed3d70dSJames Wright 
58*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER StateConservative Flux_HLL(State left, State right, StateConservative flux_left, StateConservative flux_right,
59*9ed3d70dSJames Wright                                                  CeedScalar s_left, CeedScalar s_right) {
60*9ed3d70dSJames Wright   CeedScalar U_left[5], U_right[5], F_right[5], F_left[5], F_hll[5];
61*9ed3d70dSJames Wright   UnpackState_U(left.U, U_left);
62*9ed3d70dSJames Wright   UnpackState_U(right.U, U_right);
63*9ed3d70dSJames Wright   UnpackState_U(flux_left, F_left);
64*9ed3d70dSJames Wright   UnpackState_U(flux_right, F_right);
65*9ed3d70dSJames Wright   for (int i = 0; i < 5; i++) {
66*9ed3d70dSJames Wright     F_hll[i] = (s_right * F_left[i] - s_left * F_right[i] + s_left * s_right * (U_right[i] - U_left[i])) / (s_right - s_left);
67*9ed3d70dSJames Wright   }
68*9ed3d70dSJames Wright   StateConservative F = {
69*9ed3d70dSJames Wright       F_hll[0],
70*9ed3d70dSJames Wright       {F_hll[1], F_hll[2], F_hll[3]},
71*9ed3d70dSJames Wright       F_hll[4],
72*9ed3d70dSJames Wright   };
73*9ed3d70dSJames Wright   return F;
74*9ed3d70dSJames Wright }
75*9ed3d70dSJames Wright 
76*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER StateConservative Flux_HLL_fwd(State left, State right, State dleft, State dright, StateConservative flux_left,
77*9ed3d70dSJames Wright                                                      StateConservative flux_right, StateConservative dflux_left, StateConservative dflux_right,
78*9ed3d70dSJames Wright                                                      CeedScalar S_l, CeedScalar S_r, CeedScalar dS_l, CeedScalar dS_r) {
79*9ed3d70dSJames Wright   CeedScalar U_l[5], U_r[5], F_r[5], F_l[5];
80*9ed3d70dSJames Wright   UnpackState_U(left.U, U_l);
81*9ed3d70dSJames Wright   UnpackState_U(right.U, U_r);
82*9ed3d70dSJames Wright   UnpackState_U(flux_left, F_l);
83*9ed3d70dSJames Wright   UnpackState_U(flux_right, F_r);
84*9ed3d70dSJames Wright 
85*9ed3d70dSJames Wright   CeedScalar dU_l[5], dU_r[5], dF_r[5], dF_l[5], dF_hll[5] = {0.};
86*9ed3d70dSJames Wright   UnpackState_U(dleft.U, dU_l);
87*9ed3d70dSJames Wright   UnpackState_U(dright.U, dU_r);
88*9ed3d70dSJames Wright   UnpackState_U(dflux_left, dF_l);
89*9ed3d70dSJames Wright   UnpackState_U(dflux_right, dF_r);
90*9ed3d70dSJames Wright   for (int i = 0; i < 5; i++) {
91*9ed3d70dSJames Wright     const CeedScalar U_diff      = U_r[i] - U_l[i];
92*9ed3d70dSJames Wright     const CeedScalar S_diff      = S_r - S_l;
93*9ed3d70dSJames Wright     const CeedScalar F_hll_denom = S_r * F_l[i] - S_l * F_r[i] + S_l * S_r * U_diff;
94*9ed3d70dSJames Wright 
95*9ed3d70dSJames Wright     dF_hll[i] += ((F_l[i] + S_r * U_diff) * S_diff - F_hll_denom) / Square(S_diff) * dS_r;
96*9ed3d70dSJames Wright     dF_hll[i] += ((-F_r[i] + S_r * U_diff) * S_diff + F_hll_denom) / Square(S_diff) * dS_l;
97*9ed3d70dSJames Wright     dF_hll[i] += (S_r * dF_l[i] - S_l * dF_r[i] + S_r * S_l * dU_r[i] - S_r * S_l * dU_l[i]) / S_diff;
98*9ed3d70dSJames Wright   }
99*9ed3d70dSJames Wright   StateConservative dF = {
100*9ed3d70dSJames Wright       dF_hll[0],
101*9ed3d70dSJames Wright       {dF_hll[1], dF_hll[2], dF_hll[3]},
102*9ed3d70dSJames Wright       dF_hll[4],
103*9ed3d70dSJames Wright   };
104*9ed3d70dSJames Wright   return dF;
105*9ed3d70dSJames Wright }
106*9ed3d70dSJames Wright 
107*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER void ComputeHLLSpeeds_Roe(NewtonianIdealGasContext gas, State left, CeedScalar u_left, State right, CeedScalar u_right,
108*9ed3d70dSJames Wright                                                 CeedScalar *s_left, CeedScalar *s_right) {
109*9ed3d70dSJames Wright   const CeedScalar gamma = HeatCapacityRatio(gas);
110*9ed3d70dSJames Wright 
111*9ed3d70dSJames Wright   RoeWeights r = RoeSetup(left.U.density, right.U.density);
112*9ed3d70dSJames Wright   // Speed estimate
113*9ed3d70dSJames Wright   // Roe average eigenvalues for left and right non-linear waves.
114*9ed3d70dSJames Wright   // Stability requires that these speed estimates are *at least* as fast as the physical wave speeds.
115*9ed3d70dSJames Wright   CeedScalar u_roe = RoeAverage(r, u_left, u_right);
116*9ed3d70dSJames Wright 
117*9ed3d70dSJames Wright   // TODO: revisit this for gravity
118*9ed3d70dSJames Wright   CeedScalar H_left  = TotalSpecificEnthalpy(gas, left);
119*9ed3d70dSJames Wright   CeedScalar H_right = TotalSpecificEnthalpy(gas, right);
120*9ed3d70dSJames Wright   CeedScalar H_roe   = RoeAverage(r, H_left, H_right);
121*9ed3d70dSJames Wright   CeedScalar a_roe   = sqrt((gamma - 1) * (H_roe - 0.5 * Square(u_roe)));
122*9ed3d70dSJames Wright 
123*9ed3d70dSJames Wright   // Einfeldt (1988) justifies (and Toro's book repeats) that Roe speeds can be used here.
124*9ed3d70dSJames Wright   *s_left  = u_roe - a_roe;
125*9ed3d70dSJames Wright   *s_right = u_roe + a_roe;
126*9ed3d70dSJames Wright }
127*9ed3d70dSJames Wright 
128*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER void ComputeHLLSpeeds_Roe_fwd(NewtonianIdealGasContext gas, State left, State dleft, CeedScalar u_left, CeedScalar du_left,
129*9ed3d70dSJames Wright                                                     State right, State dright, CeedScalar u_right, CeedScalar du_right, CeedScalar *s_left,
130*9ed3d70dSJames Wright                                                     CeedScalar *ds_left, CeedScalar *s_right, CeedScalar *ds_right) {
131*9ed3d70dSJames Wright   const CeedScalar gamma = HeatCapacityRatio(gas);
132*9ed3d70dSJames Wright 
133*9ed3d70dSJames Wright   RoeWeights r  = RoeSetup(left.U.density, right.U.density);
134*9ed3d70dSJames Wright   RoeWeights dr = RoeSetup_fwd(left.U.density, right.U.density, dleft.U.density, dright.U.density);
135*9ed3d70dSJames Wright   // Speed estimate
136*9ed3d70dSJames Wright   // Roe average eigenvalues for left and right non-linear waves.
137*9ed3d70dSJames Wright   // Stability requires that these speed estimates are *at least* as fast as the physical wave speeds.
138*9ed3d70dSJames Wright   CeedScalar u_roe  = RoeAverage(r, u_left, u_right);
139*9ed3d70dSJames Wright   CeedScalar du_roe = RoeAverage_fwd(r, dr, u_left, u_right, du_left, du_right);
140*9ed3d70dSJames Wright 
141*9ed3d70dSJames Wright   CeedScalar H_left   = TotalSpecificEnthalpy(gas, left);
142*9ed3d70dSJames Wright   CeedScalar H_right  = TotalSpecificEnthalpy(gas, right);
143*9ed3d70dSJames Wright   CeedScalar dH_left  = TotalSpecificEnthalpy_fwd(gas, left, dleft);
144*9ed3d70dSJames Wright   CeedScalar dH_right = TotalSpecificEnthalpy_fwd(gas, right, dright);
145*9ed3d70dSJames Wright 
146*9ed3d70dSJames Wright   CeedScalar H_roe  = RoeAverage(r, H_left, H_right);
147*9ed3d70dSJames Wright   CeedScalar dH_roe = RoeAverage_fwd(r, dr, H_left, H_right, dH_left, dH_right);
148*9ed3d70dSJames Wright   CeedScalar a_roe  = sqrt((gamma - 1) * (H_roe - 0.5 * Square(u_roe)));
149*9ed3d70dSJames Wright   CeedScalar da_roe = 0.5 * (gamma - 1) / sqrt(H_roe) * dH_roe - 0.5 * sqrt(gamma - 1) * u_roe / sqrt(H_roe - 0.5 * Square(u_roe)) * du_roe;
150*9ed3d70dSJames Wright 
151*9ed3d70dSJames Wright   *s_left   = u_roe - a_roe;
152*9ed3d70dSJames Wright   *ds_left  = du_roe - da_roe;
153*9ed3d70dSJames Wright   *s_right  = u_roe + a_roe;
154*9ed3d70dSJames Wright   *ds_right = du_roe + da_roe;
155*9ed3d70dSJames Wright }
156*9ed3d70dSJames Wright 
157*9ed3d70dSJames Wright // *****************************************************************************
158*9ed3d70dSJames Wright // @brief Harten Lax VanLeer (HLL) approximate Riemann solver.
159*9ed3d70dSJames Wright // Taking in two states (left, right) and returns RiemannFlux_HLL.
160*9ed3d70dSJames Wright // The left and right states are specified from the perspective of an outward-facing normal vector pointing left to right.
161*9ed3d70dSJames Wright //
162*9ed3d70dSJames Wright // @param[in] gas    NewtonianIdealGasContext for the fluid
163*9ed3d70dSJames Wright // @param[in] left   Fluid state of the domain interior (the current solution)
164*9ed3d70dSJames Wright // @param[in] right  Fluid state of the domain exterior (free stream conditions)
165*9ed3d70dSJames Wright // @param[in] normal Normalized, outward facing boundary normal vector
166*9ed3d70dSJames Wright //
167*9ed3d70dSJames Wright // @return StateConservative with HLL Riemann Flux
168*9ed3d70dSJames Wright // *****************************************************************************
169*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER StateConservative RiemannFlux_HLL(NewtonianIdealGasContext gas, State left, State right, const CeedScalar normal[3]) {
170*9ed3d70dSJames Wright   StateConservative flux_left  = FluxInviscidDotNormal(gas, left, normal);
171*9ed3d70dSJames Wright   StateConservative flux_right = FluxInviscidDotNormal(gas, right, normal);
172*9ed3d70dSJames Wright 
173*9ed3d70dSJames Wright   CeedScalar u_left  = Dot3(left.Y.velocity, normal);
174*9ed3d70dSJames Wright   CeedScalar u_right = Dot3(right.Y.velocity, normal);
175*9ed3d70dSJames Wright 
176*9ed3d70dSJames Wright   CeedScalar s_left, s_right;
177*9ed3d70dSJames Wright   ComputeHLLSpeeds_Roe(gas, left, u_left, right, u_right, &s_left, &s_right);
178*9ed3d70dSJames Wright 
179*9ed3d70dSJames Wright   // Compute HLL flux
180*9ed3d70dSJames Wright   if (0 <= s_left) {
181*9ed3d70dSJames Wright     return flux_left;
182*9ed3d70dSJames Wright   } else if (s_right <= 0) {
183*9ed3d70dSJames Wright     return flux_right;
184*9ed3d70dSJames Wright   } else {
185*9ed3d70dSJames Wright     return Flux_HLL(left, right, flux_left, flux_right, s_left, s_right);
186*9ed3d70dSJames Wright   }
187*9ed3d70dSJames Wright }
188*9ed3d70dSJames Wright 
189*9ed3d70dSJames Wright // *****************************************************************************
190*9ed3d70dSJames Wright // @brief Forward-mode Derivative of Harten Lax VanLeer (HLL) approximate Riemann solver.
191*9ed3d70dSJames Wright //
192*9ed3d70dSJames Wright // @param gas    NewtonianIdealGasContext for the fluid
193*9ed3d70dSJames Wright // @param left   Fluid state of the domain interior (the current solution)
194*9ed3d70dSJames Wright // @param right  Fluid state of the domain exterior (free stream conditions)
195*9ed3d70dSJames Wright // @param dleft  Derivative of fluid state of the domain interior (the current solution)
196*9ed3d70dSJames Wright // @param dright Derivative of fluid state of the domain exterior (free stream conditions)
197*9ed3d70dSJames Wright // @param normal Normalized, outward facing boundary normal vector
198*9ed3d70dSJames Wright //
199*9ed3d70dSJames Wright // @return StateConservative with derivative of HLL Riemann Flux
200*9ed3d70dSJames Wright // *****************************************************************************
201*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER StateConservative RiemannFlux_HLL_fwd(NewtonianIdealGasContext gas, State left, State dleft, State right, State dright,
202*9ed3d70dSJames Wright                                                             const CeedScalar normal[3]) {
203*9ed3d70dSJames Wright   StateConservative flux_left   = FluxInviscidDotNormal(gas, left, normal);
204*9ed3d70dSJames Wright   StateConservative flux_right  = FluxInviscidDotNormal(gas, right, normal);
205*9ed3d70dSJames Wright   StateConservative dflux_left  = FluxInviscidDotNormal_fwd(gas, left, dleft, normal);
206*9ed3d70dSJames Wright   StateConservative dflux_right = FluxInviscidDotNormal_fwd(gas, right, dright, normal);
207*9ed3d70dSJames Wright 
208*9ed3d70dSJames Wright   CeedScalar u_left   = Dot3(left.Y.velocity, normal);
209*9ed3d70dSJames Wright   CeedScalar u_right  = Dot3(right.Y.velocity, normal);
210*9ed3d70dSJames Wright   CeedScalar du_left  = Dot3(dleft.Y.velocity, normal);
211*9ed3d70dSJames Wright   CeedScalar du_right = Dot3(dright.Y.velocity, normal);
212*9ed3d70dSJames Wright 
213*9ed3d70dSJames Wright   CeedScalar s_left, ds_left, s_right, ds_right;
214*9ed3d70dSJames Wright   ComputeHLLSpeeds_Roe_fwd(gas, left, dleft, u_left, du_left, right, dright, u_right, du_right, &s_left, &ds_left, &s_right, &ds_right);
215*9ed3d70dSJames Wright 
216*9ed3d70dSJames Wright   if (0 <= s_left) {
217*9ed3d70dSJames Wright     return dflux_left;
218*9ed3d70dSJames Wright   } else if (s_right <= 0) {
219*9ed3d70dSJames Wright     return dflux_right;
220*9ed3d70dSJames Wright   } else {
221*9ed3d70dSJames Wright     return Flux_HLL_fwd(left, right, dleft, dright, flux_left, flux_right, dflux_left, dflux_right, s_left, s_right, ds_left, ds_right);
222*9ed3d70dSJames Wright   }
223*9ed3d70dSJames Wright }
224*9ed3d70dSJames Wright 
225*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER StateConservative RiemannFlux_HLLC_Star(NewtonianIdealGasContext gas, State side, StateConservative F_side,
226*9ed3d70dSJames Wright                                                               const CeedScalar normal[3], CeedScalar u_side, CeedScalar s_side, CeedScalar s_star) {
227*9ed3d70dSJames Wright   CeedScalar fact  = side.U.density * (s_side - u_side) / (s_side - s_star);
228*9ed3d70dSJames Wright   CeedScalar denom = side.U.density * (s_side - u_side);
229*9ed3d70dSJames Wright   // U_* = fact * star
230*9ed3d70dSJames Wright   StateConservative star = {
231*9ed3d70dSJames Wright       1.0,
232*9ed3d70dSJames Wright       {
233*9ed3d70dSJames Wright         side.Y.velocity[0] + (s_star - u_side) * normal[0],
234*9ed3d70dSJames Wright         side.Y.velocity[1] + (s_star - u_side) * normal[1],
235*9ed3d70dSJames Wright         side.Y.velocity[2] + (s_star - u_side) * normal[2],
236*9ed3d70dSJames Wright         },
237*9ed3d70dSJames Wright       side.U.E_total / side.U.density  //
238*9ed3d70dSJames Wright           + (s_star - u_side) * (s_star + side.Y.pressure / denom)
239*9ed3d70dSJames Wright   };
240*9ed3d70dSJames Wright   return StateConservativeAXPBYPCZ(1, F_side, s_side * fact, star, -s_side, side.U);
241*9ed3d70dSJames Wright }
242*9ed3d70dSJames Wright 
243*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER StateConservative RiemannFlux_HLLC_Star_fwd(NewtonianIdealGasContext gas, State side, State dside, StateConservative F_side,
244*9ed3d70dSJames Wright                                                                   StateConservative dF_side, const CeedScalar normal[3], CeedScalar u_side,
245*9ed3d70dSJames Wright                                                                   CeedScalar du_side, CeedScalar s_side, CeedScalar ds_side, CeedScalar s_star,
246*9ed3d70dSJames Wright                                                                   CeedScalar ds_star) {
247*9ed3d70dSJames Wright   CeedScalar fact  = side.U.density * (s_side - u_side) / (s_side - s_star);
248*9ed3d70dSJames Wright   CeedScalar dfact = (side.U.density * (ds_side - du_side) + dside.U.density * (s_side - u_side)) / (s_side - s_star)  //
249*9ed3d70dSJames Wright                      - fact / (s_side - s_star) * (ds_side - ds_star);
250*9ed3d70dSJames Wright   CeedScalar denom  = side.U.density * (s_side - u_side);
251*9ed3d70dSJames Wright   CeedScalar ddenom = side.U.density * (ds_side - du_side) + dside.U.density * (s_side - u_side);
252*9ed3d70dSJames Wright 
253*9ed3d70dSJames Wright   StateConservative star = {
254*9ed3d70dSJames Wright       1.0,
255*9ed3d70dSJames Wright       {
256*9ed3d70dSJames Wright         side.Y.velocity[0] + (s_star - u_side) * normal[0],
257*9ed3d70dSJames Wright         side.Y.velocity[1] + (s_star - u_side) * normal[1],
258*9ed3d70dSJames Wright         side.Y.velocity[2] + (s_star - u_side) * normal[2],
259*9ed3d70dSJames Wright         },
260*9ed3d70dSJames Wright       side.U.E_total / side.U.density  //
261*9ed3d70dSJames Wright           + (s_star - u_side) * (s_star + side.Y.pressure / denom)
262*9ed3d70dSJames Wright   };
263*9ed3d70dSJames Wright   StateConservative dstar = {
264*9ed3d70dSJames Wright       0.,
265*9ed3d70dSJames Wright       {
266*9ed3d70dSJames Wright         dside.Y.velocity[0] + (ds_star - du_side) * normal[0],
267*9ed3d70dSJames Wright         dside.Y.velocity[1] + (ds_star - du_side) * normal[1],
268*9ed3d70dSJames Wright         dside.Y.velocity[2] + (ds_star - du_side) * normal[2],
269*9ed3d70dSJames Wright         },
270*9ed3d70dSJames Wright       dside.U.E_total / side.U.density - side.U.E_total / Square(side.U.density) * dside.U.density  //
271*9ed3d70dSJames Wright           + (ds_star - du_side) * (s_star + side.Y.pressure / denom)  //
272*9ed3d70dSJames Wright           + (s_star - u_side) * (ds_star + dside.Y.pressure / denom - side.Y.pressure / Square(denom) * ddenom)  //
273*9ed3d70dSJames Wright   };
274*9ed3d70dSJames Wright 
275*9ed3d70dSJames Wright   const CeedScalar        a[] = {1, ds_side * fact + s_side * dfact, s_side * fact, -ds_side, -s_side};
276*9ed3d70dSJames Wright   const StateConservative U[] = {dF_side, star, dstar, side.U, dside.U};
277*9ed3d70dSJames Wright   return StateConservativeMult(5, a, U);
278*9ed3d70dSJames Wright }
279*9ed3d70dSJames Wright 
280*9ed3d70dSJames Wright // HLLC Riemann solver (from Toro's book)
281*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER StateConservative RiemannFlux_HLLC(NewtonianIdealGasContext gas, State left, State right, const CeedScalar normal[3]) {
282*9ed3d70dSJames Wright   StateConservative flux_left  = FluxInviscidDotNormal(gas, left, normal);
283*9ed3d70dSJames Wright   StateConservative flux_right = FluxInviscidDotNormal(gas, right, normal);
284*9ed3d70dSJames Wright 
285*9ed3d70dSJames Wright   CeedScalar u_left  = Dot3(left.Y.velocity, normal);
286*9ed3d70dSJames Wright   CeedScalar u_right = Dot3(right.Y.velocity, normal);
287*9ed3d70dSJames Wright   CeedScalar s_left, s_right;
288*9ed3d70dSJames Wright   ComputeHLLSpeeds_Roe(gas, left, u_left, right, u_right, &s_left, &s_right);
289*9ed3d70dSJames Wright 
290*9ed3d70dSJames Wright   // Contact wave speed; Toro (10.37)
291*9ed3d70dSJames Wright   CeedScalar rhou_left = left.U.density * u_left, rhou_right = right.U.density * u_right;
292*9ed3d70dSJames Wright   CeedScalar numer  = right.Y.pressure - left.Y.pressure + rhou_left * (s_left - u_left) - rhou_right * (s_right - u_right);
293*9ed3d70dSJames Wright   CeedScalar denom  = left.U.density * (s_left - u_left) - right.U.density * (s_right - u_right);
294*9ed3d70dSJames Wright   CeedScalar s_star = numer / denom;
295*9ed3d70dSJames Wright 
296*9ed3d70dSJames Wright   // Compute HLLC flux
297*9ed3d70dSJames Wright   if (0 <= s_left) {
298*9ed3d70dSJames Wright     return flux_left;
299*9ed3d70dSJames Wright   } else if (0 <= s_star) {
300*9ed3d70dSJames Wright     return RiemannFlux_HLLC_Star(gas, left, flux_left, normal, u_left, s_left, s_star);
301*9ed3d70dSJames Wright   } else if (0 <= s_right) {
302*9ed3d70dSJames Wright     return RiemannFlux_HLLC_Star(gas, right, flux_right, normal, u_right, s_right, s_star);
303*9ed3d70dSJames Wright   } else {
304*9ed3d70dSJames Wright     return flux_right;
305*9ed3d70dSJames Wright   }
306*9ed3d70dSJames Wright }
307*9ed3d70dSJames Wright 
308*9ed3d70dSJames Wright CEED_QFUNCTION_HELPER StateConservative RiemannFlux_HLLC_fwd(NewtonianIdealGasContext gas, State left, State dleft, State right, State dright,
309*9ed3d70dSJames Wright                                                              const CeedScalar normal[3]) {
310*9ed3d70dSJames Wright   StateConservative flux_left   = FluxInviscidDotNormal(gas, left, normal);
311*9ed3d70dSJames Wright   StateConservative flux_right  = FluxInviscidDotNormal(gas, right, normal);
312*9ed3d70dSJames Wright   StateConservative dflux_left  = FluxInviscidDotNormal_fwd(gas, left, dleft, normal);
313*9ed3d70dSJames Wright   StateConservative dflux_right = FluxInviscidDotNormal_fwd(gas, right, dright, normal);
314*9ed3d70dSJames Wright 
315*9ed3d70dSJames Wright   CeedScalar u_left   = Dot3(left.Y.velocity, normal);
316*9ed3d70dSJames Wright   CeedScalar u_right  = Dot3(right.Y.velocity, normal);
317*9ed3d70dSJames Wright   CeedScalar du_left  = Dot3(dleft.Y.velocity, normal);
318*9ed3d70dSJames Wright   CeedScalar du_right = Dot3(dright.Y.velocity, normal);
319*9ed3d70dSJames Wright 
320*9ed3d70dSJames Wright   CeedScalar s_left, ds_left, s_right, ds_right;
321*9ed3d70dSJames Wright   ComputeHLLSpeeds_Roe_fwd(gas, left, dleft, u_left, du_left, right, dright, u_right, du_right, &s_left, &ds_left, &s_right, &ds_right);
322*9ed3d70dSJames Wright 
323*9ed3d70dSJames Wright   // Contact wave speed; Toro (10.37)
324*9ed3d70dSJames Wright   CeedScalar rhou_left = left.U.density * u_left, drhou_left = left.U.density * du_left + dleft.U.density * u_left;
325*9ed3d70dSJames Wright   CeedScalar rhou_right = right.U.density * u_right, drhou_right = right.U.density * du_right + dright.U.density * u_right;
326*9ed3d70dSJames Wright   CeedScalar numer = right.Y.pressure - left.Y.pressure  //
327*9ed3d70dSJames Wright                      + rhou_left * (s_left - u_left)     //
328*9ed3d70dSJames Wright                      - rhou_right * (s_right - u_right);
329*9ed3d70dSJames Wright   CeedScalar dnumer = dright.Y.pressure - dleft.Y.pressure                                //
330*9ed3d70dSJames Wright                       + rhou_left * (ds_left - du_left) + drhou_left * (s_left - u_left)  //
331*9ed3d70dSJames Wright                       - rhou_right * (ds_right - du_right) - drhou_right * (s_right - u_right);
332*9ed3d70dSJames Wright   CeedScalar denom  = left.U.density * (s_left - u_left) - right.U.density * (s_right - u_right);
333*9ed3d70dSJames Wright   CeedScalar ddenom = left.U.density * (ds_left - du_left) + dleft.U.density * (s_left - u_left)  //
334*9ed3d70dSJames Wright                       - right.U.density * (ds_right - du_right) - dright.U.density * (s_right - u_right);
335*9ed3d70dSJames Wright   CeedScalar s_star  = numer / denom;
336*9ed3d70dSJames Wright   CeedScalar ds_star = dnumer / denom - numer / Square(denom) * ddenom;
337*9ed3d70dSJames Wright 
338*9ed3d70dSJames Wright   // Compute HLLC flux
339*9ed3d70dSJames Wright   if (0 <= s_left) {
340*9ed3d70dSJames Wright     return dflux_left;
341*9ed3d70dSJames Wright   } else if (0 <= s_star) {
342*9ed3d70dSJames Wright     return RiemannFlux_HLLC_Star_fwd(gas, left, dleft, flux_left, dflux_left, normal, u_left, du_left, s_left, ds_left, s_star, ds_star);
343*9ed3d70dSJames Wright   } else if (0 <= s_right) {
344*9ed3d70dSJames Wright     return RiemannFlux_HLLC_Star_fwd(gas, right, dright, flux_right, dflux_right, normal, u_right, du_right, s_right, ds_right, s_star, ds_star);
345*9ed3d70dSJames Wright   } else {
346*9ed3d70dSJames Wright     return dflux_right;
347*9ed3d70dSJames Wright   }
348*9ed3d70dSJames Wright }
349*9ed3d70dSJames Wright 
350*9ed3d70dSJames Wright #endif  // riemann_solver_h
351