Theseus
Compressible flow solver
Loading...
Searching...
No Matches
theseus_kernels.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 <cmath>
9#include "mfem.hpp"
10
11namespace Theseus
12{
13 constexpr const int MAXEQ = 5;
14 constexpr const int MAXDIM = 3;
15
16 namespace Kernels {
17 MFEM_HOST_DEVICE inline mfem::real_t rmax(mfem::real_t a, mfem::real_t b) { return a > b ? a : b; }
18 MFEM_HOST_DEVICE inline mfem::real_t rmin(mfem::real_t a, mfem::real_t b) { return a < b ? a : b; }
19 MFEM_HOST_DEVICE inline mfem::real_t rsqrt(mfem::real_t x) { return std::sqrt(x); } // mfem::sqrt?
20 MFEM_HOST_DEVICE inline mfem::real_t rlog(mfem::real_t x) { return std::log(x); } // mfem::log?
21 MFEM_HOST_DEVICE inline mfem::real_t rpow(mfem::real_t x, mfem::real_t y) { return std::pow(x, y); };
22 MFEM_HOST_DEVICE inline mfem::real_t rabs(mfem::real_t x) { return std::abs(x); };
23
24 MFEM_HOST_DEVICE inline void Normalize(const int dim, mfem::real_t *vec){
25 mfem::real_t fac = 0.0;
26 for(int idim = 0;idim < dim;idim++){
27 fac += (vec[idim]*vec[idim]);
28 }
29 fac = 1.0/rsqrt(fac);
30 for(int idim = 0;idim < dim;idim++){
31 vec[idim] *= fac;
32 }
33 }
34
35 MFEM_HOST_DEVICE
36 inline void Normal(const int dim, const mfem::real_t *vec, mfem::real_t *nor)
37 {
38 // MFEM_ASSERT(dim == 2 || dim == 3, "Normal only defined here for 2D/3D");
39
40 if (dim == 2)
41 {
42 nor[0] = -vec[1];
43 nor[1] = vec[0];
44 return;
45 }
46
47 // 3D
48 const mfem::real_t x = vec[0];
49 const mfem::real_t y = vec[1];
50 const mfem::real_t z = vec[2];
51
52 const mfem::real_t ax = std::fabs(x);
53 const mfem::real_t ay = std::fabs(y);
54 const mfem::real_t az = std::fabs(z);
55
56 // Reject zero vector
57 // MFEM_ASSERT(ax > 0 || ay > 0 || az > 0, "Zero vector has no normal");
58
59 // Pick the coordinate axis least aligned with vec.
60 // Then nor = vec x e_i.
61 if (ax <= ay && ax <= az)
62 {
63 nor[0] = 0.0;
64 nor[1] = z;
65 nor[2] = -y;
66 }
67 else if (ay <= ax && ay <= az)
68 {
69 nor[0] = -z;
70 nor[1] = 0.0;
71 nor[2] = x;
72 }
73 else
74 {
75 nor[0] = y;
76 nor[1] = -x;
77 nor[2] = 0.0;
78 }
79 }
80
81 MFEM_HOST_DEVICE
82 inline mfem::real_t Dot(const int dim, const mfem::real_t *vec1, const mfem::real_t *vec2)
83 {
84 mfem::real_t dp = 0.0;
85 for(int idim = 0;idim < dim;idim++)
86 dp += vec1[idim]*vec2[idim];
87 return dp;
88 }
89
90 MFEM_HOST_DEVICE
91 inline void Cross(const int dim, const mfem::real_t *vec1, const mfem::real_t *vec2, mfem::real_t *cross)
92 {
93 // MFEM_ASSERT(dim == 3, "Apply cross product only to 3D vectors");
94
95 cross[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
96 cross[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
97 cross[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
98 }
99
100 MFEM_HOST_DEVICE
101 inline void ComputeMeanVec(const mfem::real_t* a, const mfem::real_t* b, mfem::real_t* out, int n)
102 {
103 for (int i=0;i<n;++i) out[i] = mfem::real_t(0.5)*(a[i]+b[i]);
104 }
105
106 MFEM_HOST_DEVICE
107 inline mfem::real_t ComputeLogMean(mfem::real_t x, mfem::real_t y, mfem::real_t eps) // eps defaults to 1e-4 on CPU
108 {
109 const mfem::real_t xi = y / x;
110 const mfem::real_t u = (xi*(xi - 2.0) + 1.0) / (xi*(xi + 2.0) + 1.0);
111
112 // polynomial approximation branch when u is small
113 if (u < eps)
114 {
115 // (x+y)*52.5 / (105 + u*(35 + u*(21 + 15*u)))
116 const mfem::real_t denom = 105.0 + u*(35.0 + u*(21.0 + 15.0*u));
117 return (x + y) * 52.5 / denom;
118 }
119 else
120 {
121 return (y - x) / Kernels::rlog(xi);
122 }
123 }
124
125 // Element storage: component-major (q blocks), length = dof*num_eq
126 // u[q*dof + id]
127 MFEM_HOST_DEVICE inline
128 mfem::real_t el_get(const mfem::real_t *u, int dof, int num_eq, int id, int q)
129 {
130 (void)num_eq; // not needed for this layout
131 return u[q*dof + id];
132 }
133
134 MFEM_HOST_DEVICE inline
135 void el_gather_state(const mfem::real_t *u, const int dof, const int num_eq, const int id, mfem::real_t *dst)
136 {
137 // MFEM_ASSERT(id >= 0 && id < dof, "element index out of bounds");
138 for (int q = 0; q < num_eq; ++q)
139 dst[q] = u[q*dof + id];
140 }
141
142 MFEM_HOST_DEVICE inline
143 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,
144 const int dim, const int dof, const int neq, const int id,
145 mfem::real_t *dqx, mfem::real_t *dqy, mfem::real_t *dqz)
146 {
147 el_gather_state(grad_state_x, dof, neq, id, dqx);
148 if (dim > 1) el_gather_state(grad_state_y, dof, neq, id, dqy);
149 if (dim > 2) el_gather_state(grad_state_z, dof, neq, id, dqz);
150 }
151
152 MFEM_HOST_DEVICE inline
153 void el_scatter_add(const mfem::real_t *f,
154 const int dof,
155 const int num_eq,
156 const int id,
157 const mfem::real_t scale,
158 mfem::real_t *du)
159 {
160 // MFEM_ASSERT(id >= 0 && id < dof, "element index out of bounds");
161 // Element storage is component-major (byVDIM):
162 // du[q*dof + id] corresponds to "row id, component q" in DenseMatrix(dof, num_eq)
163 for (int q = 0; q < num_eq; ++q)
164 {
165 du[id + q*dof] += scale * f[q];
166 }
167 }
168
169 MFEM_HOST_DEVICE inline
170 void el_scatter_assign(const mfem::real_t *f,
171 const int dof,
172 const int num_eq,
173 const int id,
174 const mfem::real_t scale,
175 mfem::real_t *du)
176 {
177 // MFEM_ASSERT(id >= 0 && id < dof, "element index out of bounds");
178 // Element storage is component-major (byVDIM):
179 // du[q*dof + id] corresponds to "row id, component q" in DenseMatrix(dof, num_eq)
180 for (int q = 0; q < num_eq; ++q)
181 {
182 du[id + q*dof] = scale * f[q];
183 }
184 }
185
186 MFEM_HOST_DEVICE inline
187 void el_scale(const mfem::real_t *scale_d,
188 const mfem::real_t fac,
189 const int dof, // scalar dofs per element
190 const int neq,
191 mfem::real_t *el_soln) // num equations
192 {
193 for (int id = 0; id < dof; ++id)
194 {
195 const mfem::real_t invJ = fac / scale_d[id];
196 for (int q = 0; q < neq; ++q)
197 {
198 el_soln[id + q*dof] *= invJ;
199 }
200 }
201 }
202
203 MFEM_HOST_DEVICE inline bool is_bad_value(mfem::real_t x)
204 {
205 return !std::isfinite(x);
206 }
207
208 }
209}
MFEM_HOST_DEVICE void Cross(const int dim, const mfem::real_t *vec1, const mfem::real_t *vec2, mfem::real_t *cross)
Definition theseus_kernels.hpp:91
MFEM_HOST_DEVICE void el_scale(const mfem::real_t *scale_d, const mfem::real_t fac, const int dof, const int neq, mfem::real_t *el_soln)
Definition theseus_kernels.hpp:187
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 el_get(const mfem::real_t *u, int dof, int num_eq, int id, int q)
Definition theseus_kernels.hpp:128
MFEM_HOST_DEVICE mfem::real_t rmin(mfem::real_t a, mfem::real_t b)
Definition theseus_kernels.hpp:18
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 mfem::real_t rlog(mfem::real_t x)
Definition theseus_kernels.hpp:20
MFEM_HOST_DEVICE void Normalize(const int dim, mfem::real_t *vec)
Definition theseus_kernels.hpp:24
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 Normal(const int dim, const mfem::real_t *vec, mfem::real_t *nor)
Definition theseus_kernels.hpp:36
MFEM_HOST_DEVICE mfem::real_t rsqrt(mfem::real_t x)
Definition theseus_kernels.hpp:19
MFEM_HOST_DEVICE void el_scatter_assign(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:170
MFEM_HOST_DEVICE mfem::real_t ComputeLogMean(mfem::real_t x, mfem::real_t y, mfem::real_t eps)
Definition theseus_kernels.hpp:107
MFEM_HOST_DEVICE bool is_bad_value(mfem::real_t x)
Definition theseus_kernels.hpp:203
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
MFEM_HOST_DEVICE mfem::real_t rpow(mfem::real_t x, mfem::real_t y)
Definition theseus_kernels.hpp:21
MFEM_HOST_DEVICE mfem::real_t Dot(const int dim, const mfem::real_t *vec1, const mfem::real_t *vec2)
Definition theseus_kernels.hpp:82
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