Ejemplo n.º 1
0
def get_potential(log_M_h, log_r_s, log_M_n, log_a):
    mw_potential = gp.CCompositePotential()
    mw_potential['bulge'] = gp.HernquistPotential(m=5E9, c=1., units=galactic)
    mw_potential['disk'] = gp.MiyamotoNagaiPotential(m=6.8E10 * u.Msun,
                                                     a=3 * u.kpc,
                                                     b=280 * u.pc,
                                                     units=galactic)
    mw_potential['nucl'] = gp.HernquistPotential(m=np.exp(log_M_n),
                                                 c=np.exp(log_a) * u.pc,
                                                 units=galactic)
    mw_potential['halo'] = gp.NFWPotential(m=np.exp(log_M_h),
                                           r_s=np.exp(log_r_s),
                                           units=galactic)

    return mw_potential
Ejemplo n.º 2
0
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 = _bfe_class.SCFPotential(m=M, r_s=r_s,
                                           Snlm=cos_coeff, Tnlm=sin_coeff,
                                           units=galactic)
    # scf_potential = HackPotential(m=10., units=galactic)

    nbins = 128
    rr = np.linspace(0.1,10.,nbins)
    xyz = np.zeros((3,nbins))
    xyz[0] = rr * np.cos(np.pi/4.) * np.sin(np.pi/4.)
    xyz[1] = rr * np.sin(np.pi/4.) * np.sin(np.pi/4.)
    xyz[2] = rr * np.cos(np.pi/4.)

    hernquist = gp.HernquistPotential(m=M, c=r_s, units=galactic)

    bfe_pot = scf_potential.energy(xyz).value
    true_pot = hernquist.energy(xyz).value
    np.testing.assert_allclose(bfe_pot, true_pot)

    bfe_grad = scf_potential.gradient(xyz).value
    true_grad = hernquist.gradient(xyz).value
    np.testing.assert_allclose(bfe_grad, true_grad)
Ejemplo n.º 3
0
def get_potential(total_mass = 130.0075e10*u.Msun,\
                  r_scale = 18.927757889861788 * u.kpc,\
                  mw_conc = 9.39):

    a_term = math.sqrt(2 * (math.log(1 + mw_conc) - mw_conc / (1 + mw_conc)))
    mw_a = r_scale * a_term

    return gp.HernquistPotential(m=total_mass, c=mw_a, units=galactic)
Ejemplo n.º 4
0
def test_staeckel_fudge_delta():
    import galpy.potential as galpy_pot
    from galpy.actionAngle import estimateDeltaStaeckel

    ro = 8.1 * u.kpc
    vo = 229 * u.km / u.s

    paired_potentials = []

    # Miyamoto-Nagai
    potential = gp.MiyamotoNagaiPotential(m=6e10 * u.Msun,
                                          a=3 * u.kpc,
                                          b=0.3 * u.kpc,
                                          units=galactic)
    amp = (G * potential.parameters['m']).to_value(vo**2 * ro)
    a = potential.parameters['a'].to_value(ro)
    b = potential.parameters['b'].to_value(ro)
    galpy_potential = galpy_pot.MiyamotoNagaiPotential(amp=amp,
                                                       a=a,
                                                       b=b,
                                                       ro=ro,
                                                       vo=vo)
    paired_potentials.append((potential, galpy_potential))

    # Hernquist
    potential = gp.HernquistPotential(m=6e10 * u.Msun,
                                      c=0.3 * u.kpc,
                                      units=galactic)
    amp = (G * potential.parameters['m']).to_value(vo**2 * ro)
    a = potential.parameters['c'].to_value(ro)
    galpy_potential = galpy_pot.HernquistPotential(amp=amp, a=a, ro=ro, vo=vo)
    paired_potentials.append((potential, galpy_potential))

    # NFW
    potential = gp.NFWPotential(m=6e11 * u.Msun,
                                r_s=15.6 * u.kpc,
                                units=galactic)
    amp = (G * potential.parameters['m']).to_value(vo**2 * ro)
    a = potential.parameters['r_s'].to_value(ro)
    galpy_potential = galpy_pot.NFWPotential(amp=amp, a=a, ro=ro, vo=vo)
    paired_potentials.append((potential, galpy_potential))

    # TEST:
    N = 1024
    rnd = np.random.default_rng(42)
    w = PhaseSpacePosition(pos=rnd.uniform(-10, 10, size=(3, N)) * u.kpc,
                           vel=rnd.uniform(-100, 100, size=(3, N)) * u.km /
                           u.s)

    R = w.cylindrical.rho.to_value(ro)
    z = w.z.to_value(ro)

    for p, galpy_p in paired_potentials:
        galpy_deltas = estimateDeltaStaeckel(galpy_p, R, z, no_median=True)
        gala_deltas = get_staeckel_fudge_delta(p, w).value
        print(p, np.allclose(gala_deltas, galpy_deltas))
        assert np.allclose(gala_deltas, galpy_deltas, atol=1e-6)
