Exemplo n.º 1
0
def test_dens_in_msolpc3():
    #Test the scaling, as a 2nd derivative of the potential / G, should scale as velocity^2/position^2
    vofid, rofid = 200., 8.
    assert numpy.fabs(4. * bovy_conversion.dens_in_msolpc3(vofid, rofid) /
                      bovy_conversion.dens_in_msolpc3(2. * vofid, rofid) - 1.
                      ) < 10.**-10., 'dens_in_msolpc3 did not work as expected'
    assert numpy.fabs(.25 * bovy_conversion.dens_in_msolpc3(vofid, rofid) /
                      bovy_conversion.dens_in_msolpc3(vofid, 2 * rofid) - 1.
                      ) < 10.**-10., 'dens_in_msolpc3 did not work as expected'
    return None
Exemplo n.º 2
0
def test_units():
    import galpy.util.bovy_conversion as conversion
    print(conversion.force_in_pcMyr2(220.,8.))#pc/Myr^2
    assert numpy.fabs(conversion.force_in_pcMyr2(220.,8.)-6.32793804994) < 10.**-4., 'unit conversion has changed'
    print(conversion.dens_in_msolpc3(220.,8.))#Msolar/pc^3
    assert numpy.fabs(conversion.dens_in_msolpc3(220.,8.)-0.175790330079) < 10.**-4., 'unit conversion has changed'
    print(conversion.surfdens_in_msolpc2(220.,8.))#Msolar/pc^2
    assert numpy.fabs(conversion.surfdens_in_msolpc2(220.,8.)-1406.32264063) < 10.**-4., 'unit conversion has changed'
    print(conversion.mass_in_1010msol(220.,8.))#10^10 Msolar
    assert numpy.fabs(conversion.mass_in_1010msol(220.,8.)-9.00046490005) < 10.**-4., 'unit conversion has changed'
    print(conversion.freq_in_Gyr(220.,8.))#1/Gyr
    assert numpy.fabs(conversion.freq_in_Gyr(220.,8.)-28.1245845523) < 10.**-4., 'unit conversion has changed'
    print(conversion.time_in_Gyr(220.,8.))#Gyr
    assert numpy.fabs(conversion.time_in_Gyr(220.,8.)-0.0355560807712) < 10.**-4., 'unit conversion has changed'
    return None
Exemplo n.º 3
0
def test_units():
    import galpy.util.bovy_conversion as conversion
    print(conversion.force_in_pcMyr2(220.,8.))#pc/Myr^2
    assert numpy.fabs(conversion.force_in_pcMyr2(220.,8.)-6.32793804994) < 10.**-4., 'unit conversion has changed'
    print(conversion.dens_in_msolpc3(220.,8.))#Msolar/pc^3
    assert numpy.fabs((conversion.dens_in_msolpc3(220.,8.)-0.175790330079)/0.175790330079) < 5.*10.**-5., 'unit conversion has changed'
    print(conversion.surfdens_in_msolpc2(220.,8.))#Msolar/pc^2
    assert numpy.fabs((conversion.surfdens_in_msolpc2(220.,8.)-1406.32264063)/1406.32264063) < 5.*10.**-5., 'unit conversion has changed'
    print(conversion.mass_in_1010msol(220.,8.))#10^10 Msolar
    assert numpy.fabs((conversion.mass_in_1010msol(220.,8.)-9.00046490005)/9.00046490005) < 5.*10.**-5., 'unit conversion has changed'
    print(conversion.freq_in_Gyr(220.,8.))#1/Gyr
    assert numpy.fabs(conversion.freq_in_Gyr(220.,8.)-28.1245845523) < 10.**-4., 'unit conversion has changed'
    print(conversion.time_in_Gyr(220.,8.))#Gyr
    assert numpy.fabs(conversion.time_in_Gyr(220.,8.)-0.0355560807712) < 10.**-4., 'unit conversion has changed'
    return None
Exemplo n.º 4
0
    def __init__(self,K=1.15,F=0.03,D=1.8,amp=1.,ro=None,vo=None):
        """
        NAME:

           __init__

        PURPOSE:

           Initialize a KGPotential

        INPUT:

           K= K parameter (= :math:`2\\pi \\Sigma_{\\mathrm{disk}}`; specify either as surface density or directly as force [i.e., including :math:`2\\pi G`]; can be Quantity)

           F= F parameter (= :math:`4\\pi\\rho_{\\mathrm{halo}}`; specify either as density or directly as second potential derivative [i.e., including :math:`4\\pi G`]; can be Quantity)

           D= D parameter (natural units or Quantity length units)

           amp - an overall amplitude

        OUTPUT:

           instance

        HISTORY:

           2010-07-12 - Written - Bovy (NYU)

        """
        linearPotential.__init__(self,amp=amp,ro=ro,vo=vo)
        if _APY_LOADED and isinstance(D,units.Quantity):
            D= D.to(units.kpc).value/self._ro
        if _APY_LOADED and isinstance(K,units.Quantity):
            try:
                K= K.to(units.pc/units.Myr**2).value\
                    /bovy_conversion.force_in_pcMyr2(self._vo,self._ro)
            except units.UnitConversionError: pass
        if _APY_LOADED and isinstance(K,units.Quantity):
            try:
                K= K.to(units.Msun/units.pc**2).value\
                    /bovy_conversion.force_in_2piGmsolpc2(self._vo,self._ro)
            except units.UnitConversionError:
                raise units.UnitConversionError("Units for K not understood; should be force or surface density")
        if _APY_LOADED and isinstance(F,units.Quantity):
            try:
                F= F.to(units.Msun/units.pc**3).value\
                    /bovy_conversion.dens_in_msolpc3(self._vo,self._ro)*4.*sc.pi
            except units.UnitConversionError: pass
        if _APY_LOADED and isinstance(F,units.Quantity):
            try:
                F= F.to(units.km**2/units.s**2/units.kpc**2).value\
                    *ro**2/vo**2
            except units.UnitConversionError:
                raise units.UnitConversionError("Units for F not understood; should be density")
        self._K= K
        self._F= F
        self._D= D
        self._D2= self._D**2.
        self.hasC= True
Exemplo n.º 5
0
    def __init__(self,Rho,Sigma):

        try:
            self.sig= [s.to(u.km/u.s).value/self.InternalUnits['vo'] for s in Sigma]
        except:
            #print('''You did not specify units for the velocity dispersion,
            #so they have been assumed to be in galpy internal units.''')
            self.sig= Sigma

        try:
            self.rho0= [r.to(u.Msun/(u.pc**3)).value/dens_in_msolpc3(self.InternalUnits['vo'], self.InternalUnits['ro']) for r in Rho]
        except:
            #print('''You did not specify units for the mid-plane density,
            #so they have been assumed to be in galpy internal units.''')
            self.rho0= Rho
Exemplo n.º 6
0
def compute_Acos_Asin(n=9,
                      l=19,
                      a=1. / ro,
                      radial_order=40,
                      costheta_order=40,
                      phi_order=40):

    Acos, Asin = potential.scf_compute_coeffs(
        lambda R, z, p: rho_bar_cyl(R * 8., z * 8., p) /
        (10**9. * bovy_conversion.dens_in_msolpc3(220., 8.)),
        N=n + 1,
        L=l + 1,
        a=a,
        radial_order=radial_order,
        costheta_order=costheta_order,
        phi_order=phi_order)

    return (Acos, Asin)
