Theseus
Compressible flow solver
Loading...
Searching...
No Matches
AxisymmetricSource.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
9#include "GasState.hpp"
10#include "NavierStokesFlux.hpp"
11
12namespace Theseus
13{
16 template<typename GasT>
17 MFEM_HOST_DEVICE inline bool AddAxisymmetricEulerSourceAwayFromAxis(
18 const GasT &gas, const mfem::real_t *state, mfem::real_t radius,
19 mfem::real_t *state_rate)
20 {
22 {
23 return false;
24 }
25
26 PointStateView U{state};
27 const mfem::real_t density = gas.density(U);
28 const mfem::real_t axial_momentum =
30 const mfem::real_t radial_momentum =
32 const mfem::real_t radial_velocity = radial_momentum / density;
33 const mfem::real_t inverse_radius = 1.0 / radius;
34
35 state_rate[gas.L.eq_mass] -= radial_momentum * inverse_radius;
36 state_rate[gas.L.eq_mom[AxisymmetricGeometry::axial_coordinate]] -=
37 axial_momentum * radial_velocity * inverse_radius;
38 state_rate[gas.L.eq_mom[AxisymmetricGeometry::radial_coordinate]] -=
39 radial_momentum * radial_velocity * inverse_radius;
40 state_rate[gas.L.eq_energy] -=
41 (gas.energy(U) + gas.pressure(U)) * radial_velocity * inverse_radius;
42 return true;
43 }
44
45 template<typename GasT>
46 MFEM_HOST_DEVICE inline void AddAxisymmetricEulerSourceAtAxis(
47 const GasT &gas, const mfem::real_t *state,
48 mfem::real_t radial_momentum_derivative, mfem::real_t *state_rate)
49 {
50 PointStateView U{state};
51 const mfem::real_t density = gas.density(U);
52 const mfem::real_t axial_velocity =
54 const mfem::real_t total_enthalpy =
55 (gas.energy(U) + gas.pressure(U)) / density;
56
57 state_rate[gas.L.eq_mass] -= radial_momentum_derivative;
58 state_rate[gas.L.eq_mom[AxisymmetricGeometry::axial_coordinate]] -=
59 axial_velocity * radial_momentum_derivative;
60 // The radial-momentum limit is zero because rho*u_r^2/r is odd.
61 state_rate[gas.L.eq_energy] -=
62 total_enthalpy * radial_momentum_derivative;
63 }
64
67 template<typename GasT>
68 MFEM_HOST_DEVICE inline bool AddAxisymmetricViscousSourceAwayFromAxis(
69 const GasT &gas, const mfem::real_t *state,
70 const mfem::real_t *dprim_x, const mfem::real_t *dprim_y,
71 const mfem::real_t *dprim_z, mfem::real_t radius,
72 mfem::real_t *state_rate)
73 {
75 {
76 return false;
77 }
78
79 mfem::real_t viscous_flux[Theseus::MAXEQ][Theseus::MAXDIM];
80 mfem::real_t azimuthal_stress = 0.0;
81 NavierStokesFlux::ComputeViscousFluxKernel(
82 gas, state, dprim_x, dprim_y, dprim_z, viscous_flux, true, radius,
83 &azimuthal_stress);
84
87 const mfem::real_t inverse_radius = 1.0 / radius;
88 state_rate[gas.L.eq_mom[axial]] +=
89 viscous_flux[gas.L.eq_mom[axial]][radial] * inverse_radius;
90 state_rate[gas.L.eq_mom[radial]] +=
91 (viscous_flux[gas.L.eq_mom[radial]][radial] - azimuthal_stress) *
92 inverse_radius;
93 state_rate[gas.L.eq_energy] +=
94 viscous_flux[gas.L.eq_energy][radial] * inverse_radius;
95 return true;
96 }
97
98 template<typename ContextT>
99 MFEM_HOST_DEVICE inline mfem::real_t RadialViscousFluxDerivative(
100 const ContextT &ctx, const mfem::real_t *element_state,
101 const mfem::real_t *element_gradprim_x,
102 const mfem::real_t *element_gradprim_y,
103 const mfem::real_t *element_gradprim_z,
104 const mfem::real_t *element_radius,
105 const mfem::real_t *element_jacobian,
106 const mfem::real_t *element_metric, int point, int equation)
107 {
108 const int nx = ctx.Np_x;
109 const int ny = ctx.Np_y;
110 const int dof = ctx.ndof_scalar_el;
111 const int equations = ctx.num_equations;
112 const int i = point % nx;
113 const int j = (point / nx) % ny;
114 mfem::real_t derivative_xi = 0.0;
115 mfem::real_t derivative_eta = 0.0;
116 mfem::real_t state[Theseus::MAXEQ];
117 mfem::real_t dprim_x[Theseus::MAXEQ];
118 mfem::real_t dprim_y[Theseus::MAXEQ];
119 mfem::real_t dprim_z[Theseus::MAXEQ];
120 mfem::real_t flux[Theseus::MAXEQ][Theseus::MAXDIM];
121 for (int l = 0; l < nx; ++l)
122 {
123 const int sample = j*nx + l;
125 element_state, dof, equations, sample, state);
127 element_gradprim_x, element_gradprim_y, element_gradprim_z,
128 ctx.dim, dof, equations, sample, dprim_x, dprim_y, dprim_z);
129 NavierStokesFlux::ComputeViscousFluxKernel(
130 ctx.gas, state, dprim_x, dprim_y, dprim_z, flux, true,
131 element_radius[sample]);
132 derivative_xi +=
134 ctx.D_d[l + nx*i];
135 }
136 for (int l = 0; l < ny; ++l)
137 {
138 const int sample = l*nx + i;
140 element_state, dof, equations, sample, state);
142 element_gradprim_x, element_gradprim_y, element_gradprim_z,
143 ctx.dim, dof, equations, sample, dprim_x, dprim_y, dprim_z);
144 NavierStokesFlux::ComputeViscousFluxKernel(
145 ctx.gas, state, dprim_x, dprim_y, dprim_z, flux, true,
146 element_radius[sample]);
147 derivative_eta +=
149 ctx.D_d[l + ny*j];
150 }
151
152 const mfem::real_t *adjugate = element_metric + point*ctx.dim*ctx.dim;
153 return (derivative_xi *
155 derivative_eta *
156 adjugate[ctx.dim + AxisymmetricGeometry::radial_coordinate]) /
157 element_jacobian[point];
158 }
159
160 template<typename ContextT>
161 MFEM_HOST_DEVICE inline void AddAxisymmetricViscousSourceAtAxis(
162 const ContextT &ctx, const mfem::real_t *element_state,
163 const mfem::real_t *element_gradprim_x,
164 const mfem::real_t *element_gradprim_y,
165 const mfem::real_t *element_gradprim_z,
166 const mfem::real_t *element_radius,
167 const mfem::real_t *element_jacobian,
168 const mfem::real_t *element_metric, int point,
169 mfem::real_t *state_rate)
170 {
171 const int axial_momentum =
173 state_rate[axial_momentum] += RadialViscousFluxDerivative(
174 ctx, element_state, element_gradprim_x, element_gradprim_y,
175 element_gradprim_z, element_radius, element_jacobian,
176 element_metric, point, axial_momentum);
177 state_rate[ctx.gas.L.eq_energy] += RadialViscousFluxDerivative(
178 ctx, element_state, element_gradprim_x, element_gradprim_y,
179 element_gradprim_z, element_radius, element_jacobian,
180 element_metric, point, ctx.gas.L.eq_energy);
181 // (tau_rr - tau_theta_theta)/r tends to zero by axis parity.
182 }
183
184 template<typename ContextT>
185 MFEM_HOST_DEVICE inline mfem::real_t RadialMomentumDerivative(
186 const ContextT &ctx, const mfem::real_t *element_state,
187 const mfem::real_t *element_jacobian,
188 const mfem::real_t *element_metric, int point)
189 {
190 const int nx = ctx.Np_x;
191 const int ny = ctx.Np_y;
192 const int dof = ctx.ndof_scalar_el;
193 const int radial_momentum_equation =
195 const int i = point % nx;
196 const int j = (point / nx) % ny;
197 mfem::real_t derivative_xi = 0.0;
198 mfem::real_t derivative_eta = 0.0;
199 for (int l = 0; l < nx; ++l)
200 {
201 derivative_xi +=
202 element_state[j*nx + l + radial_momentum_equation*dof] *
203 ctx.D_d[l + nx*i];
204 }
205 for (int l = 0; l < ny; ++l)
206 {
207 derivative_eta +=
208 element_state[l*nx + i + radial_momentum_equation*dof] *
209 ctx.D_d[l + ny*j];
210 }
211
212 const mfem::real_t *adjugate = element_metric + point*ctx.dim*ctx.dim;
213 return (derivative_xi *
215 derivative_eta *
216 adjugate[ctx.dim + AxisymmetricGeometry::radial_coordinate]) /
217 element_jacobian[point];
218 }
219
220 template<typename ContextT>
221 MFEM_HOST_DEVICE inline void AddAxisymmetricEulerElementSource(
222 const ContextT &ctx, const mfem::real_t *element_state,
223 const mfem::real_t *element_radius,
224 const mfem::real_t *element_jacobian,
225 const mfem::real_t *element_metric, mfem::real_t *element_rate)
226 {
227 if (!ctx.axisymmetric)
228 {
229 return;
230 }
231
232 const int dof = ctx.ndof_scalar_el;
233 const int equations = ctx.num_equations;
234 mfem::real_t state[Theseus::MAXEQ];
235 mfem::real_t source[Theseus::MAXEQ];
236 for (int point = 0; point < dof; ++point)
237 {
238 Kernels::el_gather_state(element_state, dof, equations, point, state);
239 for (int equation = 0; equation < equations; ++equation)
240 {
241 source[equation] = 0.0;
242 }
244 ctx.gas, state, element_radius[point], source))
245 {
247 ctx.gas, state,
248 RadialMomentumDerivative(ctx, element_state,
249 element_jacobian, element_metric,
250 point),
251 source);
252 }
253 Kernels::el_scatter_add(source, dof, equations, point, 1.0,
254 element_rate);
255 }
256 }
257
260 template<typename GasT>
261 MFEM_HOST_DEVICE inline bool ProjectAxisPrimitiveGradientDirection(
262 const GasT &gas, mfem::real_t radius, int derivative_direction,
263 mfem::real_t *dprim)
264 {
265 if (radius > AxisymmetricGeometry::radius_tolerance){ return false; }
268 const int radial_velocity = gas.L.eq_mom[radial];
269 if (derivative_direction == radial)
270 {
271 const mfem::real_t radial_velocity_derivative =
272 dprim[radial_velocity];
273 for (int equation = 0; equation < gas.L.nequations(); ++equation)
274 {
275 dprim[equation] = 0.0;
276 }
277 // u_r is odd, so its radial derivative is even and need not vanish.
278 dprim[radial_velocity] = radial_velocity_derivative;
279 }
280 else if (derivative_direction == axial)
281 {
282 // The axial derivative of the odd radial velocity vanishes on axis.
283 dprim[radial_velocity] = 0.0;
284 }
285 return true;
286 }
287}
MFEM_HOST_DEVICE void el_scatter_add(const mfem::real_t *f, const int dof, const int num_eq, const int id, const mfem::real_t scale, mfem::real_t *du)
Definition theseus_kernels.hpp:153
MFEM_HOST_DEVICE void el_gather_state(const mfem::real_t *u, const int dof, const int num_eq, const int id, mfem::real_t *dst)
Definition theseus_kernels.hpp:135
MFEM_HOST_DEVICE void el_gather_grad_state(const mfem::real_t *grad_state_x, const mfem::real_t *grad_state_y, const mfem::real_t *grad_state_z, const int dim, const int dof, const int neq, const int id, mfem::real_t *dqx, mfem::real_t *dqy, mfem::real_t *dqz)
Definition theseus_kernels.hpp:143
Definition AxisymmetricGeometry.hpp:15
MFEM_HOST_DEVICE bool AddAxisymmetricViscousSourceAwayFromAxis(const GasT &gas, const mfem::real_t *state, const mfem::real_t *dprim_x, const mfem::real_t *dprim_y, const mfem::real_t *dprim_z, mfem::real_t radius, mfem::real_t *state_rate)
Definition AxisymmetricSource.hpp:68
MFEM_HOST_DEVICE void AddAxisymmetricEulerElementSource(const ContextT &ctx, const mfem::real_t *element_state, const mfem::real_t *element_radius, const mfem::real_t *element_jacobian, const mfem::real_t *element_metric, mfem::real_t *element_rate)
Definition AxisymmetricSource.hpp:221
MFEM_HOST_DEVICE void AddAxisymmetricEulerSourceAtAxis(const GasT &gas, const mfem::real_t *state, mfem::real_t radial_momentum_derivative, mfem::real_t *state_rate)
Definition AxisymmetricSource.hpp:46
constexpr const int MAXDIM
Definition theseus_kernels.hpp:14
MFEM_HOST_DEVICE mfem::real_t RadialViscousFluxDerivative(const ContextT &ctx, const mfem::real_t *element_state, const mfem::real_t *element_gradprim_x, const mfem::real_t *element_gradprim_y, const mfem::real_t *element_gradprim_z, const mfem::real_t *element_radius, const mfem::real_t *element_jacobian, const mfem::real_t *element_metric, int point, int equation)
Definition AxisymmetricSource.hpp:99
constexpr const int MAXEQ
Definition theseus_kernels.hpp:13
MFEM_HOST_DEVICE mfem::real_t RadialMomentumDerivative(const ContextT &ctx, const mfem::real_t *element_state, const mfem::real_t *element_jacobian, const mfem::real_t *element_metric, int point)
Definition AxisymmetricSource.hpp:185
MFEM_HOST_DEVICE void AddAxisymmetricViscousSourceAtAxis(const ContextT &ctx, const mfem::real_t *element_state, const mfem::real_t *element_gradprim_x, const mfem::real_t *element_gradprim_y, const mfem::real_t *element_gradprim_z, const mfem::real_t *element_radius, const mfem::real_t *element_jacobian, const mfem::real_t *element_metric, int point, mfem::real_t *state_rate)
Definition AxisymmetricSource.hpp:161
MFEM_HOST_DEVICE bool ProjectAxisPrimitiveGradientDirection(const GasT &gas, mfem::real_t radius, int derivative_direction, mfem::real_t *dprim)
Definition AxisymmetricSource.hpp:261
MFEM_HOST_DEVICE bool AddAxisymmetricEulerSourceAwayFromAxis(const GasT &gas, const mfem::real_t *state, mfem::real_t radius, mfem::real_t *state_rate)
Definition AxisymmetricSource.hpp:17
static constexpr mfem::real_t radius_tolerance
Definition AxisymmetricGeometry.hpp:22
static constexpr int axial_coordinate
Definition AxisymmetricGeometry.hpp:19
static constexpr int radial_coordinate
Definition AxisymmetricGeometry.hpp:20
Definition GasState.hpp:127
MFEM_HOST_DEVICE mfem::real_t momentum(const StateLayout &L, int d) const
Definition GasState.hpp:147