예제 #1
0
def setup_potential_kuepper(Mhalo: float, a: float) -> List[Potential]:
    """Set up Kuepper et al. (2015) Potential.

    Parameters
    ----------
    Mhalo: float
        mass / 10^12 Msun
    a: float
        scale length / kpc,

    Returns
    -------
    potential : list
        HernquistPotential + MiyamotoNagaiPotential + NFWPotential

    """
    pot: List[Potential] = [
        potential.HernquistPotential(amp=3.4e10 * u.Msun, a=0.7 * u.kpc),
        potential.MiyamotoNagaiPotential(amp=1e11 * u.Msun,
                                         a=6.5 * u.kpc,
                                         b=0.26 * u.kpc),
        potential.NFWPotential(amp=Mhalo * 1e12 * u.Msun, a=a * u.kpc),
    ]

    return pot
예제 #2
0
def test_nemo_MiyamotoNagaiPotential():
    mp = potential.MiyamotoNagaiPotential(normalize=1., a=0.5, b=0.1)
    tmax = 4.
    vo, ro = 220., 8.
    o = Orbit([1., 0.1, 1.1, 0.3, 0.1, 0.4], ro=ro, vo=vo)
    run_orbitIntegration_comparison(o, mp, tmax, vo, ro)
    return None
예제 #3
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)
예제 #4
0
def accMWpot(x,y,z,alpha=1.8, rc=1.9, a=3., b=0.28):
    x = x/kpctocm
    y = y/kpctocm
    z = z/kpctocm
    r = np.sqrt( x**2 + y**2)
    bp= gp.PowerSphericalPotentialwCutoff(alpha=1.8,rc=1.9/8.,normalize=0.05)
    mp= gp.MiyamotoNagaiPotential(a=a/8.,b=b/8.,normalize=.6)
    nfw= gp.NFWPotential(a=16/8.,normalize=.35)
    #print(help(MWPotential2014))
    #pot = [bp,mp,nfw]
    pot = MWPotential2014
    az = evaluatezforces(pot,r*u.kpc , z*u.kpc)*bovy_conversion.force_in_kmsMyr(Vlsr/1e5,8.122)
    ar = evaluateRforces(pot,r*u.kpc , z*u.kpc)*bovy_conversion.force_in_kmsMyr(Vlsr/1e5,8.122)
    ar = ar*1.e5/(1.e6*3.15e7)
    az = -az*1.e5/(1.e6*3.15e7)

    ax = -ar*x/r
    ay = -ar*y/r
    return ax,ay,az
def setup_potential(params,c,fitc,dblexp,ro,vo,fitvoro=False,b=1.,pa=0.,
                    addgas=False):
    pot= [potential.PowerSphericalPotentialwCutoff(normalize=1.-params[0]-params[1],
                                                   alpha=1.8,rc=1.9/ro)]
    if dblexp:
        if addgas:
            # add 13 Msun/pc^2 
            gp= potential.DoubleExponentialDiskPotential(\
                amp=0.03333*u.Msun/u.pc**3\
                    *numpy.exp(ro/2./numpy.exp(params[2])/_REFR0),
                hz=150.*u.pc,
                hr=2.*numpy.exp(params[2])*_REFR0/ro,
                ro=ro,vo=vo)
            gp.turn_physical_off()
            gprf= gp.Rforce(1.,0.)
            dpf= params[0]+gprf
            if dpf < 0.: dpf= 0.
            pot.append(\
                potential.DoubleExponentialDiskPotential(\
                    normalize=dpf,hr=numpy.exp(params[2])*_REFR0/ro,
                    hz=numpy.exp(params[3])*_REFR0/ro))
        else:
            pot.append(\
                potential.DoubleExponentialDiskPotential(\
                    normalize=params[0],hr=numpy.exp(params[2])*_REFR0/ro,
                    hz=numpy.exp(params[3])*_REFR0/ro))
    else:
        pot.append(\
            potential.MiyamotoNagaiPotential(normalize=params[0],
                                             a=numpy.exp(params[2])*_REFR0/ro,
                                             b=numpy.exp(params[3])*_REFR0/ro))
    if fitc:
        pot.append(potential.TriaxialNFWPotential(\
                normalize=params[1],a=numpy.exp(params[4])*_REFR0/ro,
                c=params[7+2*fitvoro],b=b,pa=pa))
    else:
        pot.append(potential.TriaxialNFWPotential(\
                normalize=params[1],a=numpy.exp(params[4])*_REFR0/ro,
                c=c,b=b,pa=pa))
    if addgas:
        pot.append(gp) # make sure it's the last
    return pot