def writeTable(pot,params,tablename,options,fzrd):
    outfile= open(tablename,'w')
    delimiter= ' & '
    #First list the explicit parameters
    printline= '$R_0\,(\kpc)$%s$8$%sfixed\\\\\n' % (delimiter,delimiter)
    outfile.write(printline)
    printline= '$v_c(R_0)\,(\kms)$%s$220$%sfixed\\\\\n' % (delimiter,delimiter)
    outfile.write(printline)
    if options.twodisks:
        printline= '$f_{b}$%s$%.2f$%s\ldots\\\\\n' % (delimiter,1.-params[0]-params[1]-params[2],delimiter)        
        outfile.write(printline)
        printline= '$f_{d,1}$%s$%.2f$%s\ldots\\\\\n' % (delimiter,params[0],delimiter)
        outfile.write(printline)
        printline= '$f_{d,2}$%s$%.2f$%s\ldots\\\\\n' % (delimiter,params[1],delimiter)        
        outfile.write(printline)
        printline= '$f_{h}$%s$%.2f$%s\ldots\\\\\n' % (delimiter,params[2],delimiter)        
        outfile.write(printline)
    else:
        printline= '$f_{b}$%s$%.2f$%s\ldots\\\\\n' % (delimiter,1.-params[0]-params[1],delimiter)        
        outfile.write(printline)
        printline= '$f_{d}$%s%.2f%s\ldots\\\\\n' % (delimiter,params[0],delimiter)
        outfile.write(printline)
        printline= '$f_{h}$%s$%.2f$%s\ldots\\\\\n' % (delimiter,params[1],delimiter)        
        outfile.write(printline)
    #Bulge power-law and rc
    printline= '$\mathrm{Bulge\ power}$%s$-1.8$%sfixed\\\\\n' % (delimiter,delimiter)        
    outfile.write(printline)
    printline= '$\mathrm{Bulge\ cut}\,(\kpc)$%s$1.9$%sfixed\\\\\n' % (delimiter,delimiter)        
    outfile.write(printline)
    #Disk scale length and height
    printline= '$a\,(\kpc)$%s$%.1f$%s\ldots\\\\\n' % (delimiter,numpy.exp(params[2+options.twodisks])*_REFR0,delimiter)        
    outfile.write(printline)
    printline= '$b\,(\pc)$%s$%.0f$%s\ldots\\\\\n' % (delimiter,1000.*numpy.exp(params[3+options.twodisks])*_REFR0,delimiter)        
    outfile.write(printline)
    printline= '$\mathrm{Halo}\ r_s\,(\kpc)$%s$%.0f$%s\ldots\\\\\n' % (delimiter,numpy.exp(params[4+options.twodisks])*_REFR0,delimiter)        
    outfile.write(printline)
    outfile.write('%s%s\\\\\n' % (delimiter,delimiter))
    #Now the constraints
    printline= '$\sigma_b\,(\kms)$%s$%.0f$%s$117\pm15$\\\\\n' % (delimiter,bulge_dispersion(pot),delimiter)
    outfile.write(printline)
    printline= '$F_Z(R_0,1.1\kpc)\,(2\pi G\,M_\odot\pc^{-2})$%s$%.0f$%s$67\pm6$\\\\\n' % (delimiter,-potential.evaluatezforces(1.,1.1/_REFR0,pot)*bovy_conversion.force_in_2piGmsolpc2(_REFV0,_REFR0),delimiter)
    outfile.write(printline)
    printline= '$\Sigma_{\mathrm{vis}}(R_0)\,(M_\odot\pc^{-2})$%s$%.0f$%s$55\pm5$\\\\\n' % (delimiter,visible_dens(pot,options),delimiter)
    outfile.write(printline)
    printline= '$F_Z\ \mathrm{scale\ length}\,(\kpc)$%s%.1f%s$2.7\pm0.1$\\\\\n' % (delimiter,fzrd*_REFR0,delimiter)
    outfile.write(printline)
    printline= '$\\rho(R_0,z=0)\,(M_\odot\pc^{-3})$%s$%.2f$%s$0.10\pm0.01$\\\\\n' % (delimiter,potential.evaluateDensities(1.,0.,pot)*bovy_conversion.dens_in_msolpc3(_REFV0,_REFR0),delimiter)
    outfile.write(printline)
    printline= '$(\dd \ln v_c/\dd \ln R)|_{R_0}$%s$%.2f$%s$-0.2\ \mathrm{to}\ 0$\\\\\n' % (delimiter,potential.dvcircdR(pot,1.),delimiter)
    outfile.write(printline)
    printline= '$M(r<60\kpc)\,(10^{11}\,M_\odot)$%s$%.1f$%s$4.0\pm0.7$\\\\\n' % (delimiter,mass60(pot,options),delimiter)
    outfile.write(printline)
    outfile.write('%s%s\\\\\n' % (delimiter,delimiter))
    #Now some derived properties
    printline= '$M_b\,(10^{10}\,M_\odot)$%s$%.1f$%s\ldots\\\\\n' % (delimiter,pot[0].mass(10.)*bovy_conversion.mass_in_1010msol(_REFV0,_REFR0),delimiter)
    outfile.write(printline)
    if options.twodisks:
        printline= '$M_d\,(10^{10}\,M_\odot)$%s$%.1f$%s\ldots\\\\\n' % (delimiter,(pot[1]._amp+pot[2]._amp)*bovy_conversion.mass_in_1010msol(_REFV0,_REFR0),delimiter)
    else:
        printline= '$M_d\,(10^{10}\,M_\odot)$%s$%.1f$%s\ldots\\\\\n' % (delimiter,pot[1]._amp*bovy_conversion.mass_in_1010msol(_REFV0,_REFR0),delimiter)
    outfile.write(printline)
    krs= numpy.linspace(4./_REFR0,9./_REFR0,101)
    disksurf= numpy.array([visible_dens(pot,options,r=kr) for kr in krs])
    p= numpy.polyfit(krs,numpy.log(disksurf),1)
    rd= -1./p[0]*_REFR0
    printline= '$R_{d}\,(\kpc)$%s$%.1f$%s\ldots\\\\\n' % (delimiter,rd,delimiter)
    outfile.write(printline)
    rvir= pot[2+options.twodisks].rvir(_REFV0,_REFR0,wrtcrit=True,overdens=96.7)
    printline= '$\\rho_{\mathrm{DM}}(R_0)\,(M_\odot\pc^{-3})$%s$%.3f$%s\\\\\n' % (delimiter,potential.evaluateDensities(1.,0.,pot[2+options.twodisks])*bovy_conversion.dens_in_msolpc3(_REFV0,_REFR0),delimiter)
    outfile.write(printline)
    printline= '$M_{\mathrm{vir}}\,(10^{12}\,M_\odot)$%s$%.1f$%s\ldots\\\\\n' % (delimiter,pot[2+options.twodisks].mass(rvir)*bovy_conversion.mass_in_1010msol(_REFV0,_REFR0)/100.,delimiter)
    outfile.write(printline)
    printline= '$r_{\mathrm{vir}}\,(\kpc)$%s$%.0f$%s\ldots\\\\\n' % (delimiter,rvir*_REFR0,delimiter)
    outfile.write(printline)
    printline= '$\mathrm{Concentration}$%s$%.1f$%s\ldots\\\\\n' % (delimiter,rvir/pot[2+options.twodisks].a,delimiter)
    outfile.write(printline)
    printline= '$v_{\mathrm{esc}}(R_0)\,(\kms)$%s$%.0f$%s\ldots\n' % (delimiter,potential.vesc(pot,1.)*_REFV0,delimiter)
    outfile.write(printline)
    #printline= '$r_{\mathrm{vir}}\,(\kpc)$%s$%.0f$%s\ldots\\\\\n' % (delimiter,delimiter)
    #outfile.write(printline)
    
    outfile.write('\\enddata\n')
    pass
