def check_virial(self): r""" Computes the radial density profile for the collisionless particles computed from integrating over the distribution function, and the relative difference between this and the input density profile. Returns ------- rho : NumPy array The density profile computed from integrating the distribution function. chk : NumPy array The relative difference between the input density profile and the one calculated using this method. """ n = self.num_elements rho = np.zeros(n) pden = self.model[f"{self.ptype}_density"].d rho_int = lambda e, psi: self.f(e)*np.sqrt(2*(psi-e)) for i, e in enumerate(self.ee): rho[i] = 4.*np.pi*quad(rho_int, 0., e, args=(e,))[0] chk = (rho[::-1]-pden)/pden mylog.info("The maximum relative deviation of this profile from " "virial equilibrium is %g", np.abs(chk).max()) return rho[::-1], chk
def check_model(self): n = len(self.ee) rho = np.zeros(n) rho_int = lambda e, psi: self.f(e)*np.sqrt(2*(psi-e)) for i, e in enumerate(self.ee[::-1]): rho[i] = 4.*np.pi*quad(rho_int, 0., e, args=(e))[0] chk = np.abs(rho-self.pden)/self.pden mylog.info("The maximum relative deviation of this profile from " "virial equilibrium is %g" % np.abs(chk).max()) return rho, chk
def _generate_df(self): pden = self.model[f"{self.ptype}_density"][::-1] density_spline = InterpolatedUnivariateSpline(self.ee, pden) g = np.zeros(self.num_elements) dgdp = lambda t, e: 2*density_spline(e-t*t, 1) pbar = tqdm(leave=True, total=self.num_elements, desc="Computing particle DF ") for i in range(self.num_elements): g[i] = quad(dgdp, 0., np.sqrt(self.ee[i]), epsabs=1.49e-05, epsrel=1.49e-05, args=(self.ee[i]))[0] pbar.update() pbar.close() g_spline = InterpolatedUnivariateSpline(self.ee, g) ff = g_spline(self.ee, 1)/(np.sqrt(8.)*np.pi**2) self.f = InterpolatedUnivariateSpline(self.ee, ff) self.df = unyt_array(ff[::-1], "Msun*Myr**3/kpc**6")
def __init__(self, num_particles, rr, gpot, pden, mdm): fields = OrderedDict() ee = gpot[::-1] density_spline = InterpolatedUnivariateSpline(ee, pden[::-1]) energy_spline = InterpolatedUnivariateSpline(rr, gpot) num_points = gpot.shape[0] g = np.zeros(num_points) dgdp = lambda t, e: 2*density_spline(e-t*t, 1) pbar = get_pbar("Computing particle DF.", num_points) for i in range(num_points): g[i] = quad(dgdp, 0., np.sqrt(ee[i]), args=(ee[i]))[0] pbar.update(i) pbar.finish() g_spline = InterpolatedUnivariateSpline(ee, g) f = lambda e: g_spline(e, 1)/(np.sqrt(8.)*np.pi**2) self.ee = ee self.f = f self.rr = rr self.pden = pden mylog.info("We will be assigning %d particles." % num_particles) mylog.info("Compute particle positions.") u = np.random.uniform(size=num_particles) P_r = np.insert(mdm, 0, 0.0) P_r /= P_r[-1] radius = np.interp(u, P_r, np.insert(rr, 0, 0.0), left=0.0, right=1.0) theta = np.arccos(np.random.uniform(low=-1.,high=1.,size=num_particles)) phi = 2.*np.pi*np.random.uniform(size=num_particles) fields["particle_radius"] = YTArray(radius, "kpc") fields["particle_position_x"] = YTArray(radius*np.sin(theta)*np.cos(phi), "kpc") fields["particle_position_y"] = YTArray(radius*np.sin(theta)*np.sin(phi), "kpc") fields["particle_position_z"] = YTArray(radius*np.cos(theta), "kpc") mylog.info("Compute particle velocities.") psi = energy_spline(radius) vesc = 2.*psi fv2esc = vesc*f(psi) vesc = np.sqrt(vesc) velocity = generate_velocities(psi, vesc, fv2esc, f) theta = np.arccos(np.random.uniform(low=-1.,high=1.,size=num_particles)) phi = 2.*np.pi*np.random.uniform(size=num_particles) fields["particle_velocity"] = YTArray(velocity, "kpc/Myr") fields["particle_velocity_x"] = YTArray(velocity*np.sin(theta)*np.cos(phi), "kpc/Myr") fields["particle_velocity_y"] = YTArray(velocity*np.sin(theta)*np.sin(phi), "kpc/Myr") fields["particle_velocity_z"] = YTArray(velocity*np.cos(theta), "kpc/Myr") fields["particle_mass"] = YTArray([mdm.max()/num_particles], "Msun") fields["particle_potential"] = YTArray(psi, "kpc**2/Myr**2") fields["particle_energy"] = fields["particle_potential"]-0.5*fields["particle_velocity"]**2 super(VirialEquilibrium, self).__init__(num_particles, fields, "spherical")