def resample_one_cluster(particles, hse, center, velocity): """ Resample radial profiles onto a single cluster's particle distribution. Parameters ---------- particles : :class:`~cluster_generator.particles.ClusterParticles` hse : center : array_like velocity : array_like """ if "gas" not in particles.particle_types: return particles center = ensure_ytarray(center, "kpc") velocity = ensure_ytarray(velocity, "kpc/Myr") r = ((particles["gas", "particle_position"]-center)**2).sum(axis=1).d np.sqrt(r, r) get_density = InterpolatedUnivariateSpline(hse["radius"], hse["density"]) dens = get_density(r) e_arr = 1.5 * hse["pressure"] / hse["density"] get_energy = InterpolatedUnivariateSpline(hse["radius"], e_arr) particles["gas", "thermal_energy"] = unyt_array(get_energy(r), "kpc**2/Myr**2") vol = particles["gas", "particle_mass"] / particles["gas", "density"] particles["gas", "particle_mass"] = unyt_array(dens*vol.d, "Msun") particles["gas", "particle_velocity"][:,:] = velocity particles["gas", "density"] = unyt_array(dens, "Msun/kpc**3") return particles
def add_offsets(self, r_ctr, v_ctr, ptypes=None): """ Add offsets in position and velocity to the cluster particles, which can be added to one or more particle types. Parameters ---------- r_ctr : array-like A 3-element list, NumPy array, or unyt_array of the coordinates of the new center of the particle distribution. If units are not given, they are assumed to be in kpc. v_ctr : array-like A 3-element list, NumPy array, or unyt_array of the coordinates of the new bulk velocity of the particle distribution. If units are not given, they are assumed to be in kpc/Myr. ptypes : string or list of strings, optional A single string or list of strings indicating the particle type(s) to be offset. Default: None, meaning all of the particle types will be offset. This should not be used in normal circumstances. """ if ptypes is None: ptypes = self.particle_types ptypes = ensure_list(ptypes) r_ctr = ensure_ytarray(r_ctr, "kpc") v_ctr = ensure_ytarray(v_ctr, "kpc/Myr") for ptype in ptypes: self.fields[ptype, "particle_position"] += r_ctr self.fields[ptype, "particle_velocity"] += v_ctr
def __init__(self, basename, num_halos, profiles, center, velocity, num_particles=None, mag_file=None, particle_files=None, r_max=20000.0): self.basename = basename self.num_halos = num_halos self.profiles = ensure_list(profiles) self.center = ensure_ytarray(center, "kpc") self.velocity = ensure_ytarray(velocity, "kpc/Myr") if self.num_halos == 1: self.center = self.center.reshape(1, 3) self.velocity = self.velocity.reshape(1, 3) self.mag_file = mag_file self.r_max = r_max if num_particles is None: self.tot_np = {"dm": 0, "gas": 0, "star": 0} else: self.tot_np = num_particles self._determine_num_particles() self.particle_files = [None] * 3 if particle_files is not None: self.particle_files[:num_halos] = particle_files[:]
def add_black_hole(self, bh_mass, pos=None, vel=None, use_pot_min=False): r""" Add a black hole particle to the set of cluster particles. Parameters ---------- bh_mass : float The mass of the black hole particle in solar masses. pos : array-like, optional The position of the particle, assumed to be in units of kpc if units are not given. If use_pot_min=True this argument is ignored. Default: None, in which case the particle position is [0.0, 0.0, 0.0] kpc. vel : array-like, optional The velocity of the particle, assumed to be in units of kpc/Myr if units are not given. If use_pot_min=True this argument is ignored. Default: None, in which case the particle velocity is [0.0, 0.0, 0.0] kpc/Myr. use_pot_min : boolean, optional If True, use the dark matter particle with the minimum value of the gravitational potential to determine the position and velocity of the black hole particle. Default: False """ mass = unyt_quantity(bh_mass, "Msun") self.fields["black_hole", "particle_mass"] = unyt_array( [bh_mass], "Msun") if use_pot_min: idx = np.argmin(self.fields["dm", "potential_energy"]) pos = unyt_array(self.fields["dm", "particle_position"][idx] ).reshape(1,3) vel = unyt_array(self.fields["dm", "particle_velocity"][idx] ).reshape(1,3) else: if pos is None: pos = unyt_array(np.zeros((1, 3)), "kpc") if vel is None: vel = unyt_array(np.zeros((1, 3)), "kpc/Myr") pos = ensure_ytarray(pos, "kpc") vel = ensure_ytarray(vel, "kpc/Myr") if "black_hole" not in self.particle_types: self.particle_types.append("black_hole") self.fields["black_hole", "particle_position"] = pos self.fields["black_hole", "particle_velocity"] = vel self.fields["black_hole", "particle_mass"] = mass else: uappend = lambda x, y: unyt_array(np.append(x, y, axis=0).v, x.units) self.fields["black_hole", "particle_position"] = uappend( self.fields["black_hole", "particle_position"], pos) self.fields["black_hole", "particle_velocity"] = uappend( self.fields["black_hole", "particle_velocity"], vel) self.fields["black_hole", "particle_mass"] = uappend( self.fields["black_hole", "particle_mass"], mass) self._update_num_particles()
def _sample_clusters(particles, hses, center, velocity, radii=None, resample=False, passive_scalars=None): num_halos = len(hses) center = [ensure_ytarray(c, "kpc") for c in center] velocity = [ensure_ytarray(v, "kpc/Myr") for v in velocity] r = np.zeros((num_halos, particles.num_particles["gas"])) for i, c in enumerate(center): r[i,:] = ((particles["gas", "particle_position"]-c)**2).sum(axis=1).d np.sqrt(r, r) if radii is None: idxs = slice(None, None, None) else: radii = np.array(radii) idxs = np.any(r <= radii[:,np.newaxis], axis=0) d = np.zeros((num_halos, particles.num_particles["gas"])) e = np.zeros((num_halos, particles.num_particles["gas"])) m = np.zeros((num_halos, 3, particles.num_particles["gas"])) num_scalars = 0 if passive_scalars is not None: num_scalars = len(passive_scalars) s = np.zeros((num_halos, num_scalars, particles.num_particles["gas"])) for i in range(num_halos): hse = hses[i] if "density" not in hse: continue get_density = InterpolatedUnivariateSpline(hse["radius"], hse["density"]) d[i,:] = get_density(r[i,:]) e_arr = 1.5*hse["pressure"]/hse["density"] get_energy = InterpolatedUnivariateSpline(hse["radius"], e_arr) e[i,:] = get_energy(r[i,:])*d[i,:] m[i,:,:] = velocity[i].d[:,np.newaxis]*d[i,:] if num_scalars > 0: for j, name in enumerate(passive_scalars): get_scalar = InterpolatedUnivariateSpline(hse["radius"], hse[name]) s[i,j,:] = get_scalar(r[i,:])*d[i,:] dens = d.sum(axis=0) eint = e.sum(axis=0)/dens mom = m.sum(axis=0)/dens if num_scalars > 0: ps = s.sum(axis=0)/dens if resample: vol = particles["gas", "particle_mass"]/particles["gas", "density"] particles["gas", "particle_mass"][idxs] = dens[idxs]*vol[idxs] particles["gas", "density"][idxs] = dens[idxs] particles["gas", "thermal_energy"][idxs] = eint[idxs] particles["gas", "particle_velocity"][idxs] = mom.T[idxs] if num_scalars > 0: for j, name in enumerate(passive_scalars): particles["gas", name][idxs] = ps[j,idxs] return particles
def combine_three_clusters(particles1, particles2, particles3, hse1, hse2, hse3, center1, center2, center3, velocity1, velocity2, velocity3): center1 = ensure_ytarray(center1, "kpc") center2 = ensure_ytarray(center2, "kpc") center3 = ensure_ytarray(center3, "kpc") velocity1 = ensure_ytarray(velocity1, "kpc/Myr") velocity2 = ensure_ytarray(velocity2, "kpc/Myr") velocity3 = ensure_ytarray(velocity3, "kpc/Myr") if "gas" in particles1.particle_types: particles1.add_offsets(center1, [0.0]*3, ptypes=["gas"]) if "gas" in particles2.particle_types: particles2.add_offsets(center2, [0.0]*3, ptypes=["gas"]) if "gas" in particles3.particle_types: particles3.add_offsets(center3, [0.0]*3, ptypes=["gas"]) ptypes1 = particles1.particle_types.copy() ptypes2 = particles2.particle_types.copy() ptypes3 = particles3.particle_types.copy() if 'gas' in ptypes1: ptypes1.remove('gas') if 'gas' in ptypes2: ptypes2.remove('gas') if 'gas' in ptypes3: ptypes3.remove('gas') particles1.add_offsets(center1, velocity1, ptypes=ptypes1) particles2.add_offsets(center2, velocity2, ptypes=ptypes2) particles3.add_offsets(center3, velocity3, ptypes=ptypes3) particles = particles1+particles2+particles3 if "gas" in particles.particle_types: particles = _sample_clusters(particles, [hse1, hse2, hse3], [center1, center2, center3], [velocity1, velocity2, velocity3]) return particles