Exemplo n.º 8
0
    def __init__(self, K=1.15, F=0.03, D=1.8, amp=1., ro=None, vo=None):
        """
        NAME:

           __init__

        PURPOSE:

           Initialize a KGPotential

        INPUT:

           K= K parameter (= :math:`2\\pi \\Sigma_{\\mathrm{disk}}`; specify either as surface density or directly as force [i.e., including :math:`2\\pi G`]; can be Quantity)

           F= F parameter (= :math:`4\\pi\\rho_{\\mathrm{halo}}`; specify either as density or directly as second potential derivative [i.e., including :math:`4\\pi G`]; can be Quantity)

           D= D parameter (natural units or Quantity length units)

           amp - an overall amplitude

        OUTPUT:

           instance

        HISTORY:

           2010-07-12 - Written - Bovy (NYU)

        """
        linearPotential.__init__(self, amp=amp, ro=ro, vo=vo)
        if _APY_LOADED and isinstance(D, units.Quantity):
            D = D.to(units.kpc).value / self._ro
        if _APY_LOADED and isinstance(K, units.Quantity):
            try:
                K= K.to(units.pc/units.Myr**2).value\
                    /bovy_conversion.force_in_pcMyr2(self._vo,self._ro)
            except units.UnitConversionError:
                pass
        if _APY_LOADED and isinstance(K, units.Quantity):
            try:
                K= K.to(units.Msun/units.pc**2).value\
                    /bovy_conversion.force_in_2piGmsolpc2(self._vo,self._ro)
            except units.UnitConversionError:
                raise units.UnitConversionError(
                    "Units for K not understood; should be force or surface density"
                )
        if _APY_LOADED and isinstance(F, units.Quantity):
            try:
                F= F.to(units.Msun/units.pc**3).value\
                    /bovy_conversion.dens_in_msolpc3(self._vo,self._ro)*4.*sc.pi
            except units.UnitConversionError:
                pass
        if _APY_LOADED and isinstance(F, units.Quantity):
            try:
                F= F.to(units.km**2/units.s**2/units.kpc**2).value\
                    *ro**2/vo**2
            except units.UnitConversionError:
                raise units.UnitConversionError(
                    "Units for F not understood; should be density")
        self._K = K
        self._F = F
        self._D = D
        self._D2 = self._D**2.
Exemplo n.º 9
0
def rlimiting(cluster,
              pot=MWPotential2014,
              rgc=None,
              ro=8.0,
              vo=220.0,
              nrad=20,
              projected=False,
              plot=False,
              **kwargs):
    """Calculate limiting radius of the cluster
       
    - The limiting radius is defined to be where the cluster's density reaches the local background density of the host galaxy
    - for cases where the cluster's orbital parameters are not set, it is possible to manually set rgc which is assumed to be in kpc.

    Parameters
    ----------

    cluster : class
        StarCluster
    pot : class 
        GALPY potential used to calculate actions
    rgc : 
        Manually set galactocentric distance in kpc at which the tidal radius is to be evaluated (default: None)
    ro : float
        GALPY radius scaling parameter
    vo : float
        GALPY velocity scaling parameter
    nrad : int
        number of radial bins used to calculate density profile (Default: 20)
    projected : bool
        use projected values (default: False)
    plot : bool
        plot the density profile and mark the limiting radius of the cluster (default: False)

    Returns
    -------
        rl : float
            limiting radius

    Other Parameters
    ----------------
    kwargs : str
        key words for plotting

    History
    -------
    2019 - Written - Webb (UofT)
    """
    units0, origin0 = save_cluster(cluster)

    cluster.to_centre()
    cluster.to_galpy()

    if rgc != None:
        R = rgc / ro
        z = 0.0
    else:
        R = np.sqrt(cluster.xgc**2.0 + cluster.ygc**2.0)
        z = cluster.zgc

    # Calculate local density:
    rho_local = potential.evaluateDensities(
        pot, R, z, ro=ro, vo=vo,
        use_physical=False) / bovy_conversion.dens_in_msolpc3(ro=ro, vo=vo)

    rprof, pprof, nprof = _rho_prof(cluster, nrad=nrad, projected=projected)

    if pprof[-1] > rho_local:
        rl = rprof[-1]
    elif pprof[0] < rho_local:
        rl = 0.0
    else:
        indx = np.argwhere(pprof < rho_local)[0][0]
        r1 = (rprof[indx - 1], pprof[indx - 1])
        r2 = (rprof[indx], pprof[indx])

        rl = interpolate(r1, r2, y=rho_local)

    if units0 == "pckms":
        rl *= 1000.0 * ro
    elif units0 == "kpckms":
        rl *= ro
    elif units0 == "nbody":
        rl *= 1000.0 * ro / cluster.rbar

    return_cluster(cluster, units0, origin0, do_order=True, do_key_params=True)

    if plot:

        filename = kwargs.pop("filename", None)
        overplot = kwargs.pop("overplot", False)

        if cluster.units == "nbody":
            rprof *= ro * 1000.0 / cluster.rbar
            pprof *= (bovy_conversion.dens_in_msolpc3(ro=ro, vo=vo) *
                      (cluster.rbar**3.0) / cluster.zmbar)
            rho_local *= (bovy_conversion.dens_in_msolpc3(ro=ro, vo=vo) *
                          (cluster.rbar**3.0) / cluster.zmbar)
            xunits = " (NBODY)"
            yunits = " (NBODY)"
        elif cluster.units == "pckms":
            rprof *= ro * 1000.0
            pprof *= bovy_conversion.dens_in_msolpc3(ro=ro, vo=vo)
            rho_local *= bovy_conversion.dens_in_msolpc3(ro=ro, vo=vo)
            xunits = " (pc)"
            if projected:
                yunits = " Msun/pc^2"
            else:
                yunits = " Msun/pc^3"
        elif cluster.units == "kpckms":
            rprof *= ro
            pprof *= bovy_conversion.dens_in_msolpc3(ro=ro, vo=vo) * (1000.0**
                                                                      3.0)
            rho_local *= bovy_conversion.dens_in_msolpc3(ro=ro,
                                                         vo=vo) * (1000.0**3.0)

            xunits = " (kpc)"
            if projected:
                yunits = " Msun/kpc^2"
            else:
                yunits = " Msun/kpc^3"
        elif cluster.units == "galpy":
            xunits = " (GALPY)"
            yunits = " (GALPY)"

        else:
            xunits = ""
            yunits = ""

        x, y, n = rprof, pprof, nprof
        _lplot(
            x,
            y,
            xlabel=r"$R %s$" % (xunits),
            ylabel=r"$\rho %s$" % (yunits),
            title="Time = %f" % cluster.tphys,
            log=True,
            overplot=overplot,
            filename=filename,
        )
        _lplot(x, np.ones(len(x)) * rho_local, "--", overplot=True)
        _lplot(np.ones(len(y)) * rl, y, "--", overplot=True)

        if filename != None:
            plt.savefig(filename)

    return rl
