9#include "../feedback/feedback.h"
10#include "../feedback/ratecalc.h"
11#include "../feedback/stencil.h"
12#include "../global/global.h"
13#include "../utils/basic_structs.h"
15namespace fb_prescription
18inline __device__
void log_fb(
int cycle_num,
int num_SN,
bool is_resolved, Real pos_x_indU, Real pos_y_indU,
19 Real pos_z_indU, Real vel_x, Real vel_y, Real vel_z, part_int_t particle_id,
20 Real n_0_cgs = -1.23456789)
24 "..fb: { \"cycle\":%d, \"id\": %lld, \"num_SN\": %d, \"resolved\": %d, \"n0\": %g, \"pos_indU\": [%g, %g, %g], "
25 "\"vel\": [%g, %g, %g]}\n",
26 cycle_num, (
long long int)(particle_id), num_SN,
int(is_resolved), n_0_cgs, pos_x_indU, pos_y_indU, pos_z_indU,
37inline __device__ __host__ Real radius_shell_formation_kpc(Real ndens_cgs,
int num_SN)
48 return 0.0226 * pow(ndens_cgs, -0.46) * pow(fabs(Real(num_SN)), 0.29);
51template <
typename Stencil>
54 static constexpr bool has_resolved_prescription =
true;
55 static constexpr bool has_unresolved_prescription =
false;
60 return Stencil::nearest_noGhostOverlap_pos(pos_indU, ng_x, ng_y, ng_z, n_ghost);
64 template <
typename Function>
65 static __device__
void for_each_possible_overlap(Real pos_x_indU, Real pos_y_indU, Real pos_z_indU,
int nx_g,
66 int ny_g, Function&& f)
69 std::forward<Function>(f));
72 static __device__
void apply_feedback(Real pos_x_indU, Real pos_y_indU, Real pos_z_indU, Real vel_x, Real vel_y,
73 Real vel_z, Real age, Real& mass_ref, part_int_t particle_id, Real dx, Real dy,
74 Real dz,
int nx_g,
int ny_g,
int nz_g,
int n_ghost,
int num_SN,
int cycle_num,
75 Real* s_info, Real* conserved_dev)
77 int tid = threadIdx.x;
79 s_info[FBInfoLUT::LEN * tid + FBInfoLUT::countSN] += num_SN;
80 s_info[FBInfoLUT::LEN * tid + FBInfoLUT::countResolved] += num_SN;
81 s_info[FBInfoLUT::LEN * tid + FBInfoLUT::totalEnergy] += feedback::ENERGY_PER_SN;
83 Real dV = dx * dy * dz;
84 Real feedback_energy = num_SN * feedback::ENERGY_PER_SN / dV;
85 Real feedback_density = num_SN * feedback::MASS_PER_SN / dV;
87 mass_ref = max(0.0, mass_ref - num_SN * feedback::MASS_PER_SN);
89 log_fb(cycle_num, num_SN,
true, pos_x_indU, pos_y_indU, pos_z_indU, vel_x, vel_y, vel_z, particle_id);
92 vel_z, nx_g, ny_g, nx_g * ny_g * nz_g, conserved_dev, feedback_density,
98 int ny_g,
int n_cells, Real* conserved_device, Real feedback_density,
101 Real* density = conserved_device;
102 Real* momentum_x = &conserved_device[n_cells * grid_enum::momentum_x];
103 Real* momentum_y = &conserved_device[n_cells * grid_enum::momentum_y];
104 Real* momentum_z = &conserved_device[n_cells * grid_enum::momentum_z];
105 Real* energy = &conserved_device[n_cells * grid_enum::Energy];
107 Real* gasEnergy = &conserved_device[n_cells * grid_enum::GasEnergy];
110 Stencil::for_each(pos_indU, nx_g, ny_g, [=](
double stencil_vol_frac,
int idx3D) {
119 Real intial_ke_density = 0.5 *
120 (momentum_x[idx3D] * momentum_x[idx3D] + momentum_y[idx3D] * momentum_y[idx3D] +
121 momentum_z[idx3D] * momentum_z[idx3D]) /
124 energy[idx3D] -= intial_ke_density;
130 double injected_density = stencil_vol_frac * feedback_density;
132 momentum_x[idx3D] += vel_x * injected_density;
133 momentum_y[idx3D] += vel_y * injected_density;
134 momentum_z[idx3D] += vel_z * injected_density;
137 density[idx3D] += injected_density;
141 gasEnergy[idx3D] += stencil_vol_frac * feedback_energy;
143 energy[idx3D] += stencil_vol_frac * feedback_energy;
146 energy[idx3D] += 0.5 *
147 (momentum_x[idx3D] * momentum_x[idx3D] + momentum_y[idx3D] * momentum_y[idx3D] +
148 momentum_z[idx3D] * momentum_z[idx3D]) /
187template <
typename Stencil>
189 Real* conserved_device, Real overwrite_density)
194 const int n_cells = nx_g * ny_g * nz_g;
195 Real* density = conserved_device;
196 Real* momentum_x = &conserved_device[n_cells * grid_enum::momentum_x];
197 Real* momentum_y = &conserved_device[n_cells * grid_enum::momentum_y];
198 Real* momentum_z = &conserved_device[n_cells * grid_enum::momentum_z];
199 Real* energy = &conserved_device[n_cells * grid_enum::Energy];
206 Real tot_momentum[3] = {0.0, 0.0, 0.0};
208 Stencil::for_each_overlap_zone(stencil_pos_indU, nx_g, ny_g, [&](
int idx3D) {
209 tot_momentum[0] += momentum_x[idx3D];
210 tot_momentum[1] += momentum_y[idx3D];
211 tot_momentum[2] += momentum_z[idx3D];
219 const Real new_ke_density =
221 (avg_momentum[0] * avg_momentum[0] + avg_momentum[1] * avg_momentum[1] + avg_momentum[2] * avg_momentum[2]) /
223 Stencil::for_each_overlap_zone(stencil_pos_indU, nx_g, ny_g, [=](
int idx3D) {
225 const Real inv_initial_dens = 1.0 / (density[idx3D] + TINY_NUMBER * (density[idx3D] == 0.0));
226 const Real intial_ke_density = 0.5 * inv_initial_dens *
227 (momentum_x[idx3D] * momentum_x[idx3D] + momentum_y[idx3D] * momentum_y[idx3D] +
228 momentum_z[idx3D] * momentum_z[idx3D]);
229 density[idx3D] = overwrite_density;
230 momentum_x[idx3D] = avg_momentum[0];
231 momentum_y[idx3D] = avg_momentum[1];
232 momentum_z[idx3D] = avg_momentum[2];
233 energy[idx3D] += new_ke_density - intial_ke_density;
250template <
typename Stencil>
251inline __device__
void Apply_Energy_Momentum_Deposition(Real pos_x_indU, Real pos_y_indU, Real pos_z_indU, Real vel_x,
252 Real vel_y, Real vel_z,
int nx_g,
int ny_g,
int n_ghost,
253 int n_cells, Real* conserved_device, Real feedback_density,
254 Real feedback_momentum, Real feedback_energy)
256 Real* density = conserved_device;
257 Real* momentum_x = &conserved_device[n_cells * grid_enum::momentum_x];
258 Real* momentum_y = &conserved_device[n_cells * grid_enum::momentum_y];
259 Real* momentum_z = &conserved_device[n_cells * grid_enum::momentum_z];
260 Real* energy = &conserved_device[n_cells * grid_enum::Energy];
262 Real* gas_energy = &conserved_device[n_cells * grid_enum::GasEnergy];
265 Stencil::for_each_vecflavor(
266 {pos_x_indU, pos_y_indU, pos_z_indU}, nx_g, ny_g,
269 const Real inv_initial_density = 1.0 / (density[idx3D] + TINY_NUMBER * (density[idx3D] == 0.0));
275 const Real intial_ke_density = 0.5 * inv_initial_density *
276 (momentum_x[idx3D] * momentum_x[idx3D] + momentum_y[idx3D] * momentum_y[idx3D] +
277 momentum_z[idx3D] * momentum_z[idx3D]);
278 energy[idx3D] -= intial_ke_density;
287 Real gas_vx = inv_initial_density * momentum_x[idx3D];
288 Real gas_vy = inv_initial_density * momentum_y[idx3D];
289 Real gas_vz = inv_initial_density * momentum_z[idx3D];
297 momentum_x[idx3D] = density[idx3D] * gas_vx;
298 momentum_y[idx3D] = density[idx3D] * gas_vy;
299 momentum_z[idx3D] = density[idx3D] * gas_vz;
303 density[idx3D] += scalar_weight * feedback_density;
304 momentum_x[idx3D] += momentum_weights[0] * feedback_momentum;
305 momentum_y[idx3D] += momentum_weights[1] * feedback_momentum;
306 momentum_z[idx3D] += momentum_weights[2] * feedback_momentum;
312 energy[idx3D] += scalar_weight * feedback_energy;
314 gas_energy[idx3D] += scalar_weight * feedback_energy;
318 const Real inv_final_density = 1.0 / (density[idx3D] + TINY_NUMBER * (density[idx3D] == 0.0));
324 Real gas_vx = inv_final_density * momentum_x[idx3D];
325 Real gas_vy = inv_final_density * momentum_y[idx3D];
326 Real gas_vz = inv_final_density * momentum_z[idx3D];
334 momentum_x[idx3D] = density[idx3D] * gas_vx;
335 momentum_y[idx3D] = density[idx3D] * gas_vy;
336 momentum_z[idx3D] = density[idx3D] * gas_vz;
342 energy[idx3D] += 0.5 * inv_final_density *
343 (momentum_x[idx3D] * momentum_x[idx3D] + momentum_y[idx3D] * momentum_y[idx3D] +
344 momentum_z[idx3D] * momentum_z[idx3D]);
349template <
typename ResolvedPrescriptionT,
typename UnresolvedStencil>
352 static constexpr bool has_resolved_prescription =
true;
353 static constexpr bool has_unresolved_prescription =
true;
360 return UnresolvedStencil::nearest_noGhostOverlap_pos(pos_indU, ng_x, ng_y, ng_z, n_ghost);
364 template <
typename Function>
365 static __device__
void for_each_possible_overlap(Real pos_x_indU, Real pos_y_indU, Real pos_z_indU,
int nx_g,
366 int ny_g, Function&& f)
369 std::forward<Function>(f));
372 static __device__
void apply_feedback(Real pos_x_indU, Real pos_y_indU, Real pos_z_indU, Real vel_x, Real vel_y,
373 Real vel_z, Real age, Real& mass_ref, part_int_t particle_id, Real dx, Real dy,
374 Real dz,
int nx_g,
int ny_g,
int nz_g,
int n_ghost,
int num_SN,
int cycle_num,
375 Real* s_info, Real* conserved_dev)
377 int tid = threadIdx.x;
379 Real dV = dx * dy * dz;
380 int n_cells = nx_g * ny_g * nz_g;
384 Real* density = conserved_dev;
391 UnresolvedStencil::for_each_overlap_zone(pos_indU, nx_g, ny_g, [&dtot, &num, density](
int idx3) {
392 dtot += density[idx3];
395 avg_mass_dens = dtot / num;
397 Real n_0_cgs = avg_mass_dens * DENSITY_UNIT / (MU * MP);
399 s_info[FBInfoLUT::LEN * tid + FBInfoLUT::countSN] += num_SN;
401 Real shell_radius = radius_shell_formation_kpc(n_0_cgs, num_SN);
403 const bool is_resolved = (3 * max(dx, max(dy, dz)) <= shell_radius);
405 mass_ref = max(0.0, mass_ref - num_SN * feedback::MASS_PER_SN);
406 Real feedback_density = num_SN * feedback::MASS_PER_SN / dV;
408 log_fb(cycle_num, num_SN, is_resolved, pos_x_indU, pos_y_indU, pos_z_indU, vel_x, vel_y, vel_z, particle_id,
413 Real feedback_energy = num_SN * feedback::ENERGY_PER_SN / dV;
415 s_info[FBInfoLUT::LEN * tid + FBInfoLUT::countResolved] += num_SN;
416 s_info[FBInfoLUT::LEN * tid + FBInfoLUT::totalEnergy] += feedback_energy * dV;
418 ResolvedPrescriptionT::apply(pos_indU, vel_x, vel_y, vel_z, nx_g, ny_g, n_cells, conserved_dev, feedback_density,
424 Overwrite_Average<UnresolvedStencil>(pos_indU, nx_g, ny_g, nz_g, conserved_dev, avg_mass_dens);
445 Real feedback_momentum = feedback::FINAL_MOMENTUM * pow(n_0_cgs, -0.17) * pow(Real(num_SN), 0.93);
446 Real feedback_momentum_density = feedback_momentum / dV;
447 Real feedback_energy = 0.0;
449 s_info[FBInfoLUT::LEN * tid + FBInfoLUT::countUnresolved] += num_SN;
450 s_info[FBInfoLUT::LEN * tid + FBInfoLUT::totalMomentum] += feedback_momentum;
451 s_info[FBInfoLUT::LEN * tid + FBInfoLUT::totalUnresEnergy] += feedback_energy * dV;
452 Apply_Energy_Momentum_Deposition<UnresolvedStencil>(pos_x_indU, pos_y_indU, pos_z_indU, vel_x, vel_y, vel_z, nx_g,
453 ny_g, n_ghost, n_cells, conserved_dev, feedback_density,
454 feedback_momentum_density, feedback_energy);
Definition prescription.h:350
Definition prescription.h:52
A data only struct that acts as a simple 3 element vector.
Definition basic_structs.h:32