Ejemplo n.º 5
0
def integrate(w0,\
              pot=gp.HernquistPotential(m=130.0075e10*u.Msun,c = 32.089, units=galactic),\
              timestep = -10.67,\
              ntimesteps = 250,\
              verbose=False):

    # TODO
    orbit = None  # define the orbit object in this scope

    if verbose:
        print('integrating ... ')
        start_time = time.time()
        orbit = gp.Hamiltonian(pot).integrate_orbit(w0,
                                                    dt=timestep,
                                                    n_steps=ntimesteps)
        orbit_time = time.time() - start_time
        print('done integrating')
        print('Length of integration: %1.3f' % orbit_time)
    else:
        orbit = gp.Hamiltonian(pot).integrate_orbit(w0,
                                                    dt=timestep,
                                                    n_steps=ntimesteps)

    return orbit, pot
Ejemplo n.º 6
0
                                         a=1.9746 * 5 * u.kpc,
                                         b=1 * u.kpc,
                                         units=galactic)

pot['disk2'] = gp.MiyamotoNagaiPotential(m=10E10 * -1.2756 * u.Msun,
                                         a=4.2333 * 5 * u.kpc,
                                         b=1 * u.kpc,
                                         units=galactic)

pot['disk3'] = gp.MiyamotoNagaiPotential(m=10E10 * 0.2153 * u.Msun,
                                         a=0.6354 * 5 * u.kpc,
                                         b=1 * u.kpc,
                                         units=galactic)

pot['bulge'] = gp.HernquistPotential(m=3e10 * u.Msun,
                                     c=0.5 * u.kpc,
                                     units=galactic)

## Make grid (0.1 kpc resolution) for mock image
mock_image = np.zeros((61, 201))

## Calculate densities along line of sight in each x-z bin
temp_index = np.indices((1, 201, 1), dtype=float)
temp_index[1] = temp_index[1] / 2. - 50

# Not sure how to get properly shaped array of output from pot.density, hence for-loops
# Only run this once!!
for xind in range(0, 201):
    for zind in range(0, 61):

        xtemp = xind / 2. - 50
Ejemplo n.º 7
0
def hernquist_gradient(xyz, M, r_s):
    import gala.potential as gp
    p = gp.HernquistPotential(m=M, c=r_s,
                              units=[u.kpc, u.Myr, u.Msun, u.radian])
    return p.gradient(xyz).value
Ejemplo n.º 8
0
    Omega = ConfigItem(40., "Bar pattern speed [km/s/kpc]")
    bar_mass = ConfigItem(1E10, "Bar mass [Msun]")

    # TODO: add other tunable parameters once I decide on the potential...


# ==============================================================================

# Define the potential model up to the bar component
potential_no_bar = gp.CCompositePotential()
potential_no_bar['disk'] = gp.MiyamotoNagaiPotential(m=5E10 * u.Msun,
                                                     a=3 * u.kpc,
                                                     b=280 * u.pc,
                                                     units=galactic)
potential_no_bar['spheroid'] = gp.HernquistPotential(m=4E9 * u.Msun,
                                                     c=0.6 * u.kpc,
                                                     units=galactic)
potential_no_bar['halo'] = gp.NFWPotential(m=6E11,
                                           r_s=18 * u.kpc,
                                           units=galactic)


def get_hamiltonian(config_file=None):
    c = Config()
    c.load(config_file)

    pot = potential_no_bar.copy()
    pot['bar'] = get_bar_potential(config_file)

    Om = [0., 0., c.Omega] * u.km / u.s / u.kpc
    frame = gp.ConstantRotatingFrame(Omega=Om, units=galactic)