Exemplo n.º 10
0
import numpy as np
from galpy.potential import DiskSCFPotential, NFWPotential, \
    SCFPotential, scf_compute_coeffs_axi
from galpy.util import bovy_conversion
from SCF_derivs import mySCFPotential, myDiskSCFPotential

ro = 8.21
vo = 233.1
sigo = bovy_conversion.surfdens_in_msolpc2(vo=vo, ro=ro)
rhoo = bovy_conversion.dens_in_msolpc3(vo=vo, ro=ro)

#gas disk parameters (fixed in McMillan (2017)...)
Rd_HI = 7/ro
Rm_HI = 4/ro
zd_HI = 0.085/ro
Sigma0_HI = 53.1/sigo
Rd_H2 = 1.5/ro
Rm_H2 = 12/ro
zd_H2 = 0.045/ro
Sigma0_H2 = 2180/sigo

#parameters of best-fitting model in McMillan (2017)
#stellar disks
Sigma0_thin = 896/sigo
Rd_thin = 2.5/ro
zd_thin = 0.3/ro
Sigma0_thick = 183/sigo
Rd_thick = 3.02/ro
zd_thick = 0.9/ro
#bulge
rho0_bulge = 98.4/rhoo
Exemplo n.º 11
0
## Basic
import numpy as np
import sys, os, pdb

## galpy
from galpy import potential
from galpy.util import bovy_conversion as gpconv

# ----------------------------------------------------------------------------

# Module globals
ro=8.21
vo=233.1
sigo = gpconv.surfdens_in_msolpc2(vo=vo, ro=ro)
rhoo = gpconv.dens_in_msolpc3(vo=vo, ro=ro)

#gas disk parameters (fixed in McMillan (2017)...)
Rd_HI = 7/ro
Rm_HI = 4/ro
zd_HI = 0.085/ro
Sigma0_HI = 53.1/sigo
Rd_H2 = 1.5/ro
Rm_H2 = 12/ro
zd_H2 = 0.045/ro
Sigma0_H2 = 2180/sigo

#parameters of best-fitting model in McMillan (2017)
#stellar disks
Sigma0_thin = 896/sigo
Rd_thin = 2.5/ro
Exemplo n.º 12
0
def test_dens_in_msolpc3():
    #Test the scaling, as a 2nd derivative of the potential / G, should scale as velocity^2/position^2
    vofid, rofid= 200., 8.
    assert numpy.fabs(4.*bovy_conversion.dens_in_msolpc3(vofid,rofid)/bovy_conversion.dens_in_msolpc3(2.*vofid,rofid)-1.) < 10.**-10., 'dens_in_msolpc3 did not work as expected'
    assert numpy.fabs(.25*bovy_conversion.dens_in_msolpc3(vofid,rofid)/bovy_conversion.dens_in_msolpc3(vofid,2*rofid)-1.) < 10.**-10., 'dens_in_msolpc3 did not work as expected'
    return None
def like_func(params,c,surfrs,kzs,kzerrs,termdata,termsigma,fitc,fitvoro,
              dblexp,addpal5,addgd1,ro,vo,addgas):
    #Check ranges
    if params[0] < 0. or params[0] > 1.: return numpy.finfo(numpy.dtype(numpy.float64)).max
    if params[1] < 0. or params[1] > 1.: return numpy.finfo(numpy.dtype(numpy.float64)).max
    if (1.-params[0]-params[1]) < 0. or (1.-params[0]-params[1]) > 1.: return numpy.finfo(numpy.dtype(numpy.float64)).max
    if params[2] < numpy.log(1./_REFR0) or params[2] > numpy.log(8./_REFR0):
        return numpy.finfo(numpy.dtype(numpy.float64)).max
    if params[3] < numpy.log(0.05/_REFR0) or params[3] > numpy.log(1./_REFR0):
        return numpy.finfo(numpy.dtype(numpy.float64)).max
    if fitvoro and (params[7] <= 150./_REFV0 or params[7] > 290./_REFV0):
        return numpy.finfo(numpy.dtype(numpy.float64)).max
    if fitvoro and (params[8] <= 7./_REFR0 or params[8] > 9.4/_REFR0):
        return numpy.finfo(numpy.dtype(numpy.float64)).max
    if fitc and (params[7+2*fitvoro] <= 0. or params[7+2*fitvoro] > 4.):
        return numpy.finfo(numpy.dtype(numpy.float64)).max
    if fitvoro:
        ro, vo= _REFR0*params[8], _REFV0*params[7]
    #Setup potential
    pot= setup_potential(params,c,fitc,dblexp,ro,vo,fitvoro=fitvoro,
                         addgas=addgas)
    #Calculate model surface density at surfrs
    modelkzs= numpy.empty_like(surfrs)
    for ii in range(len(surfrs)):
        modelkzs[ii]= -potential.evaluatezforces(pot,
                                                 (ro-8.+surfrs[ii])/ro,
                                                 1.1/ro,
                                                 phi=0.)*bovy_conversion.force_in_2piGmsolpc2(vo,ro)
    out= 0.5*numpy.sum((kzs-modelkzs)**2./kzerrs**2.)
    #Add terminal velocities
    vrsun= params[5]
    vtsun= params[6]
    cl_glon, cl_vterm, cl_corr, mc_glon, mc_vterm, mc_corr= termdata
    #Calculate terminal velocities at data glon
    cl_vterm_model= numpy.zeros_like(cl_vterm)
    for ii in range(len(cl_glon)):
        cl_vterm_model[ii]= potential.vterm(pot,cl_glon[ii])
    cl_vterm_model+= vrsun*numpy.cos(cl_glon/180.*numpy.pi)\
        -vtsun*numpy.sin(cl_glon/180.*numpy.pi)
    mc_vterm_model= numpy.zeros_like(mc_vterm)
    for ii in range(len(mc_glon)):
        mc_vterm_model[ii]= potential.vterm(pot,mc_glon[ii])
    mc_vterm_model+= vrsun*numpy.cos(mc_glon/180.*numpy.pi)\
        -vtsun*numpy.sin(mc_glon/180.*numpy.pi)
    cl_dvterm= (cl_vterm-cl_vterm_model*vo)/termsigma
    mc_dvterm= (mc_vterm-mc_vterm_model*vo)/termsigma
    out+= 0.5*numpy.sum(cl_dvterm*numpy.dot(cl_corr,cl_dvterm))
    out+= 0.5*numpy.sum(mc_dvterm*numpy.dot(mc_corr,mc_dvterm))
    #Rotation curve constraint
    out-= logprior_dlnvcdlnr(potential.dvcircdR(pot,1.,phi=0.))
    #K dwarfs, Kz
    out+= 0.5*(-potential.evaluatezforces(pot,1.,1.1/ro,phi=0.)*bovy_conversion.force_in_2piGmsolpc2(vo,ro)-67.)**2./36.
    #K dwarfs, visible
    out+= 0.5*(visible_dens(pot,ro,vo)-55.)**2./25.
    #Local density prior
    localdens= potential.evaluateDensities(pot,1.,0.,phi=0.)*bovy_conversion.dens_in_msolpc3(vo,ro)
    out+= 0.5*(localdens-0.102)**2./0.01**2.
    #Bulge velocity dispersion
    out+= 0.5*(bulge_dispersion(pot,ro,vo)-117.)**2./225.
    #Mass at 60 kpc
    out+= 0.5*(mass60(pot,ro,vo)-4.)**2./0.7**2.
    #Pal5
    if addpal5:
        # q = 0.94 +/- 0.05 + add'l
        fp5= force_pal5(pot,23.46,ro,vo)
        out+= 0.5*(numpy.sqrt(2.*fp5[0]/fp5[1])-0.94)**2./0.05**2.
        out+= 0.5*(0.94**2.*(fp5[0]+0.8)+2.*(fp5[1]+1.82)+0.2)**2./0.6**2.
    #GD-1
    if addgd1:
        # q = 0.95 +/- 0.04 + add'l
        fg1= force_gd1(pot,ro,vo)
        out+= 0.5*(numpy.sqrt(6.675/12.5*fg1[0]/fg1[1])-0.95)**2./0.04**2.
        out+= 0.5*(0.95**2.*(fg1[0]+2.51)+6.675/12.5*(fg1[1]+1.47)+0.05)**2./0.3**2.
    # vc and ro measurements: vc=218 +/- 10 km/s, ro= 8.1 +/- 0.1 kpc
    out+= (vo-218.)**2./200.+(ro-8.1)**2./0.02
    if numpy.isnan(out): 
        return numpy.finfo(numpy.dtype(numpy.float64)).max
    else:
        return out
