Cholla 3.0.1-dev
Cholla - Massively parallel hydro on GPUs
Loading...
Searching...
No Matches
hydro_utilities.h
Go to the documentation of this file.
1
8#pragma once
9
10#include <iostream>
11#include <string>
12
13// Local Includes
14#include "../global/global.h"
15#include "../global/global_cuda.h"
16#include "../utils/basic_structs.h"
17#include "../utils/gpu.hpp"
18#include "../utils/math_utilities.h"
19#include "../utils/mhd_utilities.h"
20
32namespace hydro_utilities
33{
34inline __host__ __device__ Real Calc_Pressure_Primitive(Real const &E, Real const &d, Real const &vx, Real const &vy,
35 Real const &vz, Real const &gamma, Real const &magnetic_x = 0.0,
36 Real const &magnetic_y = 0.0, Real const &magnetic_z = 0.0)
37{
38 Real pressure = E - 0.5 * d * math_utils::SquareMagnitude(vx, vy, vz);
39
40#ifdef MHD
41 pressure -= mhd::utils::computeMagneticEnergy(magnetic_x, magnetic_y, magnetic_z);
42#endif // MHD
43
44 return fmax((gamma - 1.) * pressure, TINY_NUMBER);
45}
46
47inline __host__ __device__ Real Calc_Pressure_Conserved(Real const &E, Real const &d, Real const &mx, Real const &my,
48 Real const &mz, Real const &gamma, Real const &magnetic_x = 0.0,
49 Real const &magnetic_y = 0.0, Real const &magnetic_z = 0.0)
50{
51 Real pressure = E - 0.5 * math_utils::SquareMagnitude(mx, my, mz) / d;
52
53#ifdef MHD
54 pressure -= mhd::utils::computeMagneticEnergy(magnetic_x, magnetic_y, magnetic_z);
55#endif // MHD
56
57 return fmax((gamma - 1.) * pressure, TINY_NUMBER);
58}
59
60inline __host__ __device__ Real Calc_Temp(Real const &P, Real const &n)
61{
62 Real T = P * PRESSURE_UNIT / (n * KB);
63 return T;
64}
65
81inline __host__ __device__ Real Calc_Temp_Conserved(Real const E, Real const d, Real const mx, Real const my,
82 Real const mz, Real const gamma, Real const n,
83 Real const magnetic_x = 0.0, Real const magnetic_y = 0.0,
84 Real const magnetic_z = 0.0)
85{
86 Real const P = Calc_Pressure_Conserved(E, d, mx, my, mz, gamma, magnetic_x, magnetic_y, magnetic_z);
87 return Calc_Temp(P, n);
88}
89
90#ifdef DE
100inline __host__ __device__ Real Calc_Temp_DE(Real const gas_energy, Real const gamma, Real const n)
101{
102 return gas_energy * (gamma - 1.0) * PRESSURE_UNIT / (n * KB);
103}
104#endif // DE
105
106inline __host__ __device__ Real Calc_Energy_Primitive(Real const &P, Real const &d, Real const &vx, Real const &vy,
107 Real const &vz, Real const &gamma, Real const &magnetic_x = 0.0,
108 Real const &magnetic_y = 0.0, Real const &magnetic_z = 0.0)
109{
110 // Compute and return energy
111 Real energy = (fmax(P, TINY_NUMBER) / (gamma - 1.)) + 0.5 * d * math_utils::SquareMagnitude(vx, vy, vz);
112
113#ifdef MHD
114 energy += mhd::utils::computeMagneticEnergy(magnetic_x, magnetic_y, magnetic_z);
115#endif // MHD
116
117 return energy;
118}
119
120inline __host__ __device__ Real Calc_Energy_Conserved(Real const &P, Real const &d, Real const &momentum_x,
121 Real const &momentum_y, Real const &momentum_z, Real const &gamma,
122 Real const &magnetic_x = 0.0, Real const &magnetic_y = 0.0,
123 Real const &magnetic_z = 0.0)
124{
125 // Compute and return energy
126 Real energy = (fmax(P, TINY_NUMBER) / (gamma - 1.)) +
127 (0.5 / d) * math_utils::SquareMagnitude(momentum_x, momentum_y, momentum_z);
128
129#ifdef MHD
130 energy += mhd::utils::computeMagneticEnergy(magnetic_x, magnetic_y, magnetic_z);
131#endif // MHD
132
133 return energy;
134}
135
136inline __host__ __device__ Real Get_Pressure_From_DE(Real const &E, Real const &U_total, Real const &U_advected,
137 Real const &gamma)
138{
139 Real U, P;
140 Real eta = DE_ETA_1;
141 // Apply same condition as Byan+2013 to select the internal energy from which
142 // compute pressure.
143 if (U_total / E > eta) {
144 U = U_total;
145 } else {
146 U = U_advected;
147 }
148 P = U * (gamma - 1.0);
149 return fmax(P, (Real)TINY_NUMBER);
150 ;
151}
152
162inline __host__ __device__ Real Calc_Kinetic_Energy_From_Velocity(Real const &d, Real const &vx, Real const &vy,
163 Real const &vz)
164{
165 return 0.5 * d * math_utils::SquareMagnitude(vx, vy, vz);
166}
167
177inline __host__ __device__ Real Calc_Kinetic_Energy_From_Momentum(Real const &d, Real const &mx, Real const &my,
178 Real const &mz)
179{
180 return (0.5 / d) * math_utils::SquareMagnitude(mx, my, mz);
181}
182
194inline __host__ __device__ Real Calc_Sound_Speed(Real const &E, Real const &d, Real const &mx, Real const &my,
195 Real const &mz, Real const &gamma)
196{
197 Real P = Calc_Pressure_Conserved(E, d, mx, my, mz, gamma);
198 return sqrt(gamma * P / d);
199}
200
209inline __host__ __device__ Real Calc_Sound_Speed(Real const &P, Real const &d, Real const &gamma)
210{
211 return sqrt(gamma * P / d);
212}
213
214// =====================================================================================================================
232template <uint dir = 0>
233inline __host__ __device__ Conserved Load_Cell_Conserved(Real const *dev_conserved, size_t const xid, size_t const yid,
234 size_t const zid, size_t const nx, size_t const ny,
235 size_t const n_cells)
236{
237 // First, check that our direction is correct
238 static_assert((0 <= dir) and (dir <= 2), "dir is not in the proper range");
239
240 // Compute index
241 size_t const cell_id = cuda_utilities::compute1DIndex(xid, yid, zid, nx, ny);
242
243 // Load all the data
244 Conserved loaded_data;
245
246 // Hydro variables
247 loaded_data.density = dev_conserved[cell_id + n_cells * grid_enum::density];
248 loaded_data.momentum.x() = dev_conserved[cell_id + n_cells * grid_enum::momentum_x];
249 loaded_data.momentum.y() = dev_conserved[cell_id + n_cells * grid_enum::momentum_y];
250 loaded_data.momentum.z() = dev_conserved[cell_id + n_cells * grid_enum::momentum_z];
251 loaded_data.energy = dev_conserved[cell_id + n_cells * grid_enum::Energy];
252
253#ifdef MHD
254 // These are all cell centered values
255 loaded_data.magnetic = mhd::utils::cellCenteredMagneticFields(dev_conserved, cell_id, xid, yid, zid, n_cells, nx, ny);
256#endif // MHD
257
258#ifdef DE
259 loaded_data.gas_energy = dev_conserved[cell_id + n_cells * grid_enum::GasEnergy];
260#endif // DE
261
262#ifdef SCALAR
263 for (size_t i = 0; i < grid_enum::nscalars; i++) {
264 loaded_data.scalar[i] = dev_conserved[cell_id + n_cells * (grid_enum::scalar + i)];
265 }
266#endif // SCALAR
267
268 // Now that all the data is loaded, let's sort out the direction
269 // if constexpr(dir == 0) in this case everything is already set so we'll skip this case
270 if constexpr (dir == 1) {
271 math_utils::Cyclic_Permute_Once(loaded_data.momentum);
272#ifdef MHD
273 math_utils::Cyclic_Permute_Once(loaded_data.magnetic);
274#endif // MHD
275 } else if constexpr (dir == 2) {
276 math_utils::Cyclic_Permute_Twice(loaded_data.momentum);
277#ifdef MHD
278 math_utils::Cyclic_Permute_Twice(loaded_data.magnetic);
279#endif // MHD
280 }
281
282 return loaded_data;
283}
284// =====================================================================================================================
285
286// =====================================================================================================================
294__inline__ __host__ __device__ Primitive Conserved_2_Primitive(Conserved const &conserved_in, Real const gamma)
295{
296 Primitive output;
297
298 // First the easy ones
299 output.density = conserved_in.density;
300 output.velocity.x() = conserved_in.momentum.x() / conserved_in.density;
301 output.velocity.y() = conserved_in.momentum.y() / conserved_in.density;
302 output.velocity.z() = conserved_in.momentum.z() / conserved_in.density;
303
304#ifdef MHD
305 output.magnetic.x() = conserved_in.magnetic.x();
306 output.magnetic.y() = conserved_in.magnetic.y();
307 output.magnetic.z() = conserved_in.magnetic.z();
308#endif // MHD
309
310#ifdef DE
311 output.gas_energy = conserved_in.gas_energy / conserved_in.density;
312#endif // DE
313
314#ifdef SCALAR
315 for (size_t i = 0; i < grid_enum::nscalars; i++) {
316 output.scalar[i] = conserved_in.scalar[i] / conserved_in.density;
317 }
318#endif // SCALAR
319
320// Now that the easy ones are done let's figure out the pressure
321#ifdef DE // DE
322 Real E_non_thermal = hydro_utilities::Calc_Kinetic_Energy_From_Velocity(output.density, output.velocity.x(),
323 output.velocity.y(), output.velocity.z());
324
325 #ifdef MHD
326 E_non_thermal += mhd::utils::computeMagneticEnergy(output.magnetic.x(), output.magnetic.y(), output.magnetic.z());
327 #endif // MHD
328
329 output.pressure = hydro_utilities::Get_Pressure_From_DE(conserved_in.energy, conserved_in.energy - E_non_thermal,
330 conserved_in.gas_energy, gamma);
331#else // not DE
332 #ifdef MHD
333 output.pressure = hydro_utilities::Calc_Pressure_Primitive(
334 conserved_in.energy, conserved_in.density, output.velocity.x(), output.velocity.y(), output.velocity.z(), gamma,
335 output.magnetic.x(), output.magnetic.y(), output.magnetic.z());
336 #else // not MHD
337 output.pressure = hydro_utilities::Calc_Pressure_Primitive(
338 conserved_in.energy, conserved_in.density, output.velocity.x(), output.velocity.y(), output.velocity.z(), gamma);
339 #endif // MHD
340#endif // DE
341
342 return output;
343}
344// =====================================================================================================================
345
346// =====================================================================================================================
354__inline__ __host__ __device__ Conserved Primitive_2_Conserved(Primitive const &primitive_in, Real const gamma)
355{
356 Conserved output;
357
358 // First the easy ones
359 output.density = primitive_in.density;
360 output.momentum.x() = primitive_in.velocity.x() * primitive_in.density;
361 output.momentum.y() = primitive_in.velocity.y() * primitive_in.density;
362 output.momentum.z() = primitive_in.velocity.z() * primitive_in.density;
363
364#ifdef MHD
365 output.magnetic.x() = primitive_in.magnetic.x();
366 output.magnetic.y() = primitive_in.magnetic.y();
367 output.magnetic.z() = primitive_in.magnetic.z();
368#endif // MHD
369
370#ifdef DE
371 output.gas_energy = primitive_in.gas_energy * primitive_in.density;
372#endif // DE
373
374#ifdef SCALAR
375 for (size_t i = 0; i < grid_enum::nscalars; i++) {
376 output.scalar[i] = primitive_in.scalar[i] * primitive_in.density;
377 }
378#endif // SCALAR
379
380// Now that the easy ones are done let's figure out the energy
381#ifdef MHD
382 output.energy = hydro_utilities::Calc_Energy_Primitive(primitive_in.pressure, primitive_in.density,
383 primitive_in.velocity.x(), primitive_in.velocity.y(),
384 primitive_in.velocity.z(), gamma, primitive_in.magnetic.x(),
385 primitive_in.magnetic.y(), primitive_in.magnetic.z());
386#else // not MHD
387 output.energy =
388 hydro_utilities::Calc_Energy_Primitive(primitive_in.pressure, primitive_in.density, primitive_in.velocity.x(),
389 primitive_in.velocity.y(), primitive_in.velocity.z(), gamma);
390#endif // MHD
391
392 return output;
393}
394// =====================================================================================================================
395
396// =====================================================================================================================
415template <uint dir = 0>
416inline __host__ __device__ Primitive Load_Cell_Primitive(Real const *dev_conserved, size_t const xid, size_t const yid,
417 size_t const zid, size_t const nx, size_t const ny,
418 size_t const n_cells, Real const gamma)
419{
420 Conserved const conserved_cell = Load_Cell_Conserved<dir>(dev_conserved, xid, yid, zid, nx, ny, n_cells);
421 return Conserved_2_Primitive(conserved_cell, gamma);
422}
423// =====================================================================================================================
424
425} // namespace hydro_utilities
__device__ __host__ Real SquareMagnitude(Real const &v1, Real const &v2, Real const &v3)
Compute the magnitude of a vector.
Definition math_utilities.h:96
__host__ __device__ Real computeMagneticEnergy(Real const &magneticX, Real const &magneticY, Real const &magneticZ)
Compute the magnetic energy.
Definition mhd_utilities.h:76
Definition basic_structs.h:15
__host__ __device__ Primitive Conserved_2_Primitive(Conserved const &conserved_in, Real const gamma)
Convert Conserved cell centered variables to primitive variables.
Definition hydro_utilities.h:294
__host__ __device__ Conserved Primitive_2_Conserved(Primitive const &primitive_in, Real const gamma)
Convert primitive cell centered variables to conserved variables.
Definition hydro_utilities.h:354
__host__ __device__ Real Calc_Temp_Conserved(Real const E, Real const d, Real const mx, Real const my, Real const mz, Real const gamma, Real const n, Real const magnetic_x=0.0, Real const magnetic_y=0.0, Real const magnetic_z=0.0)
Compute the temperature from the conserved variables.
Definition hydro_utilities.h:81
__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
__host__ __device__ Primitive Load_Cell_Primitive(Real const *dev_conserved, size_t const xid, size_t const yid, size_t const zid, size_t const nx, size_t const ny, size_t const n_cells, Real const gamma)
Load the primitive variables from a single cell. Note that with MHD this returns cell-centered magnet...
Definition hydro_utilities.h:416
__host__ __device__ Real Calc_Kinetic_Energy_From_Momentum(Real const &d, Real const &mx, Real const &my, Real const &mz)
Compute the kinetic energy from the density and momenta.
Definition hydro_utilities.h:177
__host__ __device__ Real Calc_Kinetic_Energy_From_Velocity(Real const &d, Real const &vx, Real const &vy, Real const &vz)
Compute the kinetic energy from the density and velocities.
Definition hydro_utilities.h:162
__host__ __device__ Conserved Load_Cell_Conserved(Real const *dev_conserved, size_t const xid, size_t const yid, size_t const zid, size_t const nx, size_t const ny, size_t const n_cells)
Load the conserved variables from a single cell. Note that with MHD this returns cell-centered magnet...
Definition hydro_utilities.h:233
A data only struct for the conserved variables.
Definition basic_structs.h:83
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