Cholla 3.0.1-dev
Cholla - Massively parallel hydro on GPUs
Loading...
Searching...
No Matches
plm_cuda.h
Go to the documentation of this file.
1
5#ifndef PLMC_CUDA_H
6#define PLMC_CUDA_H
7
8#include "../global/global.h"
9#include "../grid/grid_enum.h"
10#include "../reconstruction/reconstruction_internals.h"
11#include "../utils/hydro_utilities.h"
12#include "../utils/mhd_utilities.h"
13
19template <int dir>
20__global__ __launch_bounds__(TPB) void PLM_cuda(Real *dev_conserved, Real *dev_bounds_L, Real *dev_bounds_R, int nx,
21 int ny, int nz, Real dx, Real dt, Real gamma);
22
23namespace reconstruction
24{
36void __device__ __host__ __inline__ PLM_Characteristic_Evolution(hydro_utilities::Primitive const &cell_i,
37 hydro_utilities::Primitive const &del_m, Real const dt,
38 Real const dx, Real const gamma,
39 hydro_utilities::Primitive &interface_R_imh,
40 hydro_utilities::Primitive &interface_L_iph)
41{
42 Real const dtodx = dt / dx;
43 Real const sound_speed = hydro_utilities::Calc_Sound_Speed(cell_i.pressure, cell_i.density, gamma);
44
45 // Compute the eigenvalues of the linearized equations in the
46 // primitive variables using the cell-centered primitive variables
47 Real const lambda_m = cell_i.velocity.x() - sound_speed;
48 Real const lambda_0 = cell_i.velocity.x();
49 Real const lambda_p = cell_i.velocity.x() + sound_speed;
50
51 // Integrate linear interpolation function over domain of dependence
52 // defined by max(min) eigenvalue
53 Real qx = -0.5 * fmin(lambda_m, 0.0) * dtodx;
54 interface_R_imh.density = interface_R_imh.density + qx * del_m.density;
55 interface_R_imh.velocity.x() = interface_R_imh.velocity.x() + qx * del_m.velocity.x();
56 interface_R_imh.velocity.y() = interface_R_imh.velocity.y() + qx * del_m.velocity.y();
57 interface_R_imh.velocity.z() = interface_R_imh.velocity.z() + qx * del_m.velocity.z();
58 interface_R_imh.pressure = interface_R_imh.pressure + qx * del_m.pressure;
59
60 qx = 0.5 * fmax(lambda_p, 0.0) * dtodx;
61 interface_L_iph.density = interface_L_iph.density - qx * del_m.density;
62 interface_L_iph.velocity.x() = interface_L_iph.velocity.x() - qx * del_m.velocity.x();
63 interface_L_iph.velocity.y() = interface_L_iph.velocity.y() - qx * del_m.velocity.y();
64 interface_L_iph.velocity.z() = interface_L_iph.velocity.z() - qx * del_m.velocity.z();
65 interface_L_iph.pressure = interface_L_iph.pressure - qx * del_m.pressure;
66
67#ifdef DE
68 interface_R_imh.gas_energy = interface_R_imh.gas_energy + qx * del_m.gas_energy;
69 interface_L_iph.gas_energy = interface_L_iph.gas_energy - qx * del_m.gas_energy;
70#endif // DE
71
72#ifdef SCALAR
73 for (int i = 0; i < NSCALARS; i++) {
74 interface_R_imh.scalar[i] = interface_R_imh.scalar[i] + qx * del_m.scalar[i];
75 interface_L_iph.scalar[i] = interface_L_iph.scalar[i] - qx * del_m.scalar[i];
76 }
77#endif // SCALAR
78
79 // Perform the characteristic tracing
80 // Stone Eqns 42 & 43
81
82 // left-hand interface value, i+1/2
83 Real sum_0 = 0.0, sum_1 = 0.0, sum_2 = 0.0, sum_3 = 0.0, sum_4 = 0.0;
84#ifdef DE
85 Real sum_ge = 0;
86#endif // DE
87#ifdef SCALAR
88 Real sum_scalar[NSCALARS];
89 for (double &scalar_i : sum_scalar) {
90 scalar_i = 0.0;
91 }
92#endif // SCALAR
93 if (lambda_m >= 0) {
94 Real lamdiff = lambda_p - lambda_m;
95
96 sum_0 += lamdiff * (-cell_i.density * del_m.velocity.x() / (2 * sound_speed) +
97 del_m.pressure / (2 * sound_speed * sound_speed));
98 sum_1 += lamdiff * (del_m.velocity.x() / 2.0 - del_m.pressure / (2 * sound_speed * cell_i.density));
99 sum_4 += lamdiff * (-cell_i.density * del_m.velocity.x() * sound_speed / 2.0 + del_m.pressure / 2.0);
100 }
101 if (lambda_0 >= 0) {
102 Real lamdiff = lambda_p - lambda_0;
103
104 sum_0 += lamdiff * (del_m.density - del_m.pressure / (sound_speed * sound_speed));
105 sum_2 += lamdiff * del_m.velocity.y();
106 sum_3 += lamdiff * del_m.velocity.z();
107#ifdef DE
108 sum_ge += lamdiff * del_m.gas_energy;
109#endif // DE
110#ifdef SCALAR
111 for (int i = 0; i < NSCALARS; i++) {
112 sum_scalar[i] += lamdiff * del_m.scalar[i];
113 }
114#endif // SCALAR
115 }
116 if (lambda_p >= 0) {
117 Real lamdiff = lambda_p - lambda_p;
118
119 sum_0 += lamdiff * (cell_i.density * del_m.velocity.x() / (2 * sound_speed) +
120 del_m.pressure / (2 * sound_speed * sound_speed));
121 sum_1 += lamdiff * (del_m.velocity.x() / 2.0 + del_m.pressure / (2 * sound_speed * cell_i.density));
122 sum_4 += lamdiff * (cell_i.density * del_m.velocity.x() * sound_speed / 2.0 + del_m.pressure / 2.0);
123 }
124
125 // add the corrections to the initial guesses for the interface values
126 interface_L_iph.density += 0.5 * dtodx * sum_0;
127 interface_L_iph.velocity.x() += 0.5 * dtodx * sum_1;
128 interface_L_iph.velocity.y() += 0.5 * dtodx * sum_2;
129 interface_L_iph.velocity.z() += 0.5 * dtodx * sum_3;
130 interface_L_iph.pressure += 0.5 * dtodx * sum_4;
131#ifdef DE
132 interface_L_iph.gas_energy += 0.5 * dtodx * sum_ge;
133#endif // DE
134#ifdef SCALAR
135 for (int i = 0; i < NSCALARS; i++) {
136 interface_L_iph.scalar[i] += 0.5 * dtodx * sum_scalar[i];
137 }
138#endif // SCALAR
139
140 // right-hand interface value, i-1/2
141 sum_0 = sum_1 = sum_2 = sum_3 = sum_4 = 0;
142#ifdef DE
143 sum_ge = 0;
144#endif // DE
145#ifdef SCALAR
146 for (double &scalar_i : sum_scalar) {
147 scalar_i = 0.0;
148 }
149#endif // SCALAR
150 if (lambda_m <= 0) {
151 Real lamdiff = lambda_m - lambda_m;
152
153 sum_0 += lamdiff * (-cell_i.density * del_m.velocity.x() / (2 * sound_speed) +
154 del_m.pressure / (2 * sound_speed * sound_speed));
155 sum_1 += lamdiff * (del_m.velocity.x() / 2.0 - del_m.pressure / (2 * sound_speed * cell_i.density));
156 sum_4 += lamdiff * (-cell_i.density * del_m.velocity.x() * sound_speed / 2.0 + del_m.pressure / 2.0);
157 }
158 if (lambda_0 <= 0) {
159 Real lamdiff = lambda_m - lambda_0;
160
161 sum_0 += lamdiff * (del_m.density - del_m.pressure / (sound_speed * sound_speed));
162 sum_2 += lamdiff * del_m.velocity.y();
163 sum_3 += lamdiff * del_m.velocity.z();
164#ifdef DE
165 sum_ge += lamdiff * del_m.gas_energy;
166#endif // DE
167#ifdef SCALAR
168 for (int i = 0; i < NSCALARS; i++) {
169 sum_scalar[i] += lamdiff * del_m.scalar[i];
170 }
171#endif // SCALAR
172 }
173 if (lambda_p <= 0) {
174 Real lamdiff = lambda_m - lambda_p;
175
176 sum_0 += lamdiff * (cell_i.density * del_m.velocity.x() / (2 * sound_speed) +
177 del_m.pressure / (2 * sound_speed * sound_speed));
178 sum_1 += lamdiff * (del_m.velocity.x() / 2.0 + del_m.pressure / (2 * sound_speed * cell_i.density));
179 sum_4 += lamdiff * (cell_i.density * del_m.velocity.x() * sound_speed / 2.0 + del_m.pressure / 2.0);
180 }
181
182 // add the corrections
183 interface_R_imh.density += 0.5 * dtodx * sum_0;
184 interface_R_imh.velocity.x() += 0.5 * dtodx * sum_1;
185 interface_R_imh.velocity.y() += 0.5 * dtodx * sum_2;
186 interface_R_imh.velocity.z() += 0.5 * dtodx * sum_3;
187 interface_R_imh.pressure += 0.5 * dtodx * sum_4;
188#ifdef DE
189 interface_R_imh.gas_energy += 0.5 * dtodx * sum_ge;
190#endif // DE
191#ifdef SCALAR
192 for (int i = 0; i < NSCALARS; i++) {
193 interface_R_imh.scalar[i] += 0.5 * dtodx * sum_scalar[i];
194 }
195#endif // SCALAR
196}
197
215template <uint direction>
216auto __device__ __inline__ PLM_Reconstruction(Real *dev_conserved, int const xid, int const yid, int const zid,
217 int const nx, int const ny, int const nz, Real const dx, Real const dt,
218 Real const gamma)
219{
220 // Compute the total number of cells
221 int const n_cells = nx * ny * nz;
222
223 // load the 3-cell stencil into registers
224 // cell i
225 hydro_utilities::Primitive const cell_i =
226 hydro_utilities::Load_Cell_Primitive<direction>(dev_conserved, xid, yid, zid, nx, ny, n_cells, gamma);
227
228 // cell i-1. The equality checks the direction and will subtract one from the correct direction
229 hydro_utilities::Primitive const cell_imo = hydro_utilities::Load_Cell_Primitive<direction>(
230 dev_conserved, xid - int(direction == 0), yid - int(direction == 1), zid - int(direction == 2), nx, ny, n_cells,
231 gamma);
232
233 // cell i+1. The equality checks the direction and add one to the correct direction
234 hydro_utilities::Primitive const cell_ipo = hydro_utilities::Load_Cell_Primitive<direction>(
235 dev_conserved, xid + int(direction == 0), yid + int(direction == 1), zid + int(direction == 2), nx, ny, n_cells,
236 gamma);
237
238 // Compute the left, right, centered, and van Leer differences of the primitive variables Note that here L and R refer
239 // to locations relative to the cell center
240
241 // left
242 hydro_utilities::Primitive const del_L = reconstruction::Compute_Slope(cell_imo, cell_i);
243
244 // right
245 hydro_utilities::Primitive const del_R = reconstruction::Compute_Slope(cell_i, cell_ipo);
246
247 // centered
248 hydro_utilities::Primitive const del_C = reconstruction::Compute_Slope(cell_imo, cell_ipo, 0.5);
249
250 // Van Leer
252
253#ifdef PLMC
254 // Compute the eigenvectors
255 reconstruction::EigenVecs const eigenvectors = reconstruction::Compute_Eigenvectors(cell_i, gamma);
256
257 // Project the left, right, centered and van Leer differences onto the
258 // characteristic variables Stone Eqn 37 (del_a are differences in
259 // characteristic variables, see Stone for notation) Use the eigenvectors
260 // given in Stone 2008, Appendix A
261 reconstruction::Characteristic const del_a_L =
262 reconstruction::Primitive_To_Characteristic(cell_i, del_L, eigenvectors, gamma);
263
264 reconstruction::Characteristic const del_a_R =
265 reconstruction::Primitive_To_Characteristic(cell_i, del_R, eigenvectors, gamma);
266
267 reconstruction::Characteristic const del_a_C =
268 reconstruction::Primitive_To_Characteristic(cell_i, del_C, eigenvectors, gamma);
269
270 reconstruction::Characteristic const del_a_G =
271 reconstruction::Primitive_To_Characteristic(cell_i, del_G, eigenvectors, gamma);
272
273 // Apply monotonicity constraints to the differences in the characteristic variables and project the monotonized
274 // difference in the characteristic variables back onto the primitive variables Stone Eqn 39
275 reconstruction::Characteristic const del_a_m = reconstruction::Van_Leer_Limiter(del_a_L, del_a_R, del_a_C, del_a_G);
276
277 // Project back into the primitive variables.
278 hydro_utilities::Primitive del_m = Characteristic_To_Primitive(cell_i, del_a_m, eigenvectors, gamma);
279
280 // Limit the variables that aren't transformed by the characteristic projection
281 #ifdef DE
282 del_m.gas_energy = Van_Leer_Limiter(del_L.gas_energy, del_R.gas_energy, del_C.gas_energy, del_G.gas_energy);
283 #endif // DE
284 #ifdef SCALAR
285 for (int i = 0; i < NSCALARS; i++) {
286 del_m.scalar[i] = Van_Leer_Limiter(del_L.scalar[i], del_R.scalar[i], del_C.scalar[i], del_G.scalar[i]);
287 }
288 #endif // SCALAR
289#else // PLMP
290 hydro_utilities::Primitive const del_m = reconstruction::Van_Leer_Limiter(del_L, del_R, del_C, del_G);
291#endif // PLMC
292
293 // Compute the left and right interface values using the monotonized difference in the primitive variables
294 hydro_utilities::Primitive interface_L_iph = reconstruction::Calc_Interface_Linear(cell_i, del_m, 1.0);
295 hydro_utilities::Primitive interface_R_imh = reconstruction::Calc_Interface_Linear(cell_i, del_m, -1.0);
296
297// Do the characteristic tracing
298#ifndef VL
299 PLM_Characteristic_Evolution(cell_i, del_m, dt, dx, gamma, interface_R_imh, interface_L_iph);
300#endif // VL
301
302 // apply minimum constraints
303 interface_R_imh.density = fmax(interface_R_imh.density, (Real)TINY_NUMBER);
304 interface_L_iph.density = fmax(interface_L_iph.density, (Real)TINY_NUMBER);
305 interface_R_imh.pressure = fmax(interface_R_imh.pressure, (Real)TINY_NUMBER);
306 interface_L_iph.pressure = fmax(interface_L_iph.pressure, (Real)TINY_NUMBER);
307
308 struct LocalReturnStruct {
309 hydro_utilities::Primitive left, right;
310 };
311 return LocalReturnStruct{interface_L_iph, interface_R_imh};
312}
313} // namespace reconstruction
314
315#endif // PLMC_CUDA_H
__host__ __device__ Real Calc_Sound_Speed(Real const &E, Real const &d, Real const &mx, Real const &my, Real const &mz, Real const &gamma)
Compute the sound speed in the cell from conserved variables.
Definition hydro_utilities.h:194
Namespace to contain various utilities for the interface reconstruction kernels.
Definition pcm_cuda.h:23
hydro_utilities::Primitive __device__ __host__ Compute_Van_Leer_Slope(hydro_utilities::Primitive const &left_slope, hydro_utilities::Primitive const &right_slope)
Compute the Van Lear slope from the left and right slopes.
Definition reconstruction_internals.h:326
auto __device__ PLM_Reconstruction(Real *dev_conserved, int const xid, int const yid, int const zid, int const nx, int const ny, int const nz, Real const dx, Real const dt, Real const gamma)
This is the device function that actually does the piecewise linear reconstruction.
Definition plm_cuda.h:216
void __device__ __host__ PLM_Characteristic_Evolution(hydro_utilities::Primitive const &cell_i, hydro_utilities::Primitive const &del_m, Real const dt, Real const dx, Real const gamma, hydro_utilities::Primitive &interface_R_imh, hydro_utilities::Primitive &interface_L_iph)
Perform characteristic tracing/evolution on an interface.
Definition plm_cuda.h:36
hydro_utilities::Primitive __device__ __host__ Compute_Slope(hydro_utilities::Primitive const &left, hydro_utilities::Primitive const &right, Real const &coef=1.0)
Compute a simple slope. Equation is coef * (right - left).
Definition reconstruction_internals.h:287
Characteristic __device__ Primitive_To_Characteristic(hydro_utilities::Primitive const &primitive, hydro_utilities::Primitive const &primitive_slope, EigenVecs const &eigen, Real const &gamma)
Project from the primitive variables slopes to the characteristic variables slopes....
Definition reconstruction_internals.h:445
hydro_utilities::Primitive __device__ __host__ Calc_Interface_Linear(hydro_utilities::Primitive const &primitive, hydro_utilities::Primitive const &slopes, Real const &sign)
Compute the interface state from the slope and cell centered state using linear interpolation.
Definition reconstruction_internals.h:749
Real __device__ __host__ Van_Leer_Limiter(Real const &left, Real const &right, Real const &centered, Real const &van_leer)
Compute the limited slope using the Van Leer limiter.
Definition reconstruction_internals.h:573
EigenVecs __device__ Compute_Eigenvectors(hydro_utilities::Primitive const &primitive, Real const &gamma)
Compute the eigenvectors in the given cell.
Definition reconstruction_internals.h:372
hydro_utilities::Primitive __device__ __host__ Characteristic_To_Primitive(hydro_utilities::Primitive const &primitive, Characteristic const &characteristic_slope, EigenVecs const &eigen, Real const &gamma)
Project from the characteristic variables slopes to the primitive variables slopes....
Definition reconstruction_internals.h:520
__global__ __launch_bounds__(TPB) void PLM_cuda(Real *dev_conserved
Performs second order reconstruction using limiting in the characteristic or primitive variables.
A data only struct for the primitive variables.
Definition basic_structs.h:124
__device__ __host__ T & x() noexcept
Directly access the x, y, and z elements. Const version is needed if the object instance is declared ...
Definition basic_structs.h:68
A struct for the characteristic variables. We use the same notation as Stone et al....
Definition reconstruction_internals.h:84
Definition reconstruction_internals.h:60