Exemplo n.º 14
0
    def __init__(self, amp=1., ro=None, vo=None, amp_units=None):
        """
        NAME:

           __init__

        PURPOSE:

           Initialize Force

        INPUT:

           amp - amplitude to be applied when evaluating the potential and its forces
           
           ro - physical distance scale (in kpc or as Quantity)

           vo - physical velocity scale (in km/s or as Quantity)

           amp_units - ('mass', 'velocity2', 'density') type of units that amp should have if it has units
           
        OUTPUT:

        HISTORY:
           2018-03-18 - Written to generalize Potential to force that may or may not be conservative - Bovy (UofT)
        """
        self._amp = amp
        # Parse ro and vo
        if ro is None:
            self._ro = config.__config__.getfloat('normalization', 'ro')
            self._roSet = False
        else:
            if _APY_LOADED and isinstance(ro, units.Quantity):
                ro = ro.to(units.kpc).value
            self._ro = ro
            self._roSet = True
        if vo is None:
            self._vo = config.__config__.getfloat('normalization', 'vo')
            self._voSet = False
        else:
            if _APY_LOADED and isinstance(vo, units.Quantity):
                vo = vo.to(units.km / units.s).value
            self._vo = vo
            self._voSet = True
        # Parse amp if it has units
        if _APY_LOADED and isinstance(self._amp, units.Quantity):
            # Try a bunch of possible units
            unitFound = False
            # velocity^2
            try:
                self._amp= self._amp.to(units.km**2/units.s**2).value\
                    /self._vo**2.
            except units.UnitConversionError:
                pass
            else:
                unitFound = True
                if not amp_units == 'velocity2':
                    raise units.UnitConversionError(
                        'amp= parameter of %s should have units of %s, but has units of velocity2 instead'
                        % (type(self).__name__, amp_units))
            if not unitFound:
                # mass
                try:
                    self._amp= self._amp.to(units.Msun).value\
                        /bovy_conversion.mass_in_msol(self._vo,self._ro)
                except units.UnitConversionError:
                    pass
                else:
                    unitFound = True
                    if not amp_units == 'mass':
                        raise units.UnitConversionError(
                            'amp= parameter of %s should have units of %s, but has units of mass instead'
                            % (type(self).__name__, amp_units))
            if not unitFound:
                # G x mass
                try:
                    self._amp= self._amp.to(units.pc*units.km**2/units.s**2)\
                        .value\
                        /bovy_conversion.mass_in_msol(self._vo,self._ro)\
                        /bovy_conversion._G
                except units.UnitConversionError:
                    pass
                else:
                    unitFound = True
                    if not amp_units == 'mass':
                        raise units.UnitConversionError(
                            'amp= parameter of %s should have units of %s, but has units of G x mass instead'
                            % (type(self).__name__, amp_units))
            if not unitFound:
                # density
                try:
                    self._amp= self._amp.to(units.Msun/units.pc**3).value\
                        /bovy_conversion.dens_in_msolpc3(self._vo,self._ro)
                except units.UnitConversionError:
                    pass
                else:
                    unitFound = True
                    if not amp_units == 'density':
                        raise units.UnitConversionError(
                            'amp= parameter of %s should have units of %s, but has units of density instead'
                            % (type(self).__name__, amp_units))
            if not unitFound:
                # G x density
                try:
                    self._amp= self._amp.to(units.km**2/units.s**2\
                                                /units.pc**2).value\
                        /bovy_conversion.dens_in_msolpc3(self._vo,self._ro)\
                        /bovy_conversion._G
                except units.UnitConversionError:
                    pass
                else:
                    unitFound = True
                    if not amp_units == 'density':
                        raise units.UnitConversionError(
                            'amp= parameter of %s should have units of %s, but has units of G x density instead'
                            % (type(self).__name__, amp_units))
            if not unitFound:
                # surface density
                try:
                    self._amp= self._amp.to(units.Msun/units.pc**2).value\
                        /bovy_conversion.surfdens_in_msolpc2(self._vo,self._ro)
                except units.UnitConversionError:
                    pass
                else:
                    unitFound = True
                    if not amp_units == 'surfacedensity':
                        raise units.UnitConversionError(
                            'amp= parameter of %s should have units of %s, but has units of surface density instead'
                            % (type(self).__name__, amp_units))
            if not unitFound:
                # G x surface density
                try:
                    self._amp= self._amp.to(units.km**2/units.s**2\
                                                /units.pc).value\
                        /bovy_conversion.surfdens_in_msolpc2(self._vo,self._ro)\
                        /bovy_conversion._G
                except units.UnitConversionError:
                    pass
                else:
                    unitFound = True
                    if not amp_units == 'surfacedensity':
                        raise units.UnitConversionError(
                            'amp= parameter of %s should have units of %s, but has units of G x surface density instead'
                            % (type(self).__name__, amp_units))
            if not unitFound:
                raise units.UnitConversionError(
                    'amp= parameter of %s should have units of %s; given units are not understood'
                    % (type(self).__name__, amp_units))
            else:
                # When amplitude is given with units, turn on physical output
                self._roSet = True
                self._voSet = True
        return None
