def _calculate_radial_quantities(self): """ Calculate various component radii and half radii """ from caesar.group_funcs import get_half_mass_radius, get_full_mass_radius r = np.empty(len(self.global_indexes), dtype=np.float64) get_periodic_r(self.obj.simulation.boxsize.d, self.pos.d, self.obj.data_manager.pos[self.global_indexes], r) rsort = np.argsort(r) r = r[rsort] mass = self.obj.data_manager.mass[self.global_indexes][rsort] ptype = self.obj.data_manager.ptype[self.global_indexes][rsort] radial_categories = dict( total = [ptype_ints['gas'],ptype_ints['star'],ptype_ints['dm'],ptype_ints['bh'],ptype_ints['dust']], baryon = [ptype_ints['gas'],ptype_ints['star']], gas = [ptype_ints['gas']], stellar = [ptype_ints['star']], dm = [ptype_ints['dm']], ) half_masses = {} for k,v in six.iteritems(self.masses): half_masses[k] = 0.5 * v for k,v in six.iteritems(radial_categories): if k == 'dm' and self.obj_type == 'galaxy': continue binary = 0 for p in v: binary += 2**p full_r = get_full_mass_radius(r[::-1], ptype[::-1], binary) self.radii[k] = self.obj.yt_dataset.quan(full_r, self.obj.units['length']) half_r = get_half_mass_radius(mass, r, ptype, half_masses[k], binary) self.radii['%s_half_mass' % k] = self.obj.yt_dataset.quan(half_r, self.obj.units['length'])
def _calculate_center_of_mass_quantities(self): """Calculate center-of-mass position and velocity. From caesar_mika """ def get_center_of_mass_quantity(quantity): ## REFACTOR ME TO BE MORE GENERIC WITH SHAPE val = np.zeros(3) for i in range(0,3): quantity_arr = getattr(self.obj.data_manager, quantity)[self.global_indexes, i] weights = self.obj.data_manager.mass[self.global_indexes] if (quantity=='pos'):# We need to be consistent with periodic boundaries if (quantity_arr.max() - quantity_arr.min())>0.5*self.obj.simulation.boxsize.d: theta_i = 6.283185307179586*quantity_arr/self.obj.simulation.boxsize.d #(2pi) Zeta_i = np.cos(theta_i) Xhi_i = np.sin(theta_i) Theta = np.arctan2(-np.average(Xhi_i, weights=weights), -np.average(Zeta_i, weights=weights))+3.141592653589793 val[i] = self.obj.simulation.boxsize.d*Theta/6.283185307179586 else: val[i] = np.average(quantity_arr, weights=weights) else: val[i] = np.average(quantity_arr, weights=weights) return val self.pos = self.obj.yt_dataset.arr(get_center_of_mass_quantity('pos'), self.obj.units['length']) self.vel = self.obj.yt_dataset.arr(get_center_of_mass_quantity('vel'), self.obj.units['velocity']) cmpos = (self.pos.to('kpc')).d ppos = self.obj.yt_dataset.arr(self.obj.data_manager.pos[self.global_indexes], self.obj.units['length']) ppos = (ppos.to('kpc')).d #Minimum potential position pot = self.obj.data_manager.pot[self.global_indexes] pos = self.obj.data_manager.pos[self.global_indexes] self.minpotpos = self.obj.yt_dataset.arr(pos[np.argmin(pot)], self.obj.units['length']) #Compute distances from the center of mass or minimum potential? self.periodic_r = np.empty(len(ppos), dtype=np.float64) #get_periodic_r(self.obj.simulation.boxsize.to('kpc').d, cmpos, ppos, self.periodic_r) # COM get_periodic_r(self.obj.simulation.boxsize.to('kpc').d, self.minpotpos.to('kpc').d, ppos, self.periodic_r) # minimum potential #Put the periodic_r for further use and not to compute it everytime self.periodic_r = self.obj.yt_dataset.arr(self.periodic_r, 'kpc')
def _unbind(self): """Iterative procedure to unbind objects.""" if not getattr(self.obj.simulation, 'unbind_%s' % group_types[self.obj_type]): return if not hasattr(self, 'unbound_indexes'): self.unbound_indexes = { ptype_ints['gas']:[], ptype_ints['star']:[], ptype_ints['dm']:[], ptype_ints['bh']:[], ptype_ints['dust']:[], } if not hasattr(self, 'unbind_iterations'): self.unbind_iterations = 0 self.unbind_iterations += 1 cmpos = (self.pos.to('kpc')).d ppos = self.obj.yt_dataset.arr(self.obj.data_manager.pos[self.global_indexes], self.obj.units['length']) ppos = (ppos.to('kpc')).d cmvel = (self.vel.to('kpc/s')).d pvels = self.obj.yt_dataset.arr(self.obj.data_manager.vel[self.global_indexes], self.obj.units['velocity']) pvels = (pvels.to('kpc/s')).d mass = self.obj.yt_dataset.arr(self.obj.data_manager.mass[self.global_indexes], self.obj.units['mass']) mass = (mass.to('Msun')).d init_mass = (self.masses['total'].to('Msun')).d r = np.empty(len(ppos), dtype=np.float64) get_periodic_r(self.obj.simulation.boxsize.d, cmpos, ppos, r) v2 = ( (pvels[:,0] - cmvel[0])**2 + (pvels[:,1] - cmvel[1])**2 + (pvels[:,2] - cmvel[2])**2 ) energy = -(mass * self.obj.simulation.G.d * (init_mass - mass) / r) + (0.5 * mass * v2) positive = np.where(energy > 0)[0] if len(positive) > 0: positive = positive[::-1] for i in positive: global_index = self.global_indexes[i] self.unbound_indexes[self.obj.data_manager.ptype[global_index]].append(self.obj.data_manager.index[global_index]) del self.global_indexes[i] self._assign_local_data() if not self._valid: return self._calculate_total_mass() self._calculate_center_of_mass_quantities() self._unbind()