Cholla 3.0.1-dev
Cholla - Massively parallel hydro on GPUs
Loading...
Searching...
No Matches
disk_galaxy.h
1#ifndef DISK_GALAXY
2#define DISK_GALAXY
3
4#include <cmath>
5#include <iostream>
6#include <memory>
7#include <random>
8
9#include "../../global/global.h"
10#include "../../utils/error_handling.h"
11
12// we are bending over backwards to ensure that the functionality defined in
13// "potentials.h" can be used on CPUs and on GPUs
14// -> previously, this functionality was simply duplicated in a number of places
15// and this created some headaches
16// -> we can't simply include the "potentials.h" header here since that would
17// produce problems for any source file that includes this header and makes
18// use of a regular c++ compiler
19// -> we instead forward declare the relevant classes/structs from "potentials.h"
20// and store pointers to these classes within DiskGalaxy (without including
21// the full definitions of these classes in this header, we can't directly
22// include them in this file)
23// -> this means that DiskGalaxy's methods that forward onto the methods of these
24// other classes will be a little slower. In files compiled with a CUDA/HIP
25// compiler, this slowdown can be avoided by including the "potentials.h"
26// header and using DiskGalaxy's accessor methods to directly access the
27// underlying objects.
28struct NFWHaloPotential;
30struct GasDiskProps;
31
32/* Intended to serve as a centralized location where all properties of the underlying galaxy-model
33 * are agregated.
34 *
35 * This object also defines some methods for computing an analytic gravitational potential. At this
36 * time, that gravitational potential is only for the stellar disk and the background halo.
37 */
39{
40 private:
41 // we store pointers to stellar_disk, gas_disk, and halo_potential purely to
42 // sidestep some compilation issues with non-CUDA/HIP source files including
43 // this file (this is described in greater depth up above)
44 std::shared_ptr<MiyamotoNagaiPotential> stellar_disk;
45 std::shared_ptr<GasDiskProps> gas_disk;
46 std::shared_ptr<NFWHaloPotential> halo_potential;
47 Real M_vir, R_vir, r_cool;
48
49 public:
50 /* To properly deallocate the internally tracked shared pointers we need to define a
51 * destructor in a source file where the full definitions of the referenced classes
52 * are visible.
53 *
54 * \note
55 * we need to declare this as virtual so code like `delete ptr;`, where `ptr` has
56 * type `DiskGalaxy*`, but references a subclass is executed properly (if the virtual
57 * specifier were missing the code snippet would invoke undefined behavior.
58 */
59 virtual ~DiskGalaxy();
60
61 DiskGalaxy(const MiyamotoNagaiPotential& stellar_disk, const GasDiskProps& gas_disk, Real mvir, Real rvir, Real cvir,
62 Real rcool);
63
64 /* Radial acceleration in miyamoto nagai */
65 Real gr_disk_D3D(Real R, Real z) const noexcept;
66
67 /* Radial acceleration in NFW halo */
68 Real gr_halo_D3D(Real R, Real z) const noexcept;
69
78 Real gr_total_D3D(Real R, Real z) const noexcept { return gr_disk_D3D(R, z) + gr_halo_D3D(R, z); };
79
80 Real gr_total_with_GasSelfGravEstimate(Real R, Real z) const noexcept;
81
82 /* returns the circular velocity of a massless test particle in the static gravitational
83 * potential at the specified (cylindrical radius, z) pair. */
84 Real circular_vel2(Real R, Real z) const noexcept { return R * std::fabs(gr_total_D3D(R, z)); }
85
86 /* returns the circular velocity of a massless test particle in the gravitational
87 * potential (including an estimate for self-gravity) at the specified
88 * (cylindrical radius, z) pair. */
89 Real circular_vel2_with_selfgrav_estimates(Real R, Real z) const noexcept
90 {
91 return R * std::fabs(gr_total_with_GasSelfGravEstimate(R, z));
92 }
93
94 /* Potential of NFW halo */
95 Real phi_halo_D3D(Real R, Real z) const noexcept;
96
97 /* Miyamoto-Nagai potential */
98 Real phi_disk_D3D(Real R, Real z) const noexcept;
99
104 Real phi_total_D3D(Real R, Real z) const noexcept { return phi_halo_D3D(R, z) + phi_disk_D3D(R, z); };
105
109 Real kappa2(Real R, Real z) const;
110
111 // Real sigma_crit(Real R)
112 //{
113 // return 3.36 * GN * stellar_disk.surface_density(R) / sqrt(kappa2(R, 0.0));
114 // };
115
116 Real getM_d() const;
117 Real getR_d() const;
118 Real getZ_d() const;
119 Real getGasDiskR_d() const;
120 const MiyamotoNagaiPotential& getStaticStellarDiskPotential() const;
121 const GasDiskProps& getGasDisk() const;
122 const NFWHaloPotential& getHaloPotential() const;
123 Real getM_vir() const { return M_vir; };
124 Real getR_vir() const { return R_vir; };
125 Real getR_cool() const { return r_cool; };
126};
127
128/* Encapsulates the cluster-mass distribution function
129 *
130 * There is 0 probability of drawing a cluster with mass M < lower_mass or M >= higher_mass.
131 * The probability of drawing a cluster mass M, satisfying lower_mass <= M < higher_mass is given
132 * by a pdf that is proportional to std::pow(M, -1 * alpha);
133 * -> alpha is not allowed to be 1 (that corresponds to the log-uniform distribution)
134 * -> when you have N particles and alpha = 2, then the total mass particles in equal sized
135 * logarithmic mass bins is constant
136 */
138{
139 public: // interface
140 ClusterMassDistribution() = delete;
141
142 ClusterMassDistribution(Real lower_mass, Real higher_mass, Real alpha)
143 : lo_mass_(lower_mass), hi_mass_(higher_mass), alpha_(alpha)
144 {
145 CHOLLA_ASSERT(lower_mass > 0.0, "The minimum cluster-mass must exceed 0");
146 CHOLLA_ASSERT(higher_mass > lower_mass, "The max mass must exceed the min mass");
147 CHOLLA_ASSERT(alpha_ > 1.0, "alpha must exceed 1.0");
148 }
149
150 Real getLowerClusterMass() const { return lo_mass_; }
151 Real getHigherClusterMass() const { return hi_mass_; }
152
153 Real meanClusterMass() const
154 {
155 Real normalization = (1 - alpha_) / (std::pow(hi_mass_, 1 - alpha_) - std::pow(lo_mass_, 1 - alpha_));
156 if (alpha_ == 2.0) {
157 return normalization * std::log(hi_mass_ / lo_mass_);
158 } else {
159 CHOLLA_ERROR("UNTESTED LOGIC");
160 return normalization * (std::pow(hi_mass_, 2 - alpha_) - std::pow(lo_mass_, 2 - alpha_)) / (2 - alpha_);
161 }
162 }
163
164 Real singleClusterMass(std::mt19937_64 generator) const
165 {
166 std::uniform_real_distribution<Real> uniform_distro(0, 1);
167 Real X = uniform_distro(generator);
168 Real mclmin = lo_mass_;
169 Real mclmax = hi_mass_;
170
171 Real tmp = std::pow(mclmin, -alpha_ + 1) - (std::pow(mclmin, -alpha_ + 1) - std::pow(mclmax, -alpha_ + 1)) * X;
172 return std::pow(tmp, 1.0 / (-alpha_ + 1));
173 }
174
175 private: // attributes
176 Real lo_mass_;
177 Real hi_mass_;
178 Real alpha_;
179};
180
181// TODO: consider doing away with the ClusteredDiskGalaxy class and instead storing
182// cluster_mass_distribution_ as an optional attribute of DiskGalaxy
184{
185 private:
186 ClusterMassDistribution cluster_mass_distribution_;
187
188 public:
189 ClusteredDiskGalaxy(ClusterMassDistribution cluster_mass_distribution, const MiyamotoNagaiPotential& stellar_disk,
190 const GasDiskProps& gas_disk, Real mvir, Real rvir, Real cvir, Real rcool)
191 : DiskGalaxy{stellar_disk, gas_disk, mvir, rvir, cvir, rcool},
192 cluster_mass_distribution_(cluster_mass_distribution)
193 {
194 }
195
196 ClusterMassDistribution getClusterMassDistribution() const
197 {
198 // we should return a CONST reference or a copy (so that the internal object isn't mutated)
199 return cluster_mass_distribution_;
200 }
201};
202
203// in the future, it may be better to make the following 2 choices more configurable (and maybe
204// store them inside the Galaxy object)
205inline Real Get_StarCluster_Truncation_Radius(const Parameters& p)
206{
207 if ((20.4 < p.xlen) and (p.xlen < 20.5)) return 9.5;
208 return p.xlen / 2.0 - 0.5;
209}
210
211inline Real Get_Gas_Truncation_Radius(const Parameters& p)
212{
213 if ((20.4 < p.xlen) and (p.xlen < 20.5)) return 9.9;
214 return p.xlen / 2.0 - 0.3;
215}
216
217namespace galaxies
218{
219
220// temporary helper function that is being used while we transition
221// to dynamically construct the galaxy model from the parameter file
222ClusteredDiskGalaxy make_MW_model();
223
224}; // namespace galaxies
225
226#endif // DISK_GALAXY
Definition disk_galaxy.h:138
Definition disk_galaxy.h:184
Definition disk_galaxy.h:39
Real kappa2(Real R, Real z) const
Definition disk_galaxy.cu:67
Real phi_total_D3D(Real R, Real z) const noexcept
Definition disk_galaxy.h:104
Real gr_total_D3D(Real R, Real z) const noexcept
Definition disk_galaxy.h:78
Definition potentials.h:254
Definition potentials.h:85
Definition potentials.h:11
Definition global.h:217