def like_func(params,surfrs,kzs,kzerrs,
              termdata,options):
    #Check ranges
    if params[0] < 0. or params[0] > 1.: return numpy.finfo(numpy.dtype(numpy.float64)).max
    if params[1] < 0. or params[1] > 1.: return numpy.finfo(numpy.dtype(numpy.float64)).max
    if options.twodisks and (params[2] < 0. or params[2] > 1.): return numpy.finfo(numpy.dtype(numpy.float64)).max
    if (1.-params[0]-params[1]-options.twodisks*params[2]) < 0. or (1.-params[0]-params[1]-options.twodisks*params[2]) > 1.: return numpy.finfo(numpy.dtype(numpy.float64)).max
    if params[2+options.twodisks] < numpy.log(1./_REFR0) or params[2+options.twodisks] > numpy.log(8./_REFR0):
        return numpy.finfo(numpy.dtype(numpy.float64)).max
    if params[3+options.twodisks] < numpy.log(0.05/_REFR0) or params[3+options.twodisks] > numpy.log(1./_REFR0):
        return numpy.finfo(numpy.dtype(numpy.float64)).max
    if options.twodisks:
        if params[5] < numpy.log(1./_REFR0) or params[5] > numpy.log(8./_REFR0):
            return numpy.finfo(numpy.dtype(numpy.float64)).max
        if params[6] < numpy.log(0.05/_REFR0) or params[6] > numpy.log(1./_REFR0):
            return numpy.finfo(numpy.dtype(numpy.float64)).max
    #Setup potential
    if options.twodisks:
        pot= [potential.PowerSphericalPotentialwCutoff(normalize=1.-params[0]-params[1]-params[2],
                                                       alpha=1.8,rc=1.9/_REFR0),
              potential.MiyamotoNagaiPotential(normalize=params[0],
                                               a=numpy.exp(params[3]),
                                               b=numpy.exp(params[4])),
              potential.MiyamotoNagaiPotential(normalize=params[1],
                                               a=numpy.exp(params[5]),
                                               b=numpy.exp(params[6])),
              potential.NFWPotential(normalize=params[2],
                                     a=numpy.exp(params[7]))]
    else:
        pot= [potential.PowerSphericalPotentialwCutoff(normalize=1.-params[0]-params[1],
                                                       alpha=1.8,rc=1.9/_REFR0),
              potential.MiyamotoNagaiPotential(normalize=params[0],
                                               a=numpy.exp(params[2]),
                                               b=numpy.exp(params[3])),
              potential.NFWPotential(normalize=params[1],a=numpy.exp(params[4]))]
    #Calculate model surface density at surfrs
    modelkzs= numpy.empty_like(surfrs)
    for ii in range(len(surfrs)):
        modelkzs[ii]= -potential.evaluatezforces(surfrs[ii]/_REFR0,1.1/_REFR0,
                                                 pot)*bovy_conversion.force_in_2piGmsolpc2(_REFV0,_REFR0)
    out= 0.5*numpy.sum((kzs-modelkzs)**2./kzerrs**2.)
    #Add terminal velocities
    vrsun= params[5+3*options.twodisks]
    vtsun= params[6+3*options.twodisks]
    cl_glon, cl_vterm, cl_corr, mc_glon, mc_vterm, mc_corr= termdata
    #Calculate terminal velocities at data glon
    cl_vterm_model= numpy.zeros_like(cl_vterm)
    for ii in range(len(cl_glon)):
        cl_vterm_model[ii]= potential.vterm(pot,cl_glon[ii])
    cl_vterm_model+= vrsun*numpy.cos(cl_glon/180.*numpy.pi)\
        -vtsun*numpy.sin(cl_glon/180.*numpy.pi)
    mc_vterm_model= numpy.zeros_like(mc_vterm)
    for ii in range(len(mc_glon)):
        mc_vterm_model[ii]= potential.vterm(pot,mc_glon[ii])
    mc_vterm_model+= vrsun*numpy.cos(mc_glon/180.*numpy.pi)\
        -vtsun*numpy.sin(mc_glon/180.*numpy.pi)
    cl_dvterm= (cl_vterm-cl_vterm_model)/options.termsigma*_REFV0
    mc_dvterm= (mc_vterm-mc_vterm_model)/options.termsigma*_REFV0
    out+= 0.5*numpy.sum(cl_dvterm*numpy.dot(cl_corr,cl_dvterm))
    out+= 0.5*numpy.sum(mc_dvterm*numpy.dot(mc_corr,mc_dvterm))
    #Rotation curve constraint
    out-= logprior_dlnvcdlnr(potential.dvcircdR(pot,1.))
    #K dwarfs, Kz
    out+= 0.5*(-potential.evaluatezforces(1.,1.1/_REFR0,pot)*bovy_conversion.force_in_2piGmsolpc2(_REFV0,_REFR0)-67.)**2./36.
    #K dwarfs, visible
    out+= 0.5*(visible_dens(pot,options)-55.)**2./25.
    #Local density prior
    localdens= potential.evaluateDensities(1.,0.,pot)*bovy_conversion.dens_in_msolpc3(_REFV0,_REFR0)
    out+= 0.5*(localdens-0.102)**2./0.01**2.
    #Bulge velocity dispersion
    out+= 0.5*(bulge_dispersion(pot)-117.)**2./225.
    #Mass at 60 kpc
    out+= 0.5*(mass60(pot,options)-4.)**2./0.7**2.
    #Concentration prior?
    return out
