Example #1
0
def test_sech2():
    Sigma = 65. * u.Msun / u.pc**2
    hz = 250 * u.pc
    _G = G.decompose([u.pc, u.Msun, u.Myr]).value
    rho0 = Sigma / (4 * hz)

    with u.set_enabled_equivalencies(u.dimensionless_angles()):
        assert quantity_allclose(sech2_density(0. * u.pc, Sigma, hz), rho0)

    # check numerical derivatives of potential against functions
    rnd = np.random.RandomState(42)
    for z0 in rnd.uniform(100, 500, size=16):  # check a few random places
        num_grad = derivative(sech2_potential,
                              z0,
                              dx=1e-2,
                              n=1,
                              args=(Sigma.value, hz.value, _G))
        grad = sech2_gradient(z0, Sigma.value, hz.value, _G)
        assert np.allclose(grad, num_grad)

        num_dens = derivative(
            sech2_potential,
            z0,
            dx=1e-2,
            n=2,
            args=(Sigma.value, hz.value, _G)) / (4 * np.pi * _G)
        dens = sech2_density(z0, Sigma.value, hz.value)
        assert np.allclose(dens, num_dens)
Example #2
0
    def __init__(self,rc,Mtot,G='kpc km2 / (M_sun s2)'):
        """
        Analytic Plummer model
        :param rc: Plummer scale length
        :param Mtot:  Plummer total mass
        :param G: Value of the gravitational constant G, it can be a number of a string.
                    If G=1, the physical value of the potential will be Phi/G.
                    If string it must follow the rule of the unity of the module.astropy constants.
                    E.g. to have G in unit of kpc3/Msun s2, the input string is 'kpc3 / (M_sun s2)'
                    See http://astrofrog-debug.readthedocs.org/en/latest/constants/

        :return:
        """
        self.rc=rc
        self.Mmax=Mtot
        if isinstance(G,float) or isinstance(G,int): self.G=G
        else:
            GG=conG.to(G)
            self.G=GG.value

        self._use_nparray=True
        self._analytic_radius=True
        self.use_c=False
        self._densnorm=(3*Mtot)/(4*np.pi*rc*rc*rc)
        self._sdensnorm=Mtot/(np.pi*rc*rc)
        self._potnorm=self.G*Mtot
Example #3
0
 def Rho_crit(self, cosmo=None):
     if not cosmo:
         cosmo = self.cosmo
     G2 = G.to(u.Mpc / u.Msun * u.km**2 / u.second**2)
     rc = 3 * cosmo.H0**2 / (8 * np.pi * G2)
     rc = rc.to(u.Msun / u.pc**2 / u.Mpc)  # unit of Msun/pc^2/mpc
     return rc
Example #4
0
    def _read_units(self):
        """
        Read and parse the SCFPAR file containing simulation parameters
        and initial conditions. Right now, only parse out the simulation units.
        """
        pars = dict()

        parfile = os.path.join(self.path, "SCFPAR")
        with open(parfile) as f:
            lines = f.readlines()

            # find what G is set to
            for i,line in enumerate(lines):
                if line.split()[1].strip() == "G":
                    break
            pars['G'] = float(lines[i].split()[0])
            pars['length'] = float(lines[i+10].split()[0])
            pars['mass'] = float(lines[i+11].split()[0])

            self.x0 = np.array(map(float, lines[19].split()))*u.kpc
            self.v0 = np.array(map(float, lines[20].split()))*u.km/u.s

        _G = G.decompose(bases=[u.kpc,u.M_sun,u.Myr]).value
        X = (_G / pars['length']**3 * pars['mass'])**-0.5

        length_unit = u.Unit("{0} kpc".format(pars['length']))
        mass_unit = u.Unit("{0} M_sun".format(pars['mass']))
        time_unit = u.Unit("{:08f} Myr".format(X))

        # units = dict(length=length_unit,
        #              mass=mass_unit,
        #              time=time_unit,
        #              speed=length_unit/time_unit,
        #              dimensionless=u.dimensionless_unscaled)
        return UnitSystem(length_unit, mass_unit, time_unit, length_unit/time_unit, u.radian)
