Theseus
Compressible flow solver
Loading...
Searching...
No Matches
HLLFlux.hpp
Go to the documentation of this file.
1// Copyright (c) 2025-2026 Board of Trustees of the University of Illinois
2//
3// This file is part of Theseus.
4//
5// SPDX-License-Identifier: BSD-3-Clause
6#pragma once
7
8#include "mfem.hpp"
10#include "theseus_kernels.hpp"
11
12namespace Theseus
13{
14
15 namespace HLLFlux
16 {
17 // This is a central flux method: also used by LLF, needs centralized
18 // TODO: Centralize the central flux method
19 template<typename GasT>
20 MFEM_HOST_DEVICE
21 inline static mfem::real_t ComputeVolumeFluxKernel(const GasT &gas,
22 const mfem::real_t* q1,
23 const mfem::real_t* q2,
24 const mfem::real_t* met1,
25 const mfem::real_t* met2,
26 mfem::real_t* F_tilde)
27 {
28 const int dim = gas.dim();
29 const int neq = gas.num_equations();
30
31 // mean metric row
32 mfem::real_t met[3] = {0,0,0};
33 Kernels::ComputeMeanVec(met1, met2, met, dim);
36 mfem::real_t inv_flux_1[Theseus::MAXEQ][Theseus::MAXDIM];
37 mfem::real_t inv_flux_2[Theseus::MAXEQ][Theseus::MAXDIM];
38 mfem::real_t inv_flux_bar[Theseus::MAXEQ];
39
40 NavierStokesFlux::ComputeInviscidFluxKernel(gas, q1, inv_flux_1);
41 NavierStokesFlux::ComputeInviscidFluxKernel(gas, q2, inv_flux_2);
42 for(int ieq=0;ieq < neq;ieq++){
43 inv_flux_bar[ieq] = 0;
44 for(int idim = 0;idim < dim;idim++){
45 inv_flux_bar[ieq] += 0.5*(inv_flux_1[ieq][idim] + inv_flux_2[ieq][idim])*met[idim];
46 }
47 }
48
49 mfem::real_t vn_1 = 0;
50 mfem::real_t vn_2 = 0;
51 mfem::real_t mnorm = 0;
52 for (int d=0; d<dim; ++d)
53 {
54 const mfem::real_t v1 = gas.velocity(S1, d);
55 const mfem::real_t v2 = gas.velocity(S2, d);
56 vn_1 += v1*met[d];
57 vn_2 += v2*met[d];
58 mnorm += met[d]*met[d];
59 }
60 vn_1 = Theseus::Kernels::rabs(vn_1);
61 vn_2 = Theseus::Kernels::rabs(vn_2);
62 mnorm = Theseus::Kernels::rsqrt(mnorm);
63 const mfem::real_t c1 = gas.sound_speed(S1)*mnorm;
64 const mfem::real_t c2 = gas.sound_speed(S2)*mnorm;
65 const mfem::real_t lambda_max = Kernels::rmax(vn_1 + c1, vn_2 + c2);
66
67 for(int ieq = 0;ieq < neq;ieq++){
68 F_tilde[ieq] = inv_flux_bar[ieq];
69 }
70
71 return lambda_max;
72 }
73
74 template<typename GasModelT>
75 MFEM_HOST_DEVICE inline static mfem::real_t
76 ComputeFaceFluxKernel(const GasModelT &gasModel,
77 const mfem::real_t *state1,
78 const mfem::real_t *state2,
79 const mfem::real_t *nor,
80 mfem::real_t *flux)
81 {
82 const int dim = gasModel.dim();
83 const int neq = gasModel.num_equations();
84
85 Theseus::PointStateView S1{state1};
86 Theseus::PointStateView S2{state2};
87
88 mfem::real_t inv_flux_1[Theseus::MAXEQ][Theseus::MAXDIM];
89 mfem::real_t inv_flux_2[Theseus::MAXEQ][Theseus::MAXDIM];
90
91 NavierStokesFlux::ComputeInviscidFluxKernel(gasModel, state1, inv_flux_1);
92 NavierStokesFlux::ComputeInviscidFluxKernel(gasModel, state2, inv_flux_2);
93
94 mfem::real_t un1 = 0.0;
95 mfem::real_t un2 = 0.0;
96 mfem::real_t nor_mag2 = 0.0;
97
98 for (int d = 0; d < dim; ++d)
99 {
100 un1 += gasModel.velocity(S1, d) * nor[d];
101 un2 += gasModel.velocity(S2, d) * nor[d];
102 nor_mag2 += nor[d] * nor[d];
103 }
104
105 const mfem::real_t nor_mag = Theseus::Kernels::rsqrt(nor_mag2);
106
107 const mfem::real_t c1 = gasModel.sound_speed(S1) * nor_mag;
108 const mfem::real_t c2 = gasModel.sound_speed(S2) * nor_mag;
109
110 const mfem::real_t sL1 = un1 - c1;
111 const mfem::real_t sL2 = un2 - c2;
112 const mfem::real_t sR1 = un1 + c1;
113 const mfem::real_t sR2 = un2 + c2;
114
115 const mfem::real_t sL = (sL1 < sL2) ? sL1 : sL2;
116 const mfem::real_t sR = (sR1 > sR2) ? sR1 : sR2;
117
118 for (int ieq = 0; ieq < neq; ++ieq)
119 {
120 mfem::real_t fn1 = 0.0;
121 mfem::real_t fn2 = 0.0;
122 for (int d = 0; d < dim; ++d)
123 {
124 fn1 += inv_flux_1[ieq][d] * nor[d];
125 fn2 += inv_flux_2[ieq][d] * nor[d];
126 }
127 if (sL >= 0.0)
128 {
129 flux[ieq] = fn1;
130 }
131 else if (sR <= 0.0)
132 {
133 flux[ieq] = fn2;
134 }
135 else
136 {
137 flux[ieq] =
138 (sR * fn1 - sL * fn2 + sL * sR * (state2[ieq] - state1[ieq]))
139 / (sR - sL);
140 }
141 }
142
145 }
146
148 template<typename GasModelT>
149 MFEM_HOST_DEVICE inline mfem::real_t ComputeVolumeFlux(const GasModelT &gasModel,
150 const mfem::real_t *q1, const mfem::real_t *q2,
151 const mfem::real_t *met1, const mfem::real_t *met2,
152 mfem::real_t *F_tilde) const{
153 return ComputeVolumeFluxKernel(gasModel, q1, q2, met1, met2, F_tilde);
154 }
155 template<typename GasModelT>
156 MFEM_HOST_DEVICE inline mfem::real_t ComputeFaceFlux(const GasModelT &gasModel,const mfem::real_t *qminus,
157 const mfem::real_t *qplus, const mfem::real_t *nor,
158 mfem::real_t *flux) const {
159 return ComputeFaceFluxKernel(gasModel, qminus, qplus, nor, flux);
160 }
161 };
162 };
163}
MFEM_HOST_DEVICE void ComputeMeanVec(const mfem::real_t *a, const mfem::real_t *b, mfem::real_t *out, int n)
Definition theseus_kernels.hpp:101
MFEM_HOST_DEVICE mfem::real_t rsqrt(mfem::real_t x)
Definition theseus_kernels.hpp:19
MFEM_HOST_DEVICE mfem::real_t rmax(mfem::real_t a, mfem::real_t b)
Definition theseus_kernels.hpp:17
MFEM_HOST_DEVICE mfem::real_t rabs(mfem::real_t x)
Definition theseus_kernels.hpp:22
Definition AxisymmetricGeometry.hpp:15
constexpr const int MAXDIM
Definition theseus_kernels.hpp:14
constexpr const int MAXEQ
Definition theseus_kernels.hpp:13
Definition HLLFlux.hpp:147
MFEM_HOST_DEVICE mfem::real_t ComputeVolumeFlux(const GasModelT &gasModel, const mfem::real_t *q1, const mfem::real_t *q2, const mfem::real_t *met1, const mfem::real_t *met2, mfem::real_t *F_tilde) const
Definition HLLFlux.hpp:149
MFEM_HOST_DEVICE mfem::real_t ComputeFaceFlux(const GasModelT &gasModel, const mfem::real_t *qminus, const mfem::real_t *qplus, const mfem::real_t *nor, mfem::real_t *flux) const
Definition HLLFlux.hpp:156
Definition GasState.hpp:127