Exemplo n.º 16
0
    def __init__(self,amp=1.,ro=None,vo=None,amp_units=None):
        """
        NAME:

           __init__

        PURPOSE:

           Initialize Force

        INPUT:

           amp - amplitude to be applied when evaluating the potential and its forces
           
           ro - physical distance scale (in kpc or as Quantity)

           vo - physical velocity scale (in km/s or as Quantity)

           amp_units - ('mass', 'velocity2', 'density') type of units that amp should have if it has units
           
        OUTPUT:

        HISTORY:
           2018-03-18 - Written to generalize Potential to force that may or may not be conservative - Bovy (UofT)
        """
        self._amp= amp
        # Parse ro and vo
        if ro is None:
            self._ro= config.__config__.getfloat('normalization','ro')
            self._roSet= False
        else:
            if _APY_LOADED and isinstance(ro,units.Quantity):
                ro= ro.to(units.kpc).value
            self._ro= ro
            self._roSet= True
        if vo is None:
            self._vo= config.__config__.getfloat('normalization','vo')
            self._voSet= False
        else:
            if _APY_LOADED and isinstance(vo,units.Quantity):
                vo= vo.to(units.km/units.s).value
            self._vo= vo
            self._voSet= True
        # Parse amp if it has units
        if _APY_LOADED and isinstance(self._amp,units.Quantity):
            # Try a bunch of possible units
            unitFound= False
            # velocity^2
            try:
                self._amp= self._amp.to(units.km**2/units.s**2).value\
                    /self._vo**2.
            except units.UnitConversionError: pass
            else:
                unitFound= True
                if not amp_units == 'velocity2':
                    raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of velocity2 instead' % (type(self).__name__,amp_units))
            if not unitFound:
                # mass
                try:
                    self._amp= self._amp.to(units.Msun).value\
                        /bovy_conversion.mass_in_msol(self._vo,self._ro)
                except units.UnitConversionError: pass
                else:
                    unitFound= True
                    if not amp_units == 'mass':
                        raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of mass instead' % (type(self).__name__,amp_units))
            if not unitFound:
                # G x mass
                try:
                    self._amp= self._amp.to(units.pc*units.km**2/units.s**2)\
                        .value\
                        /bovy_conversion.mass_in_msol(self._vo,self._ro)\
                        /bovy_conversion._G
                except units.UnitConversionError: pass
                else:
                    unitFound= True
                    if not amp_units == 'mass':
                        raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of G x mass instead' % (type(self).__name__,amp_units))
            if not unitFound:
                # density
                try:
                    self._amp= self._amp.to(units.Msun/units.pc**3).value\
                        /bovy_conversion.dens_in_msolpc3(self._vo,self._ro)
                except units.UnitConversionError: pass
                else:
                    unitFound= True
                    if not amp_units == 'density':
                        raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of density instead' % (type(self).__name__,amp_units))
            if not unitFound:
                # G x density
                try:
                    self._amp= self._amp.to(units.km**2/units.s**2\
                                                /units.pc**2).value\
                        /bovy_conversion.dens_in_msolpc3(self._vo,self._ro)\
                        /bovy_conversion._G
                except units.UnitConversionError: pass
                else:
                    unitFound= True
                    if not amp_units == 'density':
                        raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of G x density instead' % (type(self).__name__,amp_units))
            if not unitFound:
                # surface density
                try:
                    self._amp= self._amp.to(units.Msun/units.pc**2).value\
                        /bovy_conversion.surfdens_in_msolpc2(self._vo,self._ro)
                except units.UnitConversionError: pass
                else:
                    unitFound= True
                    if not amp_units == 'surfacedensity':
                        raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of surface density instead' % (type(self).__name__,amp_units))
            if not unitFound:
                # G x surface density
                try:
                    self._amp= self._amp.to(units.km**2/units.s**2\
                                                /units.pc).value\
                        /bovy_conversion.surfdens_in_msolpc2(self._vo,self._ro)\
                        /bovy_conversion._G
                except units.UnitConversionError: pass
                else:
                    unitFound= True
                    if not amp_units == 'surfacedensity':
                        raise units.UnitConversionError('amp= parameter of %s should have units of %s, but has units of G x surface density instead' % (type(self).__name__,amp_units))
            if not unitFound:
                raise units.UnitConversionError('amp= parameter of %s should have units of %s; given units are not understood' % (type(self).__name__,amp_units))    
            else:
                # When amplitude is given with units, turn on physical output
                self._roSet= True
                self._voSet= True
        return None
def like_func(
    params: Sequence,
    c: float,
    surfrs: list,
    kzs,
    kzerrs,
    termdata,
    termsigma,
    fitc,
    fitvoro,
    dblexp,
    addpal5,
    addgd1,
    ro: float,
    vo: float,
    addgas: bool,
):
    """Likelihood Function.

    Parameters
    ----------
    params: list
    c: float
    surfrs: list
    kzs
    kzerrs
    termdata
    termsigma
    fitc
    fitvoro
    dblexp
    addpal5
    addgd1
    ro: float
    vo: float
    addgas: bool

    Returns
    -------
    float

    """
    # --------------------------------------------------------------------

    from .potential import setup_potential  # TODO how do not internally?

    # TODO use a more generic switcher so can use any stream
    from ..streams.pal5.pal5_util import force_pal5
    from ..streams.gd1.gd1_util import force_gd1

    # --------------------------------------------------------------------
    # Check ranges

    if params[0] < 0.0 or params[0] > 1.0:
        return np.finfo(np.dtype(np.float64)).max
    elif params[1] < 0.0 or params[1] > 1.0:
        return np.finfo(np.dtype(np.float64)).max
    elif (1.0 - params[0] - params[1]) < 0.0 or (1.0 - params[0] - params[1]) > 1.0:
        return np.finfo(np.dtype(np.float64)).max
    elif params[2] < np.log(1.0 / REFR0) or params[2] > np.log(8.0 / REFR0):
        return np.finfo(np.dtype(np.float64)).max
    elif params[3] < np.log(0.05 / REFR0) or params[3] > np.log(1.0 / REFR0):
        return np.finfo(np.dtype(np.float64)).max
    elif fitvoro and (params[7] <= 150.0 / REFV0 or params[7] > 290.0 / REFV0):
        return np.finfo(np.dtype(np.float64)).max
    elif fitvoro and (params[8] <= 7.0 / REFR0 or params[8] > 9.4 / REFR0):
        return np.finfo(np.dtype(np.float64)).max
    elif fitc and (params[7 + 2 * fitvoro] <= 0.0 or params[7 + 2 * fitvoro] > 4.0):
        return np.finfo(np.dtype(np.float64)).max

    # --------------------------------------------------------------------

    if fitvoro:
        ro, vo = REFR0 * params[8], REFV0 * params[7]

    # Setup potential
    pot = setup_potential(
        params, c, fitc, dblexp, ro, vo, fitvoro=fitvoro, addgas=addgas
    )

    # Calculate model surface density at surfrs
    modelkzs = np.empty_like(surfrs)
    for ii in range(len(surfrs)):
        modelkzs[ii] = -potential.evaluatezforces(
            pot, (ro - 8.0 + surfrs[ii]) / ro, 1.1 / ro, phi=0.0
        ) * bovy_conversion.force_in_2piGmsolpc2(vo, ro)
    out = 0.5 * np.sum((kzs - modelkzs) ** 2.0 / kzerrs ** 2.0)

    # Add terminal velocities
    vrsun = params[5]
    vtsun = params[6]
    cl_glon, cl_vterm, cl_corr, mc_glon, mc_vterm, mc_corr = termdata

    # Calculate terminal velocities at data glon
    cl_vterm_model = np.zeros_like(cl_vterm)
    for ii in range(len(cl_glon)):
        cl_vterm_model[ii] = potential.vterm(pot, cl_glon[ii])
    cl_vterm_model += vrsun * np.cos(cl_glon / 180.0 * np.pi) - vtsun * np.sin(
        cl_glon / 180.0 * np.pi
    )
    mc_vterm_model = np.zeros_like(mc_vterm)
    for ii in range(len(mc_glon)):
        mc_vterm_model[ii] = potential.vterm(pot, mc_glon[ii])
    mc_vterm_model += vrsun * np.cos(mc_glon / 180.0 * np.pi) - vtsun * np.sin(
        mc_glon / 180.0 * np.pi
    )
    cl_dvterm = (cl_vterm - cl_vterm_model * vo) / termsigma
    mc_dvterm = (mc_vterm - mc_vterm_model * vo) / termsigma
    out += 0.5 * np.sum(cl_dvterm * np.dot(cl_corr, cl_dvterm))
    out += 0.5 * np.sum(mc_dvterm * np.dot(mc_corr, mc_dvterm))

    # Rotation curve constraint
    out -= logprior_dlnvcdlnr(potential.dvcircdR(pot, 1.0, phi=0.0))

    # K dwarfs, Kz
    out += (
        0.5
        * (
            -potential.evaluatezforces(pot, 1.0, 1.1 / ro, phi=0.0)
            * bovy_conversion.force_in_2piGmsolpc2(vo, ro)
            - 67.0
        )
        ** 2.0
        / 36.0
    )
    # K dwarfs, visible
    out += 0.5 * (visible_dens(pot, ro, vo) - 55.0) ** 2.0 / 25.0
    # Local density prior
    localdens = potential.evaluateDensities(
        pot, 1.0, 0.0, phi=0.0
    ) * bovy_conversion.dens_in_msolpc3(vo, ro)
    out += 0.5 * (localdens - 0.102) ** 2.0 / 0.01 ** 2.0
    # Bulge velocity dispersion
    out += 0.5 * (bulge_dispersion(pot, ro, vo) - 117.0) ** 2.0 / 225.0
    # Mass at 60 kpc
    out += 0.5 * (mass60(pot, ro, vo) - 4.0) ** 2.0 / 0.7 ** 2.0

    # Pal5
    if addpal5:
        # q = 0.94 +/- 0.05 + add'l
        fp5 = force_pal5(pot, 23.46, ro, vo)
        out += 0.5 * (np.sqrt(2.0 * fp5[0] / fp5[1]) - 0.94) ** 2.0 / 0.05 ** 2.0
        out += (
            0.5
            * (0.94 ** 2.0 * (fp5[0] + 0.8) + 2.0 * (fp5[1] + 1.82) + 0.2) ** 2.0
            / 0.6 ** 2.0
        )

    # GD-1
    if addgd1:
        # q = 0.95 +/- 0.04 + add'l
        fg1 = force_gd1(pot, ro, vo)
        out += (
            0.5 * (np.sqrt(6.675 / 12.5 * fg1[0] / fg1[1]) - 0.95) ** 2.0 / 0.04 ** 2.0
        )
        out += (
            0.5
            * (0.95 ** 2.0 * (fg1[0] + 2.51) + 6.675 / 12.5 * (fg1[1] + 1.47) + 0.05)
            ** 2.0
            / 0.3 ** 2.0
        )

    # vc and ro measurements: vc=218 +/- 10 km/s, ro= 8.1 +/- 0.1 kpc
    out += (vo - 218.0) ** 2.0 / 200.0 + (ro - 8.1) ** 2.0 / 0.02

    if np.isnan(out):
        return np.finfo(np.dtype(np.float64)).max
    else:
        return out