Example #5
0
def test_against_gary():
    cos_coeff = np.array([[[1.509, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [-2.606, 0.0, 0.665, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [6.406, 0.0, -0.66, 0.0, 0.044, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [-5.859, 0.0, 0.984, 0.0, -0.03, 0.0, 0.001]], [[-0.086, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [-0.221, 0.0, 0.129, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [1.295, 0.0, -0.14, 0.0, -0.012, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]], [[-0.033, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [-0.001, 0.0, 0.006, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]], [[-0.02, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],  [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]])
    sin_coeff = np.zeros_like(cos_coeff)
    nmax = sin_coeff.shape[0]-1
    lmax = sin_coeff.shape[1]-1

    max_x = 10.
    grid = np.linspace(-max_x,max_x,8)
    grid = grid[grid != 0.]
    xyz = np.ascontiguousarray(np.vstack(map(np.ravel, np.meshgrid(grid,grid,grid))).T)
    # xyz = np.array([[1.,1.,1.]])

    grad = np.zeros_like(xyz)
    acceleration(xyz, grad, sin_coeff, cos_coeff, nmax, lmax)
    grad *= -1.

    val = np.zeros(len(grad))
    value(xyz, val, sin_coeff, cos_coeff, nmax, lmax)

    # gary
    import gary.potential as gp
    from gary.units import galactic
    G = _G.decompose(galactic).value
    potential = gp.SCFPotential(m=1/G, r_s=1.,
                                sin_coeff=sin_coeff, cos_coeff=cos_coeff,
                                units=galactic)
    gary_val = potential.value(xyz)
    gary_grad = potential.gradient(xyz)

    np.testing.assert_allclose(gary_val, val, rtol=1E-5)
    np.testing.assert_allclose(gary_grad, grad, rtol=1E-5)
Example #6
0
    def __init__(self, m, a, units):
        self.parameters = OrderedDict()
        self.parameters['m'] = m
        self.parameters['a'] = a

        super(KuzminPotential, self).__init__(units=units)
        self.G = G.decompose(units).value
Example #7
0
    def __init__(self, rc, Mtot, G='kpc km2 / (M_sun s2)'):
        """
        Analytic Plummer model
        :param rc: Plummer scale length
        :param Mtot:  Plummer total mass
        :param G: Value of the gravitational constant G, it can be a number of a string.
                    If G=1, the physical value of the potential will be Phi/G.
                    If string it must follow the rule of the unity of the module.astropy constants.
                    E.g. to have G in unit of kpc3/Msun s2, the input string is 'kpc3 / (M_sun s2)'
                    See http://astrofrog-debug.readthedocs.org/en/latest/constants/

        :return:
        """
        self.rc = rc
        self.Mmax = Mtot
        if isinstance(G, float) or isinstance(G, int): self.G = G
        else:
            GG = conG.to(G)
            self.G = GG.value

        self._use_nparray = True
        self._analytic_radius = True
        self.use_c = False
        self._densnorm = (3 * Mtot) / (4 * np.pi * rc * rc * rc)
        self._potnorm = self.G * Mtot
    def __init__(self, options_reader, grid_snapshot=None):

        self.G = G_astropy.to_value(u.kpc**2 * u.km / (u.s * u.Myr * u.Msun))
        self.theta = 0.5

        self.convert_kms_Myr_to_kpc = 20000.0*np.pi / (61478577.0)
        self.kpc_in_km = 3.08567758E16
        # opt = options_reader(options_file)
        options_reader.set_options(self)
        self.options_reader = options_reader

        if not os.path.isdir(self.cache_directory):
            os.makedirs(self.cache_directory)

        self._read_snapshots_()

        # find starting star
        if self.axisymmetric:
            if self.axi_Rinit is None or self.axi_vcircfrac is None or self.axi_zinit is None:
                self._init_starting_star_()
            self._gen_axisymmetric_()
        else:
            self._init_starting_star_()

        self._init_kdtree_()

        self.evolve_model(0 | units.Myr)
Example #9
0
File: core.py Project: adrn/gala
    def __init__(self, parameters, origin=None, R=None,
                 ndim=3, units=None):

        self._units = self._validate_units(units)
        self.parameters = self._prepare_parameters(parameters, self.units)

        try:
            self.G = G.decompose(self.units).value
        except u.UnitConversionError:
            self.G = 1. # TODO: this is a HACK and could lead to user confusion

        self.ndim = ndim

        if origin is None:
            origin = np.zeros(self.ndim)
        self.origin = self._remove_units(origin)

        if R is not None and ndim not in [2, 3]:
            raise NotImplementedError('Gala potentials currently only support '
                                      'rotations when ndim=2 or ndim=3.')

        if R is not None:
            if isinstance(R, Rotation):
                R = R.as_dcm()
            R = np.array(R)

            if R.shape != (ndim, ndim):
                raise ValueError('Rotation matrix passed to potential {0} has '
                                 'an invalid shape: expected {1}, got {2}'
                                 .format(self.__class__.__name__,
                                         (ndim, ndim), R.shape))
        self.R = R
Example #10
0
File: core.py Project: abonaca/gary
    def mass_enclosed(self, x):
        """
        Estimate the mass enclosed within the given position by assumine the potential
        is spherical. This is basic, and assumes spherical symmetry.

        Parameters
        ----------
        x : array_like, numeric
            Position to estimate the enclossed mass.
        """

        # Fractional step-size in radius
        h = 0.01

        # Radius
        r = np.sqrt(np.sum(x**2, axis=-1))

        epsilon = h*x/r[...,np.newaxis]

        dPhi_dr_plus = self.value(x + epsilon)
        dPhi_dr_minus = self.value(x - epsilon)
        diff = dPhi_dr_plus - dPhi_dr_minus

        if self.units is None:
            raise ValueError("No units specified when creating potential object.")
        Gee = G.decompose(self.units).value

        return np.abs(r*r * diff / Gee / (2.*h))
Example #11
0
    def _setup_potential(self, parameters, origin=None, R=None, units=None):

        self._units = self._validate_units(units)
        self.parameters = self._prepare_parameters(parameters, self.units)

        try:
            self.G = G.decompose(self.units).value
        except u.UnitConversionError:
            # TODO: this is a convention that and could lead to confusion!
            self.G = 1.

        if origin is None:
            origin = np.zeros(self.ndim)
        self.origin = self._remove_units(origin)

        if R is not None and self.ndim not in [2, 3]:
            raise NotImplementedError('Gala potentials currently only support '
                                      'rotations when ndim=2 or ndim=3.')

        if R is not None:
            if isinstance(R, Rotation):
                R = R.as_matrix()
            R = np.array(R)

            if R.shape != (self.ndim, self.ndim):
                raise ValueError(
                    'Rotation matrix passed to potential {0} has '
                    'an invalid shape: expected {1}, got {2}'.format(
                        self.__class__.__name__, (self.ndim, self.ndim),
                        R.shape))
        self.R = R
Example #12
0
    def __init__(self,rc,  G='kpc km2 / (M_sun s2)', Mmax=None, rmax=None, Vinf=None, d0=None):
        """
        PseudoIsothermal Model:

        d=d0/((1+r^2/rc^2)

        Given that the Mass diverge at infinty it is possibile to initialize the
        model in different ways:
        Mmax  (rmax): The model will have a mass of Mmax at radius rmax, if rmax is not supplied
                      it is equal to 10*rc
        d0: Central density. The unity depends on the combinations of gthe value of G and rc. By default
                      is Msun/kpc^3.
        Vinf: asymptotic circular velocity in km/s.

        The routine gives priority firstly to Mmax, then to d0 and finally to Vinf.

        :param rc:
        :param G: Value of the gravitational constant G, it can be a number of a string.
                    If G=1, the physical value of the potential will be Phi/G.
                    If string it must follow the rule of the unity of the module.astropy constants.
                    E.g. to have G in unit of kpc3/Msun s2, the input string is 'kpc3 / (M_sun s2)'
                    See http://astrofrog-debug.readthedocs.org/en/latest/constants/
        :param Mmax: Total Mass in Msun at radius rmax.
        :param rmax: Radius to cut the density distribution, by default is equal to 10*rc.
        :param d0: Central density. The unity depends on the combinations of gthe value of G and rc. By default
                   is Msun/kpc^3. Available only if Mmax is None.
        :param Vinf: asymptotic circular velocity in km/s. Available only if Mmax and d0 are None.
        :return:
        """

        if rmax is None: self.rmax=10*rc
        else: self.rmax=rmax

        self.rc=rc
        self.use_c=False
        self._use_nparray=True
        if isinstance(G,float) or isinstance(G,int): self.G=G
        else:
            GG=conG.to(G)
            self.G=GG.value

        self.Mc=1
        self.dc=1
        self.pc=1
        if Mmax is not None:
            totmass=self._evaluatemass(self.rmax)
            self.Mc=Mmax/totmass
            self.dc=self.Mc/(4*np.pi)
            self.pc=self.G*self.Mc
        elif d0 is not None:
            self.dc=d0
            self.Mc=(4*np.pi)*self.dc
            self.pc=self.G*self.Mc
        elif Vinf is not None:
            self.pc=(Vinf*Vinf)/(self.rc*self.rc)
            self.Mc=self.pc/self.G
            self.dc=self.Mc/(4*np.pi)
Example #13
0
 def __init__(self, zs_bins=None, zg_bins=None, logger=None, l=None):
     self.logger = logger
     self.l = l
     #Gravitaional const to get Rho crit in right units
     self.G2 = G.to(u.Mpc / u.Msun * u.km**2 / u.second**2)
     self.G2 *= 8 * np.pi / 3.
     self.zs_bins = zs_bins
     self.zg_bins = zg_bins
     self.SN = {}
     if zs_bins is not None:  #sometimes we call this class just to access some of the functions
         self.set_zbins(z_bins=zs_bins, tracer='shear')
     if zg_bins is not None:  #sometimes we call this class just to access some of the functions
         self.set_zbins(z_bins=zg_bins, tracer='galaxy')
Example #14
0
    def attract(self, other):
        dx = self.x - other.x
        dy = self.y - other.y
        theta = math.atan2(dy, dx)
        distance = math.hypot(dx, dy)

        # calculate attractive force due to gravity using Newton's law of universal gravitation:
        # F = G * m1 * m2 / r^2
        # for consistency, G = [AU^3 * kg^-1 * d^-2]
        force = G.to('AU3 / (kg d2)').value * self.mass * other.mass / (
            distance**2)

        # accelerate both bodies towards each other by acceleration vector a = F/m, rearranged from Newton's second law
        self.accelerate((force / self.mass, theta - (math.pi / 2)))
        other.accelerate((force / other.mass, theta + (math.pi / 2)))
Example #15
0
def _units_from_file(scfpar):
    """ Generate a unit system from an SCFPAR file. """

    with open(scfpar) as f:
        lines = f.readlines()
        length = float(lines[16].split()[0])
        mass = float(lines[17].split()[0])

    GG = G.decompose(bases=[u.kpc, u.M_sun, u.Myr]).value
    X = (GG / length**3 * mass)**-0.5

    length_unit = u.Unit("{0} kpc".format(length))
    mass_unit = u.Unit("{0} M_sun".format(mass))
    time_unit = u.Unit("{:08f} Myr".format(X))

    return dict(length=length_unit, mass=mass_unit, time=time_unit)
Example #16
0
    def __init__(self, options_reader, grid_snapshot=None):

        agama.setUnits(mass=1, length=1, velocity=1)

        self.G = G_astropy.to_value(u.kpc**2 * u.km / (u.s * u.Myr * u.Msun))
        self.theta = 0.5

        self.convert_kms_Myr_to_kpc = 20000.0 * np.pi / (61478577.0)
        self.kpc_in_km = 3.08567758E16
        # opt = options_reader(options_file)
        options_reader.set_options(self)
        self.options_reader = options_reader

        self.snapshot_indices = range(self.startnum - self.num_prior,
                                      self.endnum + 1)
        self.initial_key = self.num_prior

        if not os.path.isdir(self.cache_directory):
            os.makedirs(self.cache_directory)

        if self.axisymmetric:
            if self.axisymmetric_tevolve:
                self._read_snapshots_()
                self._gen_axisymmetric_(all_snaps=True)
                self.evolve_model(0 | units.Myr)
            else:
                self._read_snapshots_(first_only=True)
                self._gen_axisymmetric_()
            return None

        self._read_snapshots_()

        # find starting star
        self._init_starting_star_()

        # set up trackers
        self._init_starting_star_interpolators_()

        # set up grid
        if grid_snapshot is not None:
            self._init_grid_(grid_snapshot)
        else:
            self._init_grid_()

        self.evolve_model(0 | units.Myr)

        self.grid._grid_evolved_kdtree_ = cKDTree(self.grid.evolved_grid)
Example #17
0
    def compute_rotation_curve(self, arr):
        """ Compute the rotation curve. """

        # Compute distance to centre.
        r = np.linalg.norm(arr['coords'] - self.centre, axis=1)
        mask = np.argsort(r)
        r = r[mask]

        # Compute cumulative mass.
        cmass = np.cumsum(arr['mass'][mask])

        # Compute velocity.
        myG = G.to(u.km**2 * u.Mpc * u.Msun**-1 * u.s**-2).value
        v = np.sqrt((myG * cmass) / r)

        # Return r in Mpc and v in km/s.
        return r, v
Example #18
0
    def _calculate_gravitational_acceleration(self):
        # direction and strength of force
        # F = Gm/r^2
        acceleration = []
        for body in self.current_ephem:
            r_vector = body[1].rv()[0] - self.spaceship.rv[0]
            r_magnitude = np.linalg.norm(r_vector)

            a_magnitude = (G.to("km3/kg s2") * body[0].mass) / (r_magnitude**2)
            a_vector = a_magnitude * r_vector / r_magnitude
            acceleration.append(a_vector)

        total_acceleration = 0
        for a in acceleration:
            total_acceleration += a

        return total_acceleration
Example #19
0
    def mass_enclosed(self, q, t=0.):
        """
        Estimate the mass enclosed within the given position by assuming the potential
        is spherical.

        Parameters
        ----------
        q : `~gala.dynamics.PhaseSpacePosition`, `~astropy.units.Quantity`, array_like
            Position(s) to estimate the enclossed mass.

        Returns
        -------
        menc : `~astropy.units.Quantity`
            Mass enclosed at the given position(s). If the input position
            has shape ``q.shape``, the output energy will have shape
            ``q.shape[1:]``.
        """
        q = self._remove_units_prepare_shape(q)
        orig_shape,q = self._get_c_valid_arr(q)
        t = self._validate_prepare_time(t, q)

        # small step-size in direction of q
        h = 1E-3 # MAGIC NUMBER

        # Radius
        r = np.sqrt(np.sum(q**2, axis=1))

        epsilon = h*q/r[:,np.newaxis]

        dPhi_dr_plus = self._energy(q + epsilon, t=t)
        dPhi_dr_minus = self._energy(q - epsilon, t=t)
        diff = (dPhi_dr_plus - dPhi_dr_minus)

        if isinstance(self.units, DimensionlessUnitSystem):
            Gee = 1.
        else:
            Gee = G.decompose(self.units).value

        Menc = np.abs(r*r * diff / Gee / (2.*h))
        Menc = Menc.reshape(orig_shape[1:])

        sgn = 1.
        if 'm' in self.parameters and self.parameters['m'] < 0:
            sgn = -1.

        return sgn * Menc * self.units['mass']
Example #20
0
File: core.py Project: adrn/gala
    def mass_enclosed(self, q, t=0.):
        """
        Estimate the mass enclosed within the given position by assuming the potential
        is spherical.

        Parameters
        ----------
        q : `~gala.dynamics.PhaseSpacePosition`, `~astropy.units.Quantity`, array_like
            Position(s) to estimate the enclossed mass.

        Returns
        -------
        menc : `~astropy.units.Quantity`
            Mass enclosed at the given position(s). If the input position
            has shape ``q.shape``, the output energy will have shape
            ``q.shape[1:]``.
        """
        q = self._remove_units_prepare_shape(q)
        orig_shape, q = self._get_c_valid_arr(q)
        t = self._validate_prepare_time(t, q)

        # small step-size in direction of q
        h = 1E-3 # MAGIC NUMBER

        # Radius
        r = np.sqrt(np.sum(q**2, axis=1))

        epsilon = h*q/r[:, np.newaxis]

        dPhi_dr_plus = self._energy(q + epsilon, t=t)
        dPhi_dr_minus = self._energy(q - epsilon, t=t)
        diff = (dPhi_dr_plus - dPhi_dr_minus)

        if isinstance(self.units, DimensionlessUnitSystem):
            Gee = 1.
        else:
            Gee = G.decompose(self.units).value

        Menc = np.abs(r*r * diff / Gee / (2.*h))
        Menc = Menc.reshape(orig_shape[1:])

        sgn = 1.
        if 'm' in self.parameters and self.parameters['m'] < 0:
            sgn = -1.

        return sgn * Menc * self.units['mass']
Example #21
0
def _units_from_file(scfpar):
    """ Generate a unit system from an SCFPAR file. """

    with open(scfpar) as f:
        lines = f.readlines()
        length = float(lines[16].split()[0])
        mass = float(lines[17].split()[0])

    GG = G.decompose(bases=[u.kpc,u.M_sun,u.Myr]).value
    X = (GG / length**3 * mass)**-0.5

    length_unit = u.Unit("{0} kpc".format(length))
    mass_unit = u.Unit("{0} M_sun".format(mass))
    time_unit = u.Unit("{:08f} Myr".format(X))

    return dict(length=length_unit,
                mass=mass_unit,
                time=time_unit)
def main():
    # The unit system we'll use:
    units = [u.Myr, u.kpc, u.Msun]
    _G = G.decompose(units).value

    # Initial conditions
    x0 = [10., 0, 0]
    v0 = [0, 0.15, 0]

    # Parameters of the Hernquist potential model
    m = 1E11  # Msun
    c = 1.  # kpc

    # Timestep in Myr
    dt = 1.
    n_steps = 10000  # 10 Gyr

    t, x, v = leapfrog_integrate(x0,
                                 v0,
                                 dt,
                                 n_steps,
                                 hernquist_args=(_G, m, c))

    # Plot the orbit
    fig, axes = plt.subplots(1, 2, figsize=(10, 5))

    axes[0].plot(x[:, 0], x[:, 1], marker='.', linestyle='none', alpha=0.1)
    axes[0].set_xlim(-12, 12)
    axes[0].set_ylim(-12, 12)

    axes[0].set_xlabel('$x$')
    axes[0].set_ylabel('$y$')

    # ---

    axes[1].plot(v[:, 0], v[:, 1], marker='.', linestyle='none', alpha=0.1)
    axes[1].set_xlim(-0.35, 0.35)
    axes[1].set_ylim(-0.35, 0.35)

    axes[1].set_xlabel('$v_x$')
    axes[1].set_ylabel('$v_y$')

    fig.tight_layout()
    plt.show()
Example #23
0
    def __init__(self,dprof,sprof,mprof,amodel='isotropic',G='kpc km2 / (M_sun s2)'):

        self.amodel=amodel



        self.dprof=dprof
        self.sprof=sprof
        self.mprof=mprof

        if isinstance(G,float) or isinstance(G,int): self.G=G
        else:
            GG=conG.to(G)
            self.G=GG.value

        if amodel=='isotropic':
            self.kernel=self._kerneliso


        self.cost=sqrt(2.*self.G)
Example #24
0
    def __init__(self, parameters, origin=None, parameter_physical_types=None,
                 ndim=3, units=None):

        self.units = self._validate_units(units)

        if parameter_physical_types is None:
            parameter_physical_types = dict()
        self._ptypes = parameter_physical_types
        self.parameters = self._prepare_parameters(parameters, self._ptypes,
                                                   self.units)

        try:
            self.G = G.decompose(self.units).value
        except u.UnitConversionError:
            self.G = 1. # TODO: this is a HACK and could lead to user confusion

        self.ndim = ndim

        if origin is None:
            origin = np.zeros(self.ndim)
        self.origin = self._remove_units(origin)
Example #25
0
    def __init__(self, table,span, ts):
        
        global au

        data = table
        self.g = G.to(((u.km)**3)/(u.kg*((u.day)**2))).value
        self.bodies = data['body']
        self.span = float(span)
        self.t = float(ts*u.hour.to(u.day))
        self.timestep = int(self.span/self.t)

        
        self.masses = [0.0 for i in range(len(self.bodies))]
        self.pos = [origin for i in range(len(self.bodies))]
        self.vel = [origin for i in range(len(self.bodies))]
        #self.pos_err = [origin for i in range(len(self.bodies))]
        self.barycenter = origin
        self.tot_mass = 0.0
        
        self.tab = [Table(names=['body', 'cycle', 'time', 'x', 'y', 'z', 'vx',\
            'vy', 'vz'], dtype=['S16', 'i8', 'f16', 'f16', 'f16', 'f16', 'f16',\
            'f16', 'f16']) for i in range(len(self.bodies))]

        for i in range(len(self.bodies)):


            self.masses[i] = data['mass'][i]
            self.pos[i] = vector(data['x'][i], data['y'][i], data['z'][i])
            #self.pos_err[i] = vector(data['ex'][i], data['ey'][i], data['ez'][i])
            self.vel[i] = vector(data['vx'][i], data['vy'][i], data['vz'][i])
            self.barycenter = self.barycenter + (self.pos[i])*(self.masses[i])
            self.tot_mass = self.tot_mass + self.masses[i]

        self.barycenter = self.barycenter*(1/self.tot_mass)

        for i in range(len(self.bodies)):

            self.tab[i].add_row([self.bodies[i], 0, 0, self.pos[i].x,\
            self.pos[i].y, self.pos[i].z, self.vel[i].x, self.vel[i].y,\
            self.vel[i].z])
Example #26
0
    def tdyn(self,mq=100,type=None,G='(kpc3)/(M_sun Gyr2)'):
        """
        Calculate the dynamical time of a stystem as Tdyn=0.5*pi*Sqrt(Rh^3/(G*Mh)).
        where Rh is the radius that contains the fraction Mh=h*M of the mass.
        This is the time for a particle at distance r to reach r=0 in a homogeneus spherical system
        with density rho. We do not have an homogenues sphere, but we use a medium value rho_mh
        equals to Mh/(4/3 * pi * Rh^3).
        :param mq: Fraction of the mass to use, it can ranges from 0 to 100
        :param type: Type of particle to use, it need to be an array. If None use all
        :param G: Value of the gravitational constant G, it can be a number of a string.
                    If G=1, the physical value of the potential will be Phi/G.
                    If string it must follow the rule of the unity of the module.astropy constants.
                    E.g. to have G in unit of kpc3/Msun s2, the input string is 'kpc3 / (M_sun s2)'
                    See http://astrofrog-debug.readthedocs.org/en/latest/constants/

        :return: Dynamical tyme. The units wil depends on the units used in G, If used the
                 G in default the time will be in unit of Gyr.
        """

        if type is None:
            rad_array=self.p.Radius[:]
            mas_array=self.p.Mass[:]
        else:
            type= nparray_check(type)
            rad_array=self._make_array(self.p.Radius,type)
            mas_array=self._make_array(self.p.Mass,type)


        if isinstance(G,float) or isinstance(G,int): G=G
        else:
            GG=conG.to(G)
            G=GG.value

        rq,_=self.qradius_ext(rad_array,mas_array,mq)

        mass_phy=G*(mq/100)*np.sum(mas_array)
        tdyn=0.5*np.pi*rq*np.sqrt(rq/mass_phy)


        return tdyn
Example #27
0
    def __init__(self, parameters, units=None):
        # make sure the units specified are a UnitSystem instance
        if units is not None and not isinstance(units, UnitSystem):
            units = UnitSystem(*units)

        elif units is None:
            units = DimensionlessUnitSystem()

        self.units = units

        # in case the user specified an ordered dict
        self.parameters = OrderedDict()
        for k, v in parameters.items():
            if hasattr(v, 'unit'):
                self.parameters[k] = v.decompose(self.units)
            else:
                self.parameters[k] = v * u.one

        try:
            self.G = G.decompose(self.units).value
        except u.UnitConversionError:
            self.G = 1.  # TODO: this is a HACK and could lead to user confusion
Example #28
0
    def __init__(self, parameters, units=None):
        # make sure the units specified are a UnitSystem instance
        if units is not None and not isinstance(units, UnitSystem):
            units = UnitSystem(*units)

        elif units is None:
            units = DimensionlessUnitSystem()

        self.units = units

        # in case the user specified an ordered dict
        self.parameters = OrderedDict()
        for k,v in parameters.items():
            if hasattr(v, 'unit'):
                self.parameters[k] = v.decompose(self.units)
            else:
                self.parameters[k] = v*u.one

        try:
            self.G = G.decompose(self.units).value
        except u.UnitConversionError:
            self.G = 1. # TODO: this is a HACK and could lead to user confusion
Example #29
0
    def __init__(self,m,rc,Mtot,G='kpc km2 / (M_sun s2)'):
        """
        Analytic Sersic model:

        Surface density: S(R)=S(0) * Exp(-(R/rc)^(1/m))
        for the 3D deprojection we use the analytic approximation of Lima Neto, Gerbal and Marquez, 1999.
        Density: d(r)=d(0) * Exp(-(r/rc)^(1/m)) * (r/rc)^(-p) where p=1 - 0.6097*(1/m) + 0.05463*(1/m^2)

        :param m: Sersic exponent
        :param rc: Sersic scale length
        :param Mtot:  Sersic total mass
        :param G: Value of the gravitational constant G, it can be a number of a string.
                    If G=1, the physical value of the potential will be Phi/G.
                    If string it must follow the rule of the unity of the module.astropy constants.
                    E.g. to have G in unit of kpc3/Msun s2, the input string is 'kpc3 / (M_sun s2)'
                    See http://astrofrog-debug.readthedocs.org/en/latest/constants/

        :return:
        """

        self.rc=rc
        self.Mmax=Mtot
        self.m=m
        self.nu=1/m
        self.p=1-0.6097*self.nu+0.05463*self.nu*self.nu
        self.use_c=False
        self._use_nparray=True
        self._analytic_radius=True

        if isinstance(G,float) or isinstance(G,int): self.G=G
        else:
            GG=conG.to(G)
            self.G=GG.value

        dmgamma= self.m*gamma(self.m*(3-self.p)) #Mtot=4*pi*d0*rc^3 * m* *Gamma(m*(3-p))
        self._densnorm=Mtot/(4*np.pi*rc*rc*rc*dmgamma)
        sdmgamma= self.m*gamma(2*self.m)  #Mtot=2*pi*S0*rc^2 * m * Gamma(2*m)
        self._sdensnorm=Mtot/(2*np.pi*rc*rc*sdmgamma)
        self._potnorm=(self.G*Mtot)
Example #30
0
    def tdyn(self, mq=100, type=None, G='(kpc3)/(M_sun s2)'):
        """
        Calculate the dynamical time of a stystem as Tdyn=0.5*pi*Sqrt(Rh^3/(G*Mh)).
        where Rh is the radius that contains the fraction Mh=h*M of the mass.
        This is the time for a particle at distance r to reach r=0 in a homogeneus spherical system
        with density rho. We do not have an homogenues sphere, but we use a medium value rho_mh
        equals to Mh/(4/3 * pi * Rh^3).
        :param mq: Fraction of the mass to use, it can ranges from 0 to 100
        :param type: Type of particle to use, it need to be an array. If None use all
        :param G: Value of the gravitational constant G, it can be a number of a string.
                    If G=1, the physical value of the potential will be Phi/G.
                    If string it must follow the rule of the unity of the module.astropy constants.
                    E.g. to have G in unit of kpc3/Msun s2, the input string is 'kpc3 / (M_sun s2)'
                    See http://astrofrog-debug.readthedocs.org/en/latest/constants/

        :return: Dynamical tyme. The units wil depends on the units used in G, If used the
                 G in default the time will be in unit of Gyr.
        """

        if type is None:
            rad_array = self.p.Radius[:]
            mas_array = self.p.Mass[:]
        else:
            type = nparray_check(type)
            rad_array = self._make_array(self.p.Radius, type)
            mas_array = self._make_array(self.p.Mass, type)

        if isinstance(G, float) or isinstance(G, int): G = G
        else:
            GG = conG.to(G)
            G = GG.value

        rq, _ = self.qradius_ext(rad_array, mas_array, mq)

        mass_phy = G * (mq / 100) * np.sum(mas_array)
        tdyn = 0.5 * np.pi * rq * np.sqrt(rq / mass_phy)

        return tdyn
Example #31
0
    def mass_enclosed(self, q, t=0.):
        """
        Estimate the mass enclosed within the given position by assuming the potential
        is spherical.

        Parameters
        ----------
        q : array_like, numeric
            Position to estimate the enclossed mass.

        Returns
        -------
        menc : `~astropy.units.Quantity`
            Mass enclosed at the given position(s). If the input position
            has shape ``q.shape``, the output energy will have shape
            ``q.shape[1:]``.
        """
        q = self._prefilter_pos(q)

        # small step-size in direction of q
        h = 1E-3  # MAGIC NUMBER

        # Radius
        r = np.sqrt(np.sum(q**2, axis=0))

        epsilon = h * q / r[np.newaxis]

        dPhi_dr_plus = self._value(q + epsilon, t=t)
        dPhi_dr_minus = self._value(q - epsilon, t=t)
        diff = (dPhi_dr_plus - dPhi_dr_minus)

        if isinstance(self.units, DimensionlessUnitSystem):
            Gee = 1.
        else:
            Gee = G.decompose(self.units).value

        return np.abs(r * r * diff / Gee / (2. * h)) * self.units['mass']
Example #32
0
    def __init__(self, galaxy, snap):
        # construct filename
        ilbl = '000' + str(snap)  # add string of filenumber to 000
        ilbl = ilbl[-3:]  # keep last 3 digits
        self.filename = '/home/agibbs/' + "%s_" % (galaxy) + ilbl + '.txt'

        # set delta for all com calculations
        self.comdel = 0.3  # too small a value may fail to converge and can result in an ERROR!!!

        # set G to correct units
        self.G = G.to(u.kpc * u.km**2 / u.s**2 / u.Msun)

        # store galaxy name (used to separate out M33 later)
        self.gname = galaxy

        # read in the file and particle type
        self.time, self.total, self.data = Read(self.filename)

        # store the mass, positions of all particle types
        self.m = self.data['m']

        self.x = self.data['x'] * u.kpc
        self.y = self.data['y'] * u.kpc
        self.z = self.data['z'] * u.kpc
Example #33
0
    def _read_units(self):
        """ Read and parse the SCFPAR file containing simulation parameters
            and initial conditions. Right now, only parse out the simulation
            units.
        """
        pars = dict()

        parfile = os.path.join(self.path, "SCFPAR")
        with open(parfile) as f:
            lines = f.readlines()

            # find what G is set to
            for i,line in enumerate(lines):
                if line.split()[1].strip() == "G":
                    break
            pars['G'] = float(lines[i].split()[0])
            pars['length'] = float(lines[i+10].split()[0])
            pars['mass'] = float(lines[i+11].split()[0])

            self.x0 = np.array(map(float, lines[19].split()))*u.kpc
            self.v0 = np.array(map(float, lines[20].split()))*u.km/u.s

        _G = G.decompose(bases=[u.kpc,u.M_sun,u.Myr]).value
        X = (_G / pars['length']**3 * pars['mass'])**-0.5

        length_unit = u.Unit("{0} kpc".format(pars['length']))
        mass_unit = u.Unit("{0} M_sun".format(pars['mass']))
        time_unit = u.Unit("{:08f} Myr".format(X))

        units = dict(length=length_unit,
                     mass=mass_unit,
                     time=time_unit,
                     speed=length_unit/time_unit,
                     dimensionless=u.dimensionless_unscaled)

        return units
Example #34
0
    def mass_enclosed(self, q, t=0.):
        """
        Estimate the mass enclosed within the given position by assuming the potential
        is spherical.

        Parameters
        ----------
        x : array_like, numeric
            Position to estimate the enclossed mass.

        Returns
        -------
        menc : `~numpy.ndarray`
            The mass. Will have the same shape as the input position,
            array, ``q``, but without the coordinate axis, ``axis=0``
        """

        q = np.ascontiguousarray(atleast_2d(q, insert_axis=1))

        # Fractional step-size in radius
        h = 0.01

        # Radius
        r = np.sqrt(np.sum(q**2, axis=0))

        epsilon = h*q/r[np.newaxis]

        dPhi_dr_plus = self.value(q + epsilon, t=t)
        dPhi_dr_minus = self.value(q - epsilon, t=t)
        diff = dPhi_dr_plus - dPhi_dr_minus

        if self.units is None:
            raise ValueError("No units specified when creating potential object.")
        Gee = G.decompose(self.units).value

        return np.abs(r*r * diff / Gee / (2.*h))
Example #35
0
    def mass_enclosed(self, q, t=0.):
        """
        Estimate the mass enclosed within the given position by assuming the potential
        is spherical.

        Parameters
        ----------
        x : array_like, numeric
            Position to estimate the enclossed mass.

        Returns
        -------
        menc : `~astropy.units.Quantity`
            The potential energy or value of the potential. If the input
            position has shape ``q.shape``, the output energy will have
            shape ``q.shape[1:]``.
        """
        q = self._prefilter_pos(q)

        # Fractional step-size in radius
        h = 0.01

        # Radius
        r = np.sqrt(np.sum(q**2, axis=0))

        epsilon = h*q/r[np.newaxis]

        dPhi_dr_plus = self.value(q + epsilon, t=t)
        dPhi_dr_minus = self.value(q - epsilon, t=t)
        diff = dPhi_dr_plus - dPhi_dr_minus

        if isinstance(self.units, DimensionlessUnitSystem):
            raise ValueError("No units specified when creating potential object.")
        Gee = G.decompose(self.units).value

        return np.abs(r*r * diff / Gee / (2.*h)) * self.units['mass']
Example #36
0
def isochrone_xv_to_aa(x, v, potential):
    """
    Transform the input cartesian position and velocity to action-angle
    coordinates in the Isochrone potential. See Section 3.5.2 in
    Binney & Tremaine (2008), and be aware of the errata entry for
    Eq. 3.225.

    This transformation is analytic and can be used as a "toy potential"
    in the Sanders & Binney (2014) formalism for computing action-angle
    coordinates in any potential.

    .. note::

        This function is included as a method of the :class:`~gary.potential.IsochronePotential`
        and it is recommended to call :meth:`~gary.potential.IsochronePotential.phase_space()`
        instead.

    # TODO: should accept quantities

    Parameters
    ----------
    x : array_like
        Cartesian positions. Must have shape (N,3) or (3,).
    v : array_like
        Cartesian velocities. Must have shape (N,3) or (3,).
    potential : :class:`gary.potential.IsochronePotential`
        An instance of the potential to use for computing the transformation
        to angle-action coordinates.

    Returns
    -------
    actions : :class:`numpy.ndarray`
        An array of actions computed from the input positions and velocities. Will
        always have shape (N,3) -- if input coordinates are 1D, the output shape will
        be (1,3).
    angles : :class:`numpy.ndarray`
        An array of angles computed from the input positions and velocities. Will
        always have shape (N,3) -- if input coordinates are 1D, the output shape will
        be (1,3).
    """

    x = np.atleast_2d(x)
    v = np.atleast_2d(v)

    _G = G.decompose(potential.units).value
    GM = _G*potential.parameters['m']
    b = potential.parameters['b']
    E = potential.total_energy(x, v)

    x = x * u.dimensionless_unscaled
    v = v * u.dimensionless_unscaled

    if np.any(E > 0.):
        raise ValueError("Unbound particle. (E = {})".format(E))

    # convert position, velocity to spherical polar coordinates
    x_rep = coord.CartesianRepresentation(x.T)
    x_rep = x_rep.represent_as(coord.PhysicsSphericalRepresentation)
    v_sph = cartesian_to_physicsspherical(x_rep, v.T)
    r,phi,theta = x_rep.r.value, x_rep.phi.value, x_rep.theta.value
    vr,vphi,vtheta = v_sph.value

    # ----------------------------
    # Actions
    # ----------------------------

    L_vec = angular_momentum(x,v)
    Lz = L_vec[:,2]
    L = np.linalg.norm(L_vec, axis=1)

    # Radial action
    Jr = GM / np.sqrt(-2*E) - 0.5*(L + np.sqrt(L*L + 4*GM*b))

    # compute the three action variables
    actions = np.array([Jr, Lz, L - np.abs(Lz)]).T

    # ----------------------------
    # Angles
    # ----------------------------
    c = GM / (-2*E) - b
    e = np.sqrt(1 - L*L*(1 + b/c) / GM / c)

    # Compute theta_r using eta
    tmp1 = r*vr / np.sqrt(-2.*E)
    tmp2 = b + c - np.sqrt(b*b + r*r)
    eta = np.arctan2(tmp1,tmp2)
    thetar = eta - e*c*np.sin(eta) / (c + b)  # same as theta3

    # Compute theta_z
    psi = np.arctan2(np.cos(theta), -np.sin(theta)*r*vtheta/L)
    psi[np.abs(vtheta) <= 1e-10] = np.pi/2.  # blows up for small vtheta

    omega = 0.5 * (1 + L/np.sqrt(L*L + 4*GM*b))

    a = np.sqrt((1+e) / (1-e))
    ap = np.sqrt((1 + e + 2*b/c) / (1 - e + 2*b/c))

    def F(x, y):
        z = np.zeros_like(x)

        ix = y>np.pi/2.
        z[ix] = np.pi/2. - np.arctan(np.tan(np.pi/2.-0.5*y[ix])/x[ix])

        ix = y<-np.pi/2.
        z[ix] = -np.pi/2. + np.arctan(np.tan(np.pi/2.+0.5*y[ix])/x[ix])

        ix = (y<=np.pi/2) & (y>=-np.pi/2)
        z[ix] = np.arctan(x[ix]*np.tan(0.5*y[ix]))
        return z

    A = omega*thetar - F(a,eta) - F(ap,eta)/np.sqrt(1 + 4*GM*b/L/L)
    thetaz = psi + A

    LR = Lz/L
    sinu = (LR/np.sqrt(1.-LR*LR)/np.tan(theta))
    sinu = sinu.value
    uu = np.arcsin(sinu)

    uu[sinu > 1.] = np.pi/2.
    uu[sinu < -1.] = -np.pi/2.
    uu[vtheta > 0.] = np.pi - uu[vtheta > 0.]

    thetap = phi - uu + np.sign(Lz)*thetaz
    angles = np.array([thetar, thetap, thetaz]).T
    angles %= (2*np.pi)

    return actions, angles
Example #37
0
def Lpts():
    np.random.seed(42)

    potential = LawMajewski2010()
    filename = os.path.join(plot_path, "Lpts_r.{}".format(ext))
    filename2 = os.path.join(plot_path, "Lpts_v.{}".format(ext))

    fig,axes = plt.subplots(2,4,figsize=grid_figsize,
                            sharex=True, sharey=True)
    fig2,axes2 = plt.subplots(2,4,figsize=grid_figsize,
                              sharex=True, sharey=True)

    bins = np.linspace(-3,3,50)
    nparticles = 2000
    for k,_m in enumerate(range(6,9+1)):
        mass = "2.5e{}".format(_m)
        m = float(mass)
        print(mass)

        sgr = SgrSimulation(sgr_path.format(_m),snapfile)
        p = sgr.particles(n=nparticles, expr=expr)
        s = sgr.satellite()
        dt = -1.

        coord, r_tide, v_disp = particles_x1x2x3(p, s,
                                                 sgr.potential,
                                                 sgr.t1, sgr.t2, dt,
                                                 at_tub=False)
        (x1,x2,x3,vx1,vx2,vx3) = coord
        ts = np.arange(sgr.t1,sgr.t2+dt,dt)
        t_idx = np.array([np.argmin(np.fabs(ts - t)) for t in p.tub])

        _tcross = r_tide / np.sqrt(G.decompose(usys).value*m/r_tide)
        for ii,jj in enumerate(t_idx):
            #tcross = r_tide[jj,0] / _v[jj,ii]
            tcross = _tcross[jj]
            bnd = int(tcross / 2)

            ix1,ix2 = jj-bnd, jj+bnd
            if ix1 < 0: ix1 = 0
            if ix2 > max(sgr.t1,sgr.t2): ix2 = -1

            axes[0,k].set_rasterization_zorder(1)
            axes[0,k].plot(x1[jj-bnd:jj+bnd,ii]/r_tide[jj-bnd:jj+bnd,0],
                           x2[jj-bnd:jj+bnd,ii]/r_tide[jj-bnd:jj+bnd,0],
                           linestyle='-', alpha=0.1, marker=None, color='#555555',
                           zorder=-1)

            axes[1,k].set_rasterization_zorder(1)
            axes[1,k].plot(x1[jj-bnd:jj+bnd,ii]/r_tide[jj-bnd:jj+bnd,0],
                           x3[jj-bnd:jj+bnd,ii]/r_tide[jj-bnd:jj+bnd,0],
                           linestyle='-', alpha=0.1, marker=None, color='#555555',
                           zorder=-1)

        circ = Circle((0,0), radius=1., fill=False, alpha=0.75,
                      edgecolor='k', linestyle='solid')
        axes[0,k].add_patch(circ)
        circ = Circle((0,0), radius=1., fill=False, alpha=0.75,
                     edgecolor='k', linestyle='solid')
        axes[1,k].add_patch(circ)

        axes[0,k].axhline(0., color='k', alpha=0.75)
        axes[1,k].axhline(0., color='k', alpha=0.75)

        axes[0,k].set_xlim(-5,5)
        axes[0,k].set_ylim(axes[0,k].get_xlim())

        axes[1,k].set_xlabel(r"$x_1/r_{\rm tide}$")

        if k == 0:
            axes[0,k].set_ylabel(r"$x_2/r_{\rm tide}$")
            axes[1,k].set_ylabel(r"$x_3/r_{\rm tide}$")

        _tcross = r_tide / np.sqrt(G.decompose(usys).value*m/r_tide)
        for ii,jj in enumerate(t_idx):
            #tcross = r_tide[jj,0] / _v[jj,ii]
            tcross = _tcross[jj]
            bnd = int(tcross / 2)

            ix1,ix2 = jj-bnd, jj+bnd
            if ix1 < 0: ix1 = 0
            if ix2 > max(sgr.t1,sgr.t2): ix2 = -1

            axes2[0,k].set_rasterization_zorder(1)
            axes2[0,k].plot(vx1[jj-bnd:jj+bnd,ii]/v_disp[jj-bnd:jj+bnd,0],
                            vx2[jj-bnd:jj+bnd,ii]/v_disp[jj-bnd:jj+bnd,0],
                            linestyle='-', alpha=0.1, marker=None, color='#555555',
                            zorder=-1)

            axes2[1,k].set_rasterization_zorder(1)
            axes2[1,k].plot(vx1[jj-bnd:jj+bnd,ii]/v_disp[jj-bnd:jj+bnd,0],
                            vx3[jj-bnd:jj+bnd,ii]/v_disp[jj-bnd:jj+bnd,0],
                            linestyle='-', alpha=0.1, marker=None, color='#555555',
                            zorder=-1)

        circ = Circle((0,0), radius=1., fill=False, alpha=0.75,
                      edgecolor='k', linestyle='solid')
        axes2[0,k].add_patch(circ)
        circ = Circle((0,0), radius=1., fill=False, alpha=0.75,
                      edgecolor='k', linestyle='solid')
        axes2[1,k].add_patch(circ)

        axes2[0,k].axhline(0., color='k', alpha=0.75)
        axes2[1,k].axhline(0., color='k', alpha=0.75)

        axes2[1,k].set_xlim(-5,5)
        axes2[1,k].set_ylim(axes2[1,k].get_xlim())

        axes2[1,k].set_xlabel(r"$v_{x_1}/\sigma_v$")

        if k == 0:
            axes2[0,k].set_ylabel(r"$v_{x_2}/\sigma_v$")
            axes2[1,k].set_ylabel(r"$v_{x_3}/\sigma_v$")

        axes[0,k].text(0.5, 1.05, r"$2.5\times10^{}M_\odot$".format(_m),
                       horizontalalignment='center',
                       fontsize=24,
                       transform=axes[0,k].transAxes)

        axes2[0,k].text(0.5, 1.05, r"$2.5\times10^{}M_\odot$".format(_m),
                        horizontalalignment='center',
                        fontsize=24,
                        transform=axes2[0,k].transAxes)

    fig.tight_layout()
    fig.subplots_adjust(top=0.92, hspace=0.025, wspace=0.1)
    fig.savefig(filename)

    fig2.tight_layout()
    fig2.subplots_adjust(top=0.92, hspace=0.025, wspace=0.1)
    fig2.savefig(filename2)
Example #38
0
def test_constants():
    usys = UnitSystem(u.kpc, u.Myr, u.radian, u.Msun)
    assert np.allclose(usys.get_constant('G'), G.decompose([u.kpc, u.Myr, u.radian, u.Msun]).value)
    assert np.allclose(usys.get_constant('c'), c.decompose([u.kpc, u.Myr, u.radian, u.Msun]).value)
Example #39
0
import numpy as np
import astropy.units as u
from astropy.constants import G

# import plotting modules
import matplotlib.pyplot as plt
import matplotlib

# my modules
from ReadFile import Read
from CenterOfMass import CenterOfMass


# Gravitational Constant
# converting G to units of kpc*km^2/s^2/Msun
G = G.to(u.kpc*u.km**2/u.s**2/u.Msun) # 4.498768e-6*u.kpc**3/u.Gyr**2/u.Msun


class MassProfile:
    # Class to define the Mass and Rotation Curve of a Galaxy
    
    def __init__(self, galaxy, snap):
    # Initialize the instance of this Class with the following properties:
    # galaxy :  string, e.g. "MW"
    #  snap :  integer, e.g  1
    
        # Determine Filename
        # add a string of the filenumber to the value "000"
        ilbl = '000' + str(snap)
        # remove all but the last 3 digits
        ilbl = ilbl[-3:]
Example #40
0
from ..core import CompositePotential
from ..cbuiltin import *
from ..io import load
from ...units import galactic, solarsystem

# HACK: bad solution is to do this:
# python setup.py build_ext --inplace

top_path = "plots/"
plot_path = os.path.join(top_path, "tests/potential/cpotential")
if not os.path.exists(plot_path):
    os.makedirs(plot_path)

units = [u.kpc,u.Myr,u.Msun,u.radian]
G = G.decompose(units)

print()
color_print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", "yellow")
color_print("To view plots:", "green")
print("    open {}".format(plot_path))
color_print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", "yellow")

niter = 1000
nparticles = 1000

class PotentialTestBase(object):
    name = None
    units = galactic

    def setup(self):
Example #41
0
 def __init__(self, m, a, units):
     self.parameters = dict(m=m, a=a)
     self.units = units
     self.G = G.decompose(units).value
def external_delta_sigma(galaxies, particles, rp_bins, period, projection_period,
        cosmology=default_cosmology):
    r"""
    Parameters
    ----------
    galaxies : array_like
        Ngal x 2 numpy array containing 2-d positions of galaxies.
        Length units are comoving and assumed to be in Mpc/h,
        here and throughout Halotools.

    particles : array_like
        Npart x 2 numpy array containing 2-d positions of particles.
        Length units are comoving and assumed to be in Mpc/h,
        here and throughout Halotools. Assumes constant particle masses, but can
        use weighted pair counts as scipy 0.19.0 is released.
        scipy.spatial.cKDTree will acquire a weighted pair count functionality

    rp_bins : array_like
        array of projected radial boundaries defining the bins in which the result is
        calculated.  The minimum of rp_bins must be > 0.0.
        Length units are comoving and assumed to be in Mpc/h,
        here and throughout Halotools.

    period : array_like
        Length-2 sequence defining the periodic boundary conditions
        in each dimension. If you instead provide a single scalar, Lbox,
        period is assumed to be the same in all Cartesian directions.
        Length units are comoving and assumed to be in Mpc/h,
        here and throughout Halotools.

    projection_period : float
        The period along the direction of projection

    cosmology : instance of `astropy.cosmology`, optional
        Default value is set in `~halotools.sim_manager.default_cosmology` module.
        Typically you should use the `cosmology` attribute of the halo catalog
        you used to populate mock galaxies.

    Returns
    -------
    rmids : np.array
        The bins at which :math:`\Delta\Sigma` is calculated.
        The units of `rmids` is :math:`hinv Mpc`, where distances are in comoving units.
        You can convert to physical units using the input cosmology and redshift.
        Note that little h = 1 here and throughout Halotools.

    Delta_Sigma : np.array
        :math:`\Delta\Sigma(r_p)` calculated at projected comoving radial distances ``rp_bins``.
        The units of `ds` are :math:`h * M_{\odot} / Mpc^2`, where distances are in comoving units.
        You can convert to physical units using the input cosmology and redshift.
        Note that little h = 1 here and throughout Halotools.

    Notes
    -----
    :math:`\Delta\Sigma` is calculated by first calculating the projected
    surface density :math:`\Sigma` using the particles passed to the code

    and then,

    .. math::

        \Delta\Sigma(r_p) = \bar{\Sigma}(<r_p) - \Sigma(r_p)
    """

    from scipy.spatial import cKDTree
    from astropy.constants import G

    Ngal = float(galaxies.shape[0])
    Npart = float(particles.shape[0])
    if np.isscalar(period):
        Area = period**2
    else:
        Area = period[0] * period[1]

    tree = cKDTree(galaxies, boxsize=period)
    ptree = cKDTree(particles, boxsize=period)
    pairs_inside_rad = tree.count_neighbors(ptree, rp_bins)

    pairs_in_annuli = np.diff(pairs_inside_rad)

    # rhobar = 3H0^2/(8 pi G) Om0
    rhobar = 3.e4/(8*np.pi*G.to('km^2 Mpc/(s^2 Msun)').value)*cosmology.Om0

    sigmabar = rhobar*projection_period

    # This initializes sigma(rmids)
    rmids = rp_bins[1:]/2+rp_bins[:-1]/2
    xi2d = pairs_in_annuli/(Ngal*Npart/Area*(np.pi*(rp_bins[1:]**2-rp_bins[:-1]**2))) - 1.0
    sigma = sigmabar*xi2d

    # Now initialize sigmainside(rp_bins)
    xi2dinside = pairs_inside_rad/(Npart*Ngal/Area*(np.pi*rp_bins**2)) - 1.0
    sigmainside = sigmabar*xi2dinside

    from scipy.interpolate import interp1d
    spl = interp1d(np.log(rp_bins), np.log(sigmainside), kind="cubic")

    return rmids, np.exp(spl(np.log(rmids)))-sigma
Example #43
0
# -*- coding: utf-8 -*-
"""
This provides a few useful units for this package using astropy units
"""
import numpy as np
import os

__author__ = "Eric Emsellem"
__copyright__ = "Eric Emsellem"
__license__ = "mit"

from astropy import units as u
from astropy.constants import G as Ggrav_cgs

Ggrav = Ggrav_cgs.to(u.km**2 * u.pc / u.s**2 / u.M_sun)
# Defining our default units
pixel = u.pixel
Lsun = u.Lsun
Msun = u.Msun
Lsunpc2 = Lsun / u.pc**2
Msunpc2 = Msun / u.pc**2
kms = u.km / u.s
kmskpc = u.km / u.s / u.kpc
kms2 = (u.km / u.s)**2
km_pc = u.pc.to(u.km)
s_yr = u.yr.to(u.s)


def get_conversion_factor(unit, newunit, equiv=[], verbose=True):
    """Get the conversion factor for astropy units
Example #44
0
package developed by Benedikt Diemer, http://bdiemer.bitbucket.org.

Testing for this module is done in the
`~halotools.empirical_models.test_profile_helpers` module.

"""
from __future__ import division, print_function, absolute_import, unicode_literals

import numpy as np
from astropy import cosmology as astropy_cosmology_obj
from astropy import units as u
from astropy.constants import G

from ....custom_exceptions import HalotoolsError

newtonG = G.to(u.km*u.km*u.Mpc/(u.Msun*u.s*u.s))

__all__ = ('density_threshold', 'delta_vir', 'halo_mass_to_halo_radius',
           'halo_radius_to_halo_mass', 'halo_mass_to_virial_velocity')

__author__ = ['Benedikt Diemer', 'Andrew Hearin']


def density_threshold(cosmology, redshift, mdef):
    """
    The threshold density for a given spherical-overdensity mass definition.

    :math:`\\rho_{\\rm thresh}(z) = \\Delta_{\\rm ref}(z)\\rho_{\\rm ref}(z)`.

    See :ref:`halo_mass_definitions` for details.
Example #45
0
    def __init__(self,R,dens,rc=1,Mmax=1, G='kpc km2 / (M_sun s2)', denorm=True, use_c=False):
        """
        The purpose of the general model is to start from a density law R-dens to build a galaxy model.
        Attenzione per come è creato il modello assume sempre che
        per R>rmax la densita sia 0, la massa resti costante al suo valore massimo e il potenziale vada
        come M/r. Per modelli che raggiungono la massa massima all infinito questo potrebbe essere un problema,
        quindi si dovrebbero usare modelli con massa finita o troncarli e campionarli fino a quanto la massa non raggiunge
        il suo valore max. Per modelli non troncati è meglio utilizzare modelli analitici se possibile.
        Anche nel calcolo del potenziale Rinf è settato uguale all ultimo punto di R, poichè cmq per R>Rmax
        dens=0 e l integrale int_Rmax^inf dens r dr=0 sempre.
        :param R: list of radii, it needs to  be in the form  r/rc
        :param dens: list of dens at radii R. It can be also a function or a lambda function that depends
                     only on the variable R=r/rc
        :param rc: Scale length of the model, the R in input will be multiplyed by rc before start all the calculation
        :param Mmax: Physical Value of the Mass at Rmax (the last point of the R grid). The physical unity of dens and pot and mass
               will depends on the unity of Mmax
        :param G: Value of the gravitational constant G, it can be a number of a string.
                    If G=1, the physical value of the potential will be Phi/G.
                    If string it must follow the rule of the unity of the module.astropy constants.
                    E.g. to have G in unit of kpc3/Msun s2, the input string is 'kpc3 / (M_sun s2)'
                    See http://astrofrog-debug.readthedocs.org/en/latest/constants/
        :param denorm: If True, the output value of mass, dens and pot will be de normalized using Mmax and G.
        :param use_c: To calculate pot and mass with a C-cyle, WARNING it creates more noisy results
        """

        self.rc=rc
        self.Mmax=Mmax
        if isinstance(G,float) or isinstance(G,int): self.G=G
        else:
            GG=conG.to(G)
            self.G=GG.value


        if isinstance(dens,list) or isinstance(dens,tuple) or isinstance(dens,np.ndarray):  self.dens_arr=np.array(dens,dtype=float,order='C')
        else:
            self.dens_arr=dens(R)

        self.R=np.array(R,dtype=float,order='C')*self.rc
        self.mass_arr=np.empty_like(self.dens_arr,dtype=float,order='C')
        self.pot_arr=np.empty_like(self.dens_arr,dtype=float,order='C')
        self.use_c=use_c
        self._use_nparray=False

        self._dens=UnivariateSpline(self.R,self.dens_arr, k=1, s=0, ext=1) #for R>rmax, dens=0

        if self.use_c==True:
            #add to path to use relative path
            dll_name='model_c_ext/GeneralModel.so'
            dllabspath = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + dll_name
            lib = ct.CDLL(dllabspath)
            #add to path to use relativ path
            mass_func=lib.evalmass
            mass_func.restype=None
            mass_func.argtypes=[ndpointer(ct.c_double, flags="C_CONTIGUOUS"), ndpointer(ct.c_double, flags="C_CONTIGUOUS"),ct.c_int,ndpointer(ct.c_double, flags="C_CONTIGUOUS")]
            mass_func(self.R,self.dens_arr,len(self.dens_arr),self.mass_arr)
            self._mass_int=UnivariateSpline(self.R,self.mass_arr, k=1, s=0, ext=3) #ext=3, const for R>Rmax non ci osno piu particelle e la massa rimane uguale



            pot_func=lib.evalpot
            pot_func.restype=None
            pot_func.argtypes=[ndpointer(ct.c_double, flags="C_CONTIGUOUS"),ndpointer(ct.c_double, flags="C_CONTIGUOUS"),ndpointer(ct.c_double, flags="C_CONTIGUOUS"),ct.c_int,ndpointer(ct.c_double, flags="C_CONTIGUOUS")]
            pot_func(self.R,self.dens_arr,self.mass_arr,len(self.dens_arr),self.pot_arr)
            self._pot_int=UnivariateSpline(self.R,self.pot_arr, k=1, s=0, ext=1)



        else:
            self._dm2=UnivariateSpline(self.R,self.R*self.R*self.dens_arr, k=2, s=0,ext=1)
            self._dm=UnivariateSpline(self.R,self.R*self.dens_arr, k=1, s=0,ext=1)


            #Evaluate mass and pot on the R grid in input
            #mass
            func=np.vectorize(self._dm2.integral)
            self.mass_arr=func(0,self.R)

            #pot
            a=(1/self.R)*self.mass_arr
            func=np.vectorize(self._dm.integral)
            b=func(self.R,self.R[-1])
            self.pot_arr=a+b

        if denorm==True: self._set_denorm(self.Mmax)
        else:
            self.Mc=1
            self.dc=1
            self.pc=1
Example #46
0
#!/usr/bin/env python
# coding: utf-8

# In[1]:

# inputs
import numpy as np
import astropy.units as u
import astropy.table as tbl
import matplotlib.pyplot as plt
from Readfile import Read
from CenterOfMass import CenterOfMass as COM
from astropy.constants import G
# convert G to correct units
G = G.to(u.kpc * u.km**2 / u.s**2 / u.Msun)


# create class MassProfile
class MassProfile:
    # Class to define the mass profile of a galaxy at a snapshot time

    def __init__(self, galaxy, snap):

        # inputs:
        #       galaxy: a string with galaxy name, such as "MW" or "M31"
        #       snap:  the snapshot number, such as 0, 1, etc

        # Initialize instance of this class with the following properties:

        # store the name of the galaxy
        self.gname = galaxy
Example #47
0
import matplotlib.pyplot as plt
import numpy as np
import scipy.interpolate as inter
from astropy import log as logger
logger.setLevel(logging.DEBUG)
from astropy.constants import G

# Stream-Team
import streamteam.integrate as si
from streamteam.potential.lm10 import LM10Potential
from streamteam.potential.apw import PW14Potential
from streamteam.dynamics.actionangle import find_actions, fit_isochrone
from streamteam.potential import IsochronePotential
from streamteam.units import galactic

G = G.decompose(galactic).value

cache_path = "/home/spearson/Hessian/stream-team/hessian"

#---------------------- We want to check both LM10() triax & LM10(q1=1,q2=1,q3=1)-------------------------

#---------------------Hessian test - APW-----------------#
ppars = {'a': 6.5,
         'b': 0.26,
         'c': 0.3,
         'm_disk': 65000000000.0,
         'm_spher': 20000000000.0,
         'phi': 1.570796,
         'psi': 1.570796,
         'q1': 1.3,
         'q2': 1.0,
Example #48
0
def q_p(**kwargs):

    filename = os.path.join(plot_path, "q_p.pdf")
    fig,axes = plt.subplots(2,4,figsize=(14,7.5),
                            sharex=True, sharey=True)

    bins = np.linspace(0.,10,40)
    nparticles = 5000
    for kk,_m in enumerate(range(6,9+1)):
        mass = "2.5e{}".format(_m)
        m = float(mass)
        print(mass)

        sgr = SgrSimulation(sgr_path.format(_m), snapfile)
        p = sgr.particles(n=nparticles, expr="(tub!=0)")#" & (tub<400)")
        tub = p.tub
        s = sgr.satellite()

        potential = LawMajewski2010()

        X = np.vstack((s._X[...,:3], p._X[...,:3].copy()))
        V = np.vstack((s._X[...,3:], p._X[...,3:].copy()))
        integrator = LeapfrogIntegrator(potential._acceleration_at,
                                        np.array(X), np.array(V),
                                        args=(X.shape[0], np.zeros_like(X)))
        ts, rs, vs = integrator.run(t1=sgr.t1, t2=sgr.t2, dt=-1.)

        s_orbit = np.vstack((rs[:,0][:,np.newaxis].T, vs[:,0][:,np.newaxis].T)).T
        p_orbits = np.vstack((rs[:,1:].T, vs[:,1:].T)).T
        t_idx = np.array([np.argmin(np.fabs(ts - t)) for t in p.tub])

        p_x = np.array([p_orbits[jj,ii] for ii,jj in enumerate(t_idx)])
        s_x = np.array([s_orbit[jj,0] for jj in t_idx])

        #############################################
        # determine tail_bit
        diff = p_x-s_x
        norm_r = s_x[:,:3] / np.sqrt(np.sum(s_x[:,:3]**2, axis=-1))[:,np.newaxis]
        norm_diff_r = diff[:,:3] / np.sqrt(np.sum(diff[:,:3]**2, axis=-1))[:,np.newaxis]
        dot_prod_r = np.sum(norm_diff_r*norm_r, axis=-1)
        tail_bit = (dot_prod_r > 0.).astype(int)*2 - 1
        #############################################

        r_tide = potential._tidal_radius(m, s_orbit[...,:3])#*0.69336
        s_R_orbit = np.sqrt(np.sum(s_orbit[...,:3]**2, axis=-1))
        a_pm = (s_R_orbit + r_tide*tail_bit) / s_R_orbit
        q = np.sqrt(np.sum((p_x[:,:3] - s_x[:,:3])**2,axis=-1))

        f = r_tide / s_R_orbit
        s_V = np.sqrt(np.sum(s_orbit[...,3:]**2, axis=-1))
        vdisp = s_V * f / 1.4
        p = np.sqrt(np.sum((p_x[:,3:] - s_x[...,3:])**2,axis=-1))

        fig,axes = plt.subplots(2,1,figsize=(10,6),sharex=True)

        axes[0].plot(tub, q, marker='.', alpha=0.5, color='#666666')
        axes[0].plot(ts, r_tide*1.4, linewidth=2., alpha=0.8, color='k',
                     linestyle='-', marker=None)
        axes[0].set_ylim(0., max(r_tide)*4)

        axes[1].plot(tub, (p*u.kpc/u.Myr).to(u.km/u.s).value,
                     marker='.', alpha=0.5, color='#666666')
        axes[1].plot(ts, (vdisp*u.kpc/u.Myr).to(u.km/u.s).value, color='k',
                     linewidth=2., alpha=0.75, linestyle='-', marker=None)

        M_enc = potential._enclosed_mass(s_R_orbit)
        #delta_E = 4/3.*G.decompose(usys).value**2*m*(M_enc / s_V)**2*r_tide**2/s_R_orbit**4
        delta_v2 = 4/3.*G.decompose(usys).value**2*(M_enc / s_V)**2*\
                        np.mean(r_tide**2)/s_R_orbit**4
        delta_v = (np.sqrt(2*delta_v2)*u.kpc/u.Myr).to(u.km/u.s).value

        axes[1].plot(ts, delta_v, linewidth=2., color='#2166AC',
                     alpha=0.75, linestyle='--', marker=None)

        axes[1].set_ylim(0., max((vdisp*u.kpc/u.Myr).to(u.km/u.s).value)*4)

        axes[0].set_xlim(min(ts), max(ts))

        fig.savefig(os.path.join(plot_path, "q_p_{}.png".format(mass)),
                    transparent=True)
Example #49
0
# coding: utf-8

from __future__ import division, print_function

__author__ = "adrn <*****@*****.**>"

# Third-party
import astropy.units as u
from astropy.constants import G as _G
G = _G.decompose([u.kpc,u.Myr,u.Msun]).value
import numpy as np
import gary.potential as gp
from gary.units import galactic

# Project
from .._bfe import SCFPotential

def test_hernquist():
    nmax = 6
    lmax = 2

    M = 1E10
    r_s = 3.5

    cos_coeff = np.zeros((nmax+1,lmax+1,lmax+1))
    sin_coeff = np.zeros((nmax+1,lmax+1,lmax+1))
    cos_coeff[0,0,0] = 1.
    scf_potential = SCFPotential(m=M, r_s=r_s,
                                 Snlm=cos_coeff, Tnlm=sin_coeff,
                                 units=galactic)
Example #50
0
def isochrone_aa_to_xv(actions, angles, potential):
    """
    Transform the input actions and angles to ordinary phase space (position
    and velocity) in cartesian coordinates. See Section 3.5.2 in
    Binney & Tremaine (2008), and be aware of the errata entry for
    Eq. 3.225.

    .. note::

        This function is included as a method of the :class:`~gary.potential.IsochronePotential`
        and it is recommended to call :meth:`~gary.potential.IsochronePotential.action_angle()`
        instead.

    # TODO: should accept quantities

    Parameters
    ----------
    actions : array_like
        Action variables. Must have shape (N,3) or (3,).
    angles : array_like
        Angle variables. Must have shape (N,3) or (3,). Should be in radians.
    potential : :class:`gary.potential.IsochronePotential`
        An instance of the potential to use for computing the transformation
        to angle-action coordinates.

    Returns
    -------
    x : :class:`numpy.ndarray`
        An array of cartesian positions computed from the input angles and actions. Will
        always have shape (N,3) -- if input coordinates are 1D, the output shape will
        be (1,3).
    v : :class:`numpy.ndarray`
        An array of cartesian velocities computed from the input angles and actions. Will
        always have shape (N,3) -- if input coordinates are 1D, the output shape will
        be (1,3).

    """

    actions = np.atleast_2d(actions)
    angles = np.atleast_2d(angles)

    _G = G.decompose(potential.units).value
    GM = _G*potential.parameters['m']
    b = potential.parameters['b']

    # actions
    Jr = actions[:,0]
    Lz = actions[:,1]
    L = actions[:,2] + np.abs(Lz)

    # angles
    theta_r,theta_phi,theta_theta = angles.T

    # get longitude of ascending node
    theta_1 = theta_phi - np.sign(Lz)*theta_theta
    Omega = theta_1

    # Ly = -np.cos(Omega) * np.sqrt(L**2 - Lz**2)
    # Lx = np.sqrt(L**2 - Ly**2 - Lz**2)
    cosi = Lz/L
    sini = np.sqrt(1 - cosi**2)

    # Hamiltonian (energy)
    H = -2. * GM**2 / (2.*Jr + L + np.sqrt(4.*b*GM + L**2))**2

    if np.any(H > 0.):
        raise ValueError("Unbound particle. (E = {})".format(H))

    # Eq. 3.240
    c = -GM / (2.*H) - b
    e = np.sqrt(1 - L*L*(1 + b/c) / GM / c)

    # solve for eta
    theta_3 = theta_r
    eta_func = lambda x: x - e*c/(b+c)*np.sin(x) - theta_3
    eta_func_prime = lambda x: 1 - e*c/(b+c)*np.cos(x)

    # use newton's method to find roots
    niter = 100
    eta = np.ones_like(theta_3)*np.pi/2.
    for i in range(niter):
        eta -= eta_func(eta)/eta_func_prime(eta)

    # TODO: when to do this???
    eta -= 2*np.pi

    r = c*np.sqrt((1-e*np.cos(eta)) * (1-e*np.cos(eta) + 2*b/c))
    vr = np.sqrt(GM/(b+c))*(c*e*np.sin(eta))/r

    theta_2 = theta_theta
    Omega_23 = 0.5*(1 + L / np.sqrt(L**2 + 4*GM*b))

    a = np.sqrt((1+e) / (1-e))
    ap = np.sqrt((1 + e + 2*b/c) / (1 - e + 2*b/c))

    def F(x, y):
        z = np.zeros_like(x)

        ix = y>np.pi/2.
        z[ix] = np.pi/2. - np.arctan(np.tan(np.pi/2.-0.5*y[ix])/x[ix])

        ix = y<-np.pi/2.
        z[ix] = -np.pi/2. + np.arctan(np.tan(np.pi/2.+0.5*y[ix])/x[ix])

        ix = (y<=np.pi/2) & (y>=-np.pi/2)
        z[ix] = np.arctan(x[ix]*np.tan(0.5*y[ix]))
        return z

    theta_2[Lz < 0] -= 2*np.pi
    theta_3 -= 2*np.pi
    A = Omega_23*theta_3 - F(a,eta) - F(ap,eta)/np.sqrt(1 + 4*GM*b/L/L)
    psi = theta_2 - A

    # theta
    theta = np.arccos(np.sin(psi)*sini)
    vtheta = L*sini*np.cos(psi)/np.cos(theta)
    vtheta = -L*sini*np.cos(psi)/np.sin(theta)/r
    vphi = Lz / (r*np.sin(theta))

    # phi
    sinu = np.sin(psi)*cosi/np.sin(theta)

    uu = np.arcsin(sinu)
    uu[sinu > 1.] = np.pi/2.
    uu[sinu < -1.] = -np.pi/2.
    uu[vtheta > 0.] = np.pi - uu[vtheta > 0.]

    sinu = cosi/sini * np.cos(theta)/np.sin(theta)
    phi = (uu + Omega) % (2*np.pi)

    # We now need to convert from spherical polar coord to cart. coord.
    pos = coord.PhysicsSphericalRepresentation(r=r*u.dimensionless_unscaled,
                                               phi=phi*u.rad, theta=theta*u.rad)
    x = pos.represent_as(coord.CartesianRepresentation).xyz.T.value
    v = physicsspherical_to_cartesian(pos, [vr,vphi,vtheta]*u.dimensionless_unscaled).T.value
    return x,v
Example #51
0
def test_compose_into_arbitrary_units():
    # Issue #1438
    from astropy.constants import G
    G.decompose([u.kg, u.km, u.Unit("15 s")])
Example #52
0
from matplotlib import animation
import matplotlib.pyplot as plt
import numpy as np
from astropy.constants import G
import astropy.units as u
from scipy.signal import argrelmin
from streamteam.integrate import DOPRI853Integrator
from streamteam.dynamics import lyapunov

# Create logger
logger = logging.getLogger(__name__)

plot_path = "plots"

usys = [u.kpc, u.Myr, u.radian, u.M_sun]
_G = G.decompose(usys).value
# standard prolate:
prolate_params = (_G, 1.63E11, 3., 6., 0.2,
                  5.8E9, 0.25,
                  0.204542433, 0.5, 8.5)

# standard oblate:
oblate_params = (_G, 1.63E11, 3., 6., 0.2,
                 5.8E9, 0.25,
                 0.204542433, 1.5, 8.5)

def zotos_potential(R, z, G, Md, alpha, b, h, Mn, cn, v0, beta, ch):
    Rsq = R*R

    Vd = -G*Md / np.sqrt(b**2 + Rsq + (alpha + np.sqrt(h**2+z**2))**2)
    Vn = -G*Mn / np.sqrt(Rsq+z**2+cn**2)
Example #53
0
"""
from __future__ import division, print_function, absolute_import, unicode_literals

import numpy as np
import six
from abc import ABCMeta, abstractmethod
from scipy.integrate import quad as quad_integration
from scipy.optimize import minimize as scipy_minimize
from astropy import units as u
from astropy.constants import G

from . import halo_boundary_functions

from ... import model_defaults

newtonG = G.to(u.km * u.km * u.Mpc / (u.Msun * u.s * u.s))

__author__ = ["Andrew Hearin", "Benedikt Diemer"]

__all__ = ["AnalyticDensityProf"]


@six.add_metaclass(ABCMeta)
class AnalyticDensityProf(object):
    r""" Container class for any analytical radial profile model.

    See :ref:`profile_template_tutorial` for a review of the mathematics of
    halo profiles, and a thorough description of how the relevant equations
    are implemented in the `AnalyticDensityProf` source code.

    Notes
Example #54
0
# Standard library
from collections import OrderedDict

# Third party
import pytest
import numpy as np
from astropy.constants import G
import astropy.units as u
from matplotlib import cm

# This package
from ..core import PotentialBase, CompositePotential
from ....units import UnitSystem

units = [u.kpc, u.Myr, u.Msun, u.radian]
G = G.decompose(units)

def test_new_simple():

    class MyPotential(PotentialBase):
        def __init__(self, units=None):
            super(MyPotential, self).__init__(parameters={},
                                              units=units)

        def _energy(self, r, t=0.):
            return -1/r

        def _gradient(self, r, t=0.):
            return r**-2

    p = MyPotential()
Example #55
0
# Third-party
import astropy.units as u
from astropy.constants import G as _G
import numpy as np
import pytest

# Project
from gala._cconfig import GSL_ENABLED
from gala.units import galactic
import gala.potential as gp
from gala.potential.potential.tests.helpers import PotentialTestBase
from gala.potential.potential.io import load
from .. import _bfe_class

G = _G.decompose(galactic).value

if not GSL_ENABLED:
    pytest.skip("skipping SCF tests: they depend on GSL",
                allow_module_level=True)


def test_hernquist():
    nmax = 6
    lmax = 2

    M = 1E10
    r_s = 3.5

    cos_coeff = np.zeros((nmax+1,lmax+1,lmax+1))
    sin_coeff = np.zeros((nmax+1,lmax+1,lmax+1))
Example #56
0
    elif args.quiet:
        logger.setLevel(logging.ERROR)
    else:
        logger.setLevel(logging.INFO)

    # Contains user-specified parameters for SCF
    scfpars = dict()

    if args.rscale is None:
        ru = 0.43089*(args.mass/2.5e9)**(1/3.)
    else:
        ru = args.rscale
    scfpars['rscale'] = ru
    scfpars['mass'] = args.mass

    _G = G.decompose(bases=[u.kpc,u.M_sun,u.Myr]).value
    X = (_G / ru**3 * args.mass)**-0.5

    length_unit = u.Unit("{0} kpc".format(ru))
    mass_unit = u.Unit("{0} M_sun".format(args.mass))
    time_unit = u.Unit("{:08f} Myr".format(X))

    scfpars['dt'] = args.dt / (1*time_unit).to(u.Myr).value
    scfpars['nsteps'] = args.nsteps
    scfpars['ncen'] = args.ncen
    scfpars['nsnap'] = args.nsnap
    scfpars['ntide'] = args.ntide
    if args.scfbi_path is None:
        scfpars['SCFBIpath'] = os.path.abspath(os.path.join(project_path, 'src', 'SCFBI'))

    main(name=args.name, pos=args.x, vel=args.v, scfpars=scfpars,
Example #57
0
def total_rv():

    filenamer = os.path.join(plot_path, "rel_r.png")
    filenamev = os.path.join(plot_path, "rel_v.png")

    figr,axesr = plt.subplots(4,1,figsize=(10,14),
                              sharex=True)
    figv,axesv = plt.subplots(4,1,figsize=(10,14),
                              sharex=True)

    nparticles = 2000
    for k,_m in enumerate(range(6,9+1)):
        mass = "2.5e{}".format(_m)
        m = float(mass)
        print(mass)

        sgr = SgrSimulation(sgr_path.format(_m),snapfile)
        p = sgr.particles(n=nparticles, expr=expr)
        s = sgr.satellite()

        X = np.vstack((s._X[...,:3], p._X[...,:3].copy()))
        V = np.vstack((s._X[...,3:], p._X[...,3:].copy()))
        integrator = LeapfrogIntegrator(sgr.potential._acceleration_at,
                                        np.array(X), np.array(V),
                                        args=(X.shape[0], np.zeros_like(X)))
        ts, rs, vs = integrator.run(t1=sgr.t1, t2=sgr.t2, dt=-1.)

        s_orbit = np.vstack((rs[:,0][:,np.newaxis].T, vs[:,0][:,np.newaxis].T)).T
        p_orbits = np.vstack((rs[:,1:].T, vs[:,1:].T)).T
        t_idx = np.array([np.argmin(np.fabs(ts - t)) for t in p.tub])

        m_t = (-s.mdot*ts + s.m0)[:,np.newaxis]
        s_R = np.sqrt(np.sum(s_orbit[...,:3]**2, axis=-1))
        s_V = np.sqrt(np.sum(s_orbit[...,3:]**2, axis=-1))
        r_tide = sgr.potential._tidal_radius(m_t, s_orbit[...,:3])
        v_disp = s_V * r_tide / s_R

        # cartesian basis to project into
        x_hat = s_orbit[...,:3] / np.sqrt(np.sum(s_orbit[...,:3]**2, axis=-1))[...,np.newaxis]
        _y_hat = s_orbit[...,3:] / np.sqrt(np.sum(s_orbit[...,3:]**2, axis=-1))[...,np.newaxis]
        z_hat = np.cross(x_hat, _y_hat)
        y_hat = -np.cross(x_hat, z_hat)

        # translate to satellite position
        rel_orbits = p_orbits - s_orbit
        rel_pos = rel_orbits[...,:3]
        rel_vel = rel_orbits[...,3:]

        # project onto each
        X = np.sum(rel_pos * x_hat, axis=-1)
        Y = np.sum(rel_pos * y_hat, axis=-1)
        Z = np.sum(rel_pos * z_hat, axis=-1)
        RR = np.sqrt(X**2 + Y**2 + Z**2)

        VX = np.sum(rel_vel * x_hat, axis=-1)
        VY = np.sum(rel_vel * y_hat, axis=-1)
        VZ = np.sum(rel_vel * z_hat, axis=-1)
        VV = (np.sqrt(VX**2 + VY**2 + VZ**2)*u.kpc/u.Myr).to(u.km/u.s).value
        v_disp = (v_disp*u.kpc/u.Myr).to(u.km/u.s).value

        _tcross = r_tide / np.sqrt(G.decompose(usys).value*m/r_tide)
        for ii,jj in enumerate(t_idx):
            #tcross = r_tide[jj,0] / _v[jj,ii]
            tcross = _tcross[jj]
            bnd = int(tcross / 2)

            ix1,ix2 = jj-bnd, jj+bnd
            if ix1 < 0: ix1 = 0
            if ix2 > max(sgr.t1,sgr.t2): ix2 = -1
            axesr[k].plot(ts[ix1:ix2],
                          RR[ix1:ix2,ii],
                          linestyle='-', alpha=0.1, marker=None, color='#555555', zorder=-1)

            axesv[k].plot(ts[ix1:ix2],
                          VV[ix1:ix2,ii],
                          linestyle='-', alpha=0.1, marker=None, color='#555555', zorder=-1)

        axesr[k].plot(ts, r_tide*2., marker=None)

        axesr[k].set_xlim(ts.min(), ts.max())
        axesv[k].set_xlim(ts.min(), ts.max())

        axesr[k].set_ylim(0,max(r_tide)*7)
        axesv[k].set_ylim(0,max(v_disp)*7)

        # axes[1,k].set_xlabel(r"$x_1$")

        # if k == 0:
        #     axes[0,k].set_ylabel(r"$x_2$")
        #     axes[1,k].set_ylabel(r"$x_3$")

        axesr[k].text(3000, max(r_tide)*5, r"$2.5\times10^{}M_\odot$".format(_m))
        axesv[k].text(3000, max(v_disp)*5, r"$2.5\times10^{}M_\odot$".format(_m))

    axesr[-1].set_xlabel("time [Myr]")
    axesv[-1].set_xlabel("time [Myr]")

    figr.suptitle("Relative distance", fontsize=26)
    figr.tight_layout()
    figr.subplots_adjust(top=0.92, hspace=0.025, wspace=0.1)
    figr.savefig(filenamer)

    figv.suptitle("Relative velocity", fontsize=26)
    figv.tight_layout()
    figv.subplots_adjust(top=0.92, hspace=0.025, wspace=0.1)
    figv.savefig(filenamev)
Example #58
0
def test_constants():
    usys = UnitSystem(u.kpc, u.Myr, u.radian, u.Msun)
    assert np.allclose(usys.get_constant('G'),
                       G.decompose([u.kpc, u.Myr, u.radian, u.Msun]).value)
    assert np.allclose(usys.get_constant('c'),
                       c.decompose([u.kpc, u.Myr, u.radian, u.Msun]).value)
Example #59
0
    elif args.quiet:
        logger.setLevel(logging.ERROR)
    else:
        logger.setLevel(logging.INFO)

    # Contains user-specified parameters for SCF
    scfpars = dict()

    if args.rscale is None:
        ru = 0.43089 * (args.mass / 2.5e9)**(1 / 3.)
    else:
        ru = args.rscale
    scfpars['rscale'] = ru
    scfpars['mass'] = args.mass

    _G = G.decompose(bases=[u.kpc, u.M_sun, u.Myr]).value
    X = (_G / ru**3 * args.mass)**-0.5

    length_unit = u.Unit("{0} kpc".format(ru))
    mass_unit = u.Unit("{0} M_sun".format(args.mass))
    time_unit = u.Unit("{:08f} Myr".format(X))

    scfpars['dt'] = args.dt / (1 * time_unit).to(u.Myr).value
    scfpars['nsteps'] = args.nsteps
    scfpars['ncen'] = args.ncen
    scfpars['nsnap'] = args.nsnap
    scfpars['ntide'] = args.ntide
    if args.scfbi_path is None:
        scfpars['SCFBIpath'] = os.path.abspath(
            os.path.join(project_path, 'src', 'SCFBI'))