예제 #6
0
def setup_potential(
    params: Sequence,
    c: float,
    fitc: bool,
    dblexp: bool,
    ro: float = REFR0,
    vo: float = REFV0,
    fitvoro: bool = False,
    b: float = 1.0,
    pa: float = 0.0,
    addgas: bool = False,
) -> PotentialType:
    """Set up potential.

    PowerSphericalPotentialwCutoff
    MiyamotoNagaiPotential or DoubleExponentialDiskPotential
    TriaxialNFWPotential

    Parameters
    ----------
    params
    c
    fitc
    dblexp
        DoubleExponentialDiskPotential instead if MiyamotoNagaiPotential
    ro
    vo
    fitvoro: bool, optional
        default False
    b: float, optional
        default 1.0
    pa: float, optional
        Position Angle
        default 0.0
    addgas: bool, optional
        default False

    """
    pot: potential.Potential = [
        potential.PowerSphericalPotentialwCutoff(
            normalize=1.0 - params[0] - params[1], alpha=1.8, rc=1.9 / ro
        )
    ]

    if dblexp:
        if addgas:
            # add 13 Msun/pc^2
            gp = potential.DoubleExponentialDiskPotential(
                amp=0.03333
                * u.Msun
                / u.pc ** 3
                * np.exp(ro / 2.0 / np.exp(params[2]) / REFR0),
                hz=150.0 * u.pc,
                hr=2.0 * np.exp(params[2]) * REFR0 / ro,
                ro=ro,
                vo=vo,
            )
            gp.turn_physical_off()
            gprf = gp.Rforce(1.0, 0.0)
            dpf = params[0] + gprf
            if dpf < 0.0:
                dpf = 0.0
            pot.append(
                potential.DoubleExponentialDiskPotential(
                    normalize=dpf,
                    hr=np.exp(params[2]) * REFR0 / ro,
                    hz=np.exp(params[3]) * REFR0 / ro,
                )
            )
        else:
            pot.append(
                potential.DoubleExponentialDiskPotential(
                    normalize=params[0],
                    hr=np.exp(params[2]) * REFR0 / ro,
                    hz=np.exp(params[3]) * REFR0 / ro,
                )
            )
    else:
        pot.append(
            potential.MiyamotoNagaiPotential(
                normalize=params[0],
                a=np.exp(params[2]) * REFR0 / ro,
                b=np.exp(params[3]) * REFR0 / ro,
            )
        )

    if fitc:
        pot.append(
            potential.TriaxialNFWPotential(
                normalize=params[1],
                a=np.exp(params[4]) * REFR0 / ro,
                c=params[7 + 2 * fitvoro],
                b=b,
                pa=pa,
            )
        )
    else:
        pot.append(
            potential.TriaxialNFWPotential(
                normalize=params[1], a=np.exp(params[4]) * REFR0 / ro, c=c, b=b, pa=pa,
            )
        )

    if addgas:
        pot.append(gp)  # make sure it's the last

    return pot