Exemplo n.º 18
0
def rlimiting(
    cluster,
    pot=MWPotential2014,
    rgc=None,
    r0=8.0,
    v0=220.0,
    nrad=20,
    projected=False,
    plot=False,
    verbose=False,
    **kwargs
):
    """
    NAME:

       rlimiting

    PURPOSE:

       Calculate limiting radius of the cluster
       --> The limiting radius is defined to be where the cluster's density reaches the local background density of the host galaxy

    INPUT:

       cluster - StarCluster instance

       pot - GALPY potential used to calculate actions

       rgc - Set galactocentric distance at which the tidal radius is to be evaluated

       r0,v0 - GALPY scaling parameters

       nrad - number of radial bins used to calculate density profile (Default: 20)

       projected - use projected values (Default: False)

       plot - plot the density profile and mark the limiting radius of the cluster (Default: False)

    KWARGS:

       Same as ..util.plots.nplot

    OUTPUT:

        rl

    HISTORY:

       2019 - Written - Webb (UofT)

    """
    units0, origin0 = save_cluster(cluster)

    cluster.to_centre()
    cluster.to_galpy()


    if rgc != None:
        R = rgc / r0
        z = 0.0
    else:
        R = np.sqrt(cluster.xgc ** 2.0 + cluster.ygc ** 2.0)
        z = cluster.zgc

    # Calculate local density:
    rho_local = potential.evaluateDensities(
        pot, R, z, ro=r0, vo=v0, use_physical=False
    ) / bovy_conversion.dens_in_msolpc3(ro=r0, vo=v0)

    rprof, pprof, nprof = rho_prof(cluster, nrad=nrad, projected=projected)

    if pprof[-1] > rho_local:
        rl = rprof[-1]
    elif pprof[0] < rho_local:
        rl = 0.0
    else:
        indx = np.argwhere(pprof < rho_local)[0][0]
        r1 = (rprof[indx - 1], pprof[indx - 1])
        r2 = (rprof[indx], pprof[indx])

        rl = interpolate(r1, r2, y=rho_local)

    if verbose:
        print("FINAL RL: ", rl * r0 * 1000.0, "pc")

    if units0 == "realpc":
        rl *= 1000.0 * r0
    elif units0 == "realkpc":
        rl *= r0
    elif units0 == "nbody":
        rl *= 1000.0 * r0 / cluster.rbar

    cluster.rl = rl

    return_cluster(cluster, units0, origin0, do_order=True, do_key_params=True)

    if plot:
        if verbose:
            print("LOCAL DENSITY = ", rho_local)

        filename = kwargs.pop("filename", None)
        overplot = kwargs.pop("overplot", False)

        if cluster.units == "nbody":
            rprof *= r0 * 1000.0 / cluster.rbar
            pprof *= (
                bovy_conversion.dens_in_msolpc3(ro=r0, vo=v0)
                * (cluster.rbar ** 3.0)
                / cluster.zmbar
            )
            rho_local *= (
                bovy_conversion.dens_in_msolpc3(ro=r0, vo=v0)
                * (cluster.rbar ** 3.0)
                / cluster.zmbar
            )
            xunits = " (NBODY)"
            yunits = " (NBODY)"
        elif cluster.units == "realpc":
            rprof *= r0 * 1000.0
            pprof *= bovy_conversion.dens_in_msolpc3(ro=r0, vo=v0)
            rho_local *= bovy_conversion.dens_in_msolpc3(ro=r0, vo=v0)
            xunits = " (pc)"
            if projected:
                yunits = " Msun/pc^2"
            else:
                yunits = " Msun/pc^3"
        elif cluster.units == "realkpc":
            rprof *= r0
            pprof *= bovy_conversion.dens_in_msolpc3(ro=r0, vo=v0) * (1000.0 ** 3.0)
            rho_local *= bovy_conversion.dens_in_msolpc3(ro=r0, vo=v0) * (1000.0 ** 3.0)

            xunits = " (kpc)"
            if projected:
                yunits = " Msun/kpc^2"
            else:
                yunits = " Msun/kpc^3"
        elif cluster.units == "galpy":
            xunits = " (GALPY)"
            yunits = " (GALPY)"

        else:
            xunits = ""
            yunits = ""

        x, y, n = rprof, pprof, nprof
        nlplot(
            x,
            y,
            xlabel=r"$R %s$" % (xunits),
            ylabel=r"$\rho %s$" % (yunits),
            title="Time = %f" % cluster.tphys,
            log=True,
            overplot=overplot,
            filename=filename,
        )
        nlplot(x, np.ones(len(x)) * rho_local, "--", overplot=True)
        nlplot(np.ones(len(y)) * rl, y, "--", overplot=True)

        if filename != None:
            plt.savefig(filename)

    return rl