Theseus
Compressible flow solver
Loading...
Searching...
No Matches
LaxFriedrichsFlux.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 LaxFriedrichsFlux
16 {
17
18 // This is Riemann solver that computes the numerical flux for 2 point states
19 // Will be ctx.iflux.ComputeVolumeFlux
20 template<typename GasT>
21 MFEM_HOST_DEVICE
22 inline static mfem::real_t ComputeVolumeFluxKernel(const GasT &gas,
23 const mfem::real_t* q1,
24 const mfem::real_t* q2,
25 const mfem::real_t* met1,
26 const mfem::real_t* met2,
27 mfem::real_t* F_tilde)
28 {
29 const int dim = gas.dim();
30 const int neq = gas.num_equations();
31
32 // mean metric row
33 mfem::real_t met[3] = {0,0,0};
34 Kernels::ComputeMeanVec(met1, met2, met, dim);
37 mfem::real_t inv_flux_1[Theseus::MAXEQ][Theseus::MAXDIM];
38 mfem::real_t inv_flux_2[Theseus::MAXEQ][Theseus::MAXDIM];
39 mfem::real_t inv_flux_bar[Theseus::MAXEQ];
40
41 NavierStokesFlux::ComputeInviscidFluxKernel(gas, q1, inv_flux_1);
42 NavierStokesFlux::ComputeInviscidFluxKernel(gas, q2, inv_flux_2);
43 for(int ieq=0;ieq < neq;ieq++){
44 inv_flux_bar[ieq] = 0;
45 for(int idim = 0;idim < dim;idim++){
46 inv_flux_bar[ieq] += 0.5*(inv_flux_1[ieq][idim] + inv_flux_2[ieq][idim])*met[idim];
47 }
48 }
49
50 mfem::real_t vn_1 = 0;
51 mfem::real_t vn_2 = 0;
52 mfem::real_t mnorm = 0;
53 for (int d=0; d<dim; ++d)
54 {
55 const mfem::real_t v1 = gas.velocity(S1, d);
56 const mfem::real_t v2 = gas.velocity(S2, d);
57 vn_1 += v1*met[d];
58 vn_2 += v2*met[d];
59 mnorm += met[d]*met[d];
60 }
61 vn_1 = Theseus::Kernels::rabs(vn_1);
62 vn_2 = Theseus::Kernels::rabs(vn_2);
63 mnorm = Theseus::Kernels::rsqrt(mnorm);
64 const mfem::real_t c1 = gas.sound_speed(S1)*mnorm;
65 const mfem::real_t c2 = gas.sound_speed(S2)*mnorm;
66 const mfem::real_t lambda_max = Kernels::rmax(vn_1 + c1, vn_2 + c2);
67
68 for(int ieq = 0;ieq < neq;ieq++){
69 F_tilde[ieq] = inv_flux_bar[ieq];
70 }
71
72 return lambda_max;
73 }
74
75 template<typename GasModelT>
76 MFEM_HOST_DEVICE inline static mfem::real_t
77 ComputeFaceFluxKernel(const GasModelT &gasModel,
78 const mfem::real_t *state1,
79 const mfem::real_t *state2,
80 const mfem::real_t *nor,
81 mfem::real_t *flux)
82 {
83 const int dim = gasModel.dim();
84 const int neq = gasModel.num_equations();
85
86 Theseus::PointStateView S1{state1};
87 Theseus::PointStateView S2{state2};
88
89 mfem::real_t inv_flux_1[Theseus::MAXEQ][Theseus::MAXDIM];
90 mfem::real_t inv_flux_2[Theseus::MAXEQ][Theseus::MAXDIM];
91
92 NavierStokesFlux::ComputeInviscidFluxKernel(gasModel, state1, inv_flux_1);
93 NavierStokesFlux::ComputeInviscidFluxKernel(gasModel, state2, inv_flux_2);
94
95 mfem::real_t vn1 = 0.0;
96 mfem::real_t vn2 = 0.0;
97 mfem::real_t nor_mag2 = 0.0;
98
99 for (int d = 0; d < dim; ++d)
100 {
101 vn1 += gasModel.velocity(S1, d) * nor[d];
102 vn2 += gasModel.velocity(S2, d) * nor[d];
103 nor_mag2 += nor[d] * nor[d];
104 }
105
106 const mfem::real_t nor_mag = Theseus::Kernels::rsqrt(nor_mag2);
107
108 vn1 = Theseus::Kernels::rabs(vn1);
109 vn2 = Theseus::Kernels::rabs(vn2);
110
111 const mfem::real_t c1 = gasModel.sound_speed(S1);
112 const mfem::real_t c2 = gasModel.sound_speed(S2);
113 const mfem::real_t lambda_max =
114 Theseus::Kernels::rmax(vn1 + c1 * nor_mag,
115 vn2 + c2 * nor_mag);
116
117 for (int ieq = 0; ieq < neq; ++ieq)
118 {
119 mfem::real_t fn1 = 0.0;
120 mfem::real_t fn2 = 0.0;
121
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
128 const mfem::real_t central_flux = 0.5 * (fn1 + fn2);
129 const mfem::real_t jump = state2[ieq] - state1[ieq];
130
131 flux[ieq] = central_flux - 0.5 * lambda_max * jump;
132 }
133 return lambda_max;
134 }
135
137 template<typename GasModelT>
138 MFEM_HOST_DEVICE inline mfem::real_t ComputeVolumeFlux(const GasModelT &gasModel,
139 const mfem::real_t *q1, const mfem::real_t *q2,
140 const mfem::real_t *met1, const mfem::real_t *met2,
141 mfem::real_t *F_tilde) const{
142 return ComputeVolumeFluxKernel(gasModel, q1, q2, met1, met2, F_tilde);
143 }
144 template<typename GasModelT>
145 MFEM_HOST_DEVICE inline mfem::real_t ComputeFaceFlux(const GasModelT &gasModel,const mfem::real_t *qminus,
146 const mfem::real_t *qplus, const mfem::real_t *nor,
147 mfem::real_t *flux) const {
148 return ComputeFaceFluxKernel(gasModel, qminus, qplus, nor, flux);
149 }
150 };
151 };
152}
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 LaxFriedrichsFlux.hpp:136
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 LaxFriedrichsFlux.hpp:138
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 LaxFriedrichsFlux.hpp:145
Definition GasState.hpp:127