예제 #7
0
def test_dynamfric_c():
    import copy
    from galpy.orbit import Orbit
    from galpy.potential.Potential import _check_c
    from galpy.potential.mwpotentials import McMillan17
    #Basic parameters for the test
    times = numpy.linspace(0., -100., 1001)  #~3 Gyr at the Solar circle
    integrator = 'dop853_c'
    py_integrator = 'dop853'
    #Define all of the potentials (by hand, because need reasonable setup)
    MWPotential3021 = copy.deepcopy(potential.MWPotential2014)
    MWPotential3021[2] *= 1.5  # Increase mass by 50%
    pots= [potential.LogarithmicHaloPotential(normalize=1),
           potential.LogarithmicHaloPotential(normalize=1.3,
                                              q=0.9,b=0.7), #nonaxi
           potential.NFWPotential(normalize=1.,a=1.5),
           potential.MiyamotoNagaiPotential(normalize=.02,a=10.,b=10.),
           potential.MiyamotoNagaiPotential(normalize=.6,a=0.,b=3.), # special case
           potential.PowerSphericalPotential(alpha=2.3,normalize=2.),
           potential.DehnenSphericalPotential(normalize=4.,alpha=1.2),
           potential.DehnenCoreSphericalPotential(normalize=4.),
           potential.HernquistPotential(normalize=1.,a=3.5),
           potential.JaffePotential(normalize=1.,a=20.5),
           potential.DoubleExponentialDiskPotential(normalize=0.2,
                                                    hr=3.,hz=0.6),
           potential.FlattenedPowerPotential(normalize=3.),
           potential.FlattenedPowerPotential(normalize=3.,alpha=0), #special case
           potential.IsochronePotential(normalize=2.),
           potential.PowerSphericalPotentialwCutoff(normalize=0.3,rc=10.),
           potential.PlummerPotential(normalize=.6,b=3.),
           potential.PseudoIsothermalPotential(normalize=.1,a=3.),
           potential.BurkertPotential(normalize=.2,a=2.5),
           potential.TriaxialHernquistPotential(normalize=1.,a=3.5,
                                                b=0.8,c=0.9),
           potential.TriaxialNFWPotential(normalize=1.,a=1.5,b=0.8,c=0.9),
           potential.TriaxialJaffePotential(normalize=1.,a=20.5,b=0.8,c=1.4),
           potential.PerfectEllipsoidPotential(normalize=.3,a=3.,b=0.7,c=1.5),
           potential.PerfectEllipsoidPotential(normalize=.3,a=3.,b=0.7,c=1.5,
                                               pa=3.,zvec=[0.,1.,0.]), #rotated
           potential.HomogeneousSpherePotential(normalize=0.02,R=82./8), # make sure to go to dens = 0 part,
           potential.interpSphericalPotential(\
                    rforce=potential.HomogeneousSpherePotential(normalize=0.02,
                                                                R=82./8.),
                    rgrid=numpy.linspace(0.,82./8.,201)),
           potential.TriaxialGaussianPotential(normalize=.03,sigma=4.,b=0.8,c=1.5,pa=3.,zvec=[1.,0.,0.]),
           potential.SCFPotential(Acos=numpy.array([[[1.]]]), # same as Hernquist
                                  normalize=1.,a=3.5),
           potential.SCFPotential(Acos=numpy.array([[[1.,0.],[.3,0.]]]), # nonaxi
                                  Asin=numpy.array([[[0.,0.],[1e-1,0.]]]),
                                  normalize=1.,a=3.5),
           MWPotential3021,
           McMillan17 # SCF + DiskSCF
           ]
    #tolerances in log10
    tol = {}
    tol['default'] = -7.
    # Following are a little more difficult
    tol['DoubleExponentialDiskPotential'] = -4.5
    tol['TriaxialHernquistPotential'] = -6.
    tol['TriaxialNFWPotential'] = -6.
    tol['TriaxialJaffePotential'] = -6.
    tol['MWPotential3021'] = -6.
    tol['HomogeneousSpherePotential'] = -6.
    tol['interpSphericalPotential'] = -6.  # == HomogeneousSpherePotential
    tol['McMillan17'] = -6.
    for p in pots:
        if not _check_c(p, dens=True): continue  # dynamfric not in C!
        pname = type(p).__name__
        if pname == 'list':
            if isinstance(p[0],potential.PowerSphericalPotentialwCutoff) \
                    and len(p) > 1 \
                    and isinstance(p[1],potential.MiyamotoNagaiPotential) \
                    and len(p) > 2 \
                    and isinstance(p[2],potential.NFWPotential):
                pname = 'MWPotential3021'  # Must be!
            else:
                pname = 'McMillan17'
        #print(pname)
        if pname in list(tol.keys()): ttol = tol[pname]
        else: ttol = tol['default']
        # Setup orbit, ~ LMC
        o = Orbit([
            5.13200034, 1.08033051, 0.23323391, -3.48068653, 0.94950884,
            -1.54626091
        ])
        # Setup dynamical friction object
        if pname == 'McMillan17':
            cdf= potential.ChandrasekharDynamicalFrictionForce(\
                GMs=0.5553870441722593,rhm=5./8.,dens=p,maxr=500./8,nr=101)
            ttimes = numpy.linspace(0., -30.,
                                    1001)  #~1 Gyr at the Solar circle
        else:
            cdf= potential.ChandrasekharDynamicalFrictionForce(\
                GMs=0.5553870441722593,rhm=5./8.,dens=p,maxr=500./8,nr=201)
            ttimes = times
        # Integrate in C
        o.integrate(ttimes, p + cdf, method=integrator)
        # Integrate in Python
        op = o()
        op.integrate(ttimes, p + cdf, method=py_integrator)
        # Compare r (most important)
        assert numpy.amax(numpy.fabs(o.r(ttimes)-op.r(ttimes))) < 10**ttol, \
            'Dynamical friction in C does not agree with dynamical friction in Python for potential {}'.format(pname)
    return None