Ejemplo n.º 9
0
def integrate_dyn_fric(w0,\
              sat_mass = 1e8,\
              pot=gp.HernquistPotential(m=130.0075e10*u.Msun,c = 32.089, units=galactic),\
              scale_radius = 18.927757889861788,\
              timestep = -10.67,\
              ntimesteps = 250,\
              verbose=False):
    def F_dyn_fric(t, w, msat, rs):
        G_gal = 4.49850215e-12  # gravitational constant in galactic units (kpc^3 Msun^-1 Myr^-2)
        accdf = 0.0

        q = w[0:3]
        p = w[3:6]

        verf = np.vectorize(math.erf)

        absr = np.linalg.norm(q, axis=0)
        absv = np.linalg.norm(p, axis=0)

        loglambda = np.maximum(0, np.log(absr / 3 / 1.6))
        rhoh = pot.density(q).value

        normalized_r = absr / rs

        # 0.2199 kpc / Myr = 215 km/s
        sigma = 0.2199 * (1.4393 * normalized_r**0.354 /
                          (1 + 1.1756 * normalized_r**0.725))

        chand_x = absv / math.sqrt(2) / sigma

        # k is the part of the equation with the erf and exp components
        k = verf(chand_x) - 2 * chand_x * np.exp(
            -np.square(chand_x)) / math.sqrt(math.pi)

        accdf = (4 * math.pi * G_gal * G_gal * msat * loglambda * rhoh /
                 absv**3) * k * p

        q_dot = p
        p_dot = -pot.gradient(q).value + accdf

        toreturn = np.concatenate((q_dot, p_dot))

        return toreturn

    integrator = gi.LeapfrogIntegrator(F_dyn_fric,
                                       func_args=(sat_mass, scale_radius),
                                       func_units=galactic)

    orbit = None

    if verbose:
        print('integrating ... ')

        start_time = time.time()
        orbit = integrator.run(w0, dt=timestep, n_steps=ntimesteps)

        orbit_time = time.time() - start_time
        print('done integrating')
        print('Length of integration: %1.3f' % orbit_time)
    else:
        orbit = integrator.run(w0, dt=timestep, n_steps=ntimesteps)

    return orbit, pot
Ejemplo n.º 10
0
 def get_potential(self, p):
     """pars is the unpacked pars dict"""
     # HACK: TODO: allow other potentials
     return gp.HernquistPotential(m=p['pot_m'],
                                  c=np.exp(p['pot_log_rs']),
                                  units=galactic)
Ejemplo n.º 11
0
# clockwise 1, widdershins -1, angular thing
c1 = 1.0
c2 = -1.0
w1 = 1.0
w2 = 1.0

# Milky Way and Andromeda
M_MW = 1.0E11 * u.Msun
M_AND = 1.23E12 * u.Msun
SIZE_MW = 36.8  # kpc
SIZE_AND = 33.7  # kpc
MW_AND_DIST = 778.0 / sqrt(3)
MW_AND_VEL = -110.0 / sqrt(3)

POT_MW = gp.MilkyWayPotential()
POT_AND = gp.HernquistPotential(M_AND.value, 0, units=galactic)
ICS_MW = gd.PhaseSpacePosition(pos=[0, 0, 0] * u.kpc,
                               vel=[0, 0, 0] * u.km / u.s)
ICS_AND = gd.PhaseSpacePosition(
    pos=[MW_AND_DIST, MW_AND_DIST, MW_AND_DIST] * u.kpc,
    vel=[MW_AND_VEL, MW_AND_VEL, MW_AND_VEL] * (u.km / u.s))

# Lörg and Smøl Magellanic Clouds
M_LORG = 1.0E10 * u.M_sun
SIZE_LORG = 4.3  # u.kpc
MW_LORG_DIST = 49.97  # wrt MW, in kpc
MW_LORG_VEL = 321.0  # wrt MW, in km/s

POT_LORG = gp.HernquistPotential(M_LORG.value, 0, units=galactic)
ICS_LORG = gd.PhaseSpacePosition(
    pos=[MW_LORG_DIST, MW_LORG_DIST, MW_LORG_DIST] * u.kpc,
def run_gala_orbit(pos_sat, vel_sat, pos_tp, vel_tp):
    """
    Specify units in ICs
    """
    ## GALA set up

    # Design gala potential using Nbody and a test particle

    # Present-day position/velocity in inertial frame moving with instantaneous
    # Milky Way velocity:
    w0_mw = gd.PhaseSpacePosition(
        pos=[0, 0, 0] * u.kpc,
        vel=[0, 0, 0] * u.km / u.s,
    )
    pot_mw = gp.HernquistPotential(m=Mhost * u.Msun,
                                   c=1 * u.kpc,
                                   units=galactic)

    # Values from Vasiliev et al. 2020
    w0_lmc = gd.PhaseSpacePosition(
        pos=pos_sat,
        vel=vel_sat,
    )

    w0_test = gd.PhaseSpacePosition(
        pos=pos_tp,
        vel=vel_tp,
    )

    pot_lmc = gp.HernquistPotential(m=Msat * u.Msun,
                                    c=1 * u.kpc,
                                    units=galactic)

    w0 = gd.combine((w0_mw, w0_lmc, w0_test))
    nbody = gd.DirectNBody(w0, [pot_mw, pot_lmc, None])

    w1 = gd.combine((w0_lmc, w0_test))
    isolated = gd.DirectNBody(w1, [pot_lmc, None])

    # Full : Host - Satellite - test particle
    orbits = nbody.integrate_orbit(dt=dt * u.Gyr,
                                   t1=tmin * u.Gyr,
                                   t2=tmax * u.Gyr)

    # Orbit quantities full orbit
    pos_halo = np.array([orbits.xyz[:, :, 0].to(u.kpc).value])[0]
    pos_sat = np.array([orbits.xyz[:, :, 1].to(u.kpc).value])[0]
    pos_tp = np.array([orbits.xyz[:, :, 2].to(u.kpc).value])[0]

    vel_halo = np.array([orbits.v_xyz[:, :, 0].to(u.km / u.s).value])[0]
    vel_sat = np.array([orbits.v_xyz[:, :, 1].to(u.km / u.s).value])[0]
    vel_tp = np.array([orbits.v_xyz[:, :, 2].to(u.km / u.s).value])[0]

    r_halo = (np.sum(orbits.xyz[:, :, 0]**2, axis=0))**0.5
    r_sat = (np.sum(orbits.xyz[:, :, 1]**2, axis=0))**0.5
    r_tp = (np.sum(orbits.xyz[:, :, 2]**2, axis=0))**0.5

    v_halo = (np.sum(orbits.v_xyz[:, :, 0].to(u.km / u.s).value**2,
                     axis=0))**0.5
    v_sat = (np.sum(orbits.v_xyz[:, :, 1].to(u.km / u.s).value**2,
                    axis=0))**0.5
    v_tp = (np.sum(orbits.v_xyz[:, :, 2].to(u.km / u.s).value**2, axis=0))**0.5

    rtp_r2_sat = np.sum((np.array(orbits.xyz[:, :, 2].to(u.kpc).value -
                                  orbits.xyz[:, :, 1].to(u.kpc).value))**2,
                        axis=0)**0.5
    vtp_r2_sat = np.sum(
        (np.array(orbits.v_xyz[:, :, 2].to(u.km / u.s).value -
                  orbits.v_xyz[:, :, 1].to(u.km / u.s).value))**2,
        axis=0)**0.5

    return [pos_halo, vel_halo], [pos_sat, vel_sat], [pos_tp, vel_tp]
Ejemplo n.º 13
0
# coordinates (x, y, z) and returns the (scalar) value of the density at that
# location:


def density_func(x, y, z):
    r = np.sqrt(x**2 + y**2 + z**2)
    return 1 / (r**1.8 * (1 + r)**2.7)


# Let's visualize this density function. For comparison, let's also over-plot
# the Hernquist density distribution. The SCF expansion uses the Hernquist
# density for radial basis functions, so the similarity of the density we want
# to represent and the Hernquist function gives us a sense of how many radial
# terms we will need in the expansion:

hern = gp.HernquistPotential(m=1, c=1)

# +
x = np.logspace(-1, 1, 128)
plt.plot(x, density_func(x, 0, 0), marker='', label='custom density')

# need a 3D grid for the potentials in Gala
xyz = np.zeros((3, len(x)))
xyz[0] = x
plt.plot(x, hern.density(xyz), marker='', label='Hernquist')

plt.xscale('log')
plt.yscale('log')

plt.xlabel('$r$')
plt.ylabel(r'$\rho(r)$')