Esempio n. 1
0
def test_trailingwleadingimpact_error():
    #Imports
    from galpy.df import streamgapdf
    from galpy.orbit import Orbit
    from galpy.potential import LogarithmicHaloPotential
    from galpy.actionAngle import actionAngleIsochroneApprox
    from galpy.util import conversion  #for unit conversions
    lp = LogarithmicHaloPotential(normalize=1., q=0.9)
    aAI = actionAngleIsochroneApprox(pot=lp, b=0.8)
    prog_unp_peri = Orbit([
        2.6556151742081835, 0.2183747276300308, 0.67876510797240575,
        -2.0143395648974671, -0.3273737682604374, 0.24218273922966019
    ])
    V0, R0 = 220., 8.
    sigv = 0.365 * (10. / 2.)**(1. / 3.)  # km/s
    with pytest.raises(ValueError) as excinfo:
        dum= streamgapdf(sigv/V0,progenitor=prog_unp_peri,pot=lp,aA=aAI,
                         leading=False,nTrackChunks=26,
                         nTrackIterations=1,
                         sigMeanOffset=4.5,
                         tdisrupt=10.88\
                             /conversion.time_in_Gyr(V0,R0),
                         Vnorm=V0,Rnorm=R0,
                         impactb=0.,
                         subhalovel=numpy.array([6.82200571,132.7700529,
                                                 149.4174464])/V0,
                         timpact=0.88/conversion.time_in_Gyr(V0,R0),
                         impact_angle=2.34,
                         GM=10.**-2.\
                             /conversion.mass_in_1010msol(V0,R0),
                         rs=0.625/R0)
    return None
def parse_times(times, age):
    if 'sampling' in times:
        nsam = int(times.split('sampling')[0])
        return [
            float(ti) / conversion.time_in_Gyr(vo, ro)
            for ti in numpy.arange(1, nsam + 1) / (nsam + 1.) * age
        ]
    return [
        float(ti) / conversion.time_in_Gyr(vo, ro) for ti in times.split(',')
    ]
Esempio n. 3
0
def test_time_in_Gyr():
    #Test the scaling, should scale as position/velocity
    vofid, rofid = 200., 8.
    assert numpy.fabs(0.5 * conversion.time_in_Gyr(vofid, rofid) /
                      conversion.time_in_Gyr(2. * vofid, rofid) -
                      1.) < 10.**-10., 'time_in_Gyr did not work as expected'
    assert numpy.fabs(2. * conversion.time_in_Gyr(vofid, rofid) /
                      conversion.time_in_Gyr(vofid, 2 * rofid) -
                      1.) < 10.**-10., 'time_in_Gyr did not work as expected'
    return None
Esempio n. 4
0
def test_ChandrasekharDynamicalFrictionForce_constLambda():
    # Test that the ChandrasekharDynamicalFrictionForce with constant Lambda
    # agrees with analytical solutions for circular orbits:
    # assuming that a mass remains on a circular orbit in an isothermal halo
    # with velocity dispersion sigma and for constant Lambda:
    # r_final^2 - r_initial^2 = -0.604 ln(Lambda) GM/sigma t
    # (e.g., B&T08, p. 648)
    from galpy.util import conversion
    from galpy.orbit import Orbit
    ro, vo = 8., 220.
    # Parameters
    GMs = 10.**9. / conversion.mass_in_msol(vo, ro)
    const_lnLambda = 7.
    r_init = 2.
    dt = 2. / conversion.time_in_Gyr(vo, ro)
    # Compute
    lp = potential.LogarithmicHaloPotential(normalize=1., q=1.)
    cdfc= potential.ChandrasekharDynamicalFrictionForce(\
        GMs=GMs,const_lnLambda=const_lnLambda,
        dens=lp) # don't provide sigmar, so it gets computed using galpy.df.jeans
    o = Orbit([r_init, 0., 1., 0., 0., 0.])
    ts = numpy.linspace(0., dt, 1001)
    o.integrate(ts, [lp, cdfc], method='odeint')
    r_pred = numpy.sqrt(o.r()**2. -
                        0.604 * const_lnLambda * GMs * numpy.sqrt(2.) * dt)
    assert numpy.fabs(
        r_pred - o.r(ts[-1])
    ) < 0.01, 'ChandrasekharDynamicalFrictionForce with constant lnLambda for circular orbits does not agree with analytical prediction'
    return None
Esempio n. 5
0
def test_ChandrasekharDynamicalFrictionForce_varLambda():
    # Test that dynamical friction with variable Lambda for small r ranges
    # gives ~ the same result as using a constant Lambda that is the mean of
    # the variable lambda
    # Also tests that giving an axisymmetric list of potentials for the
    # density works
    from galpy.util import conversion
    from galpy.orbit import Orbit
    ro, vo = 8., 220.
    # Parameters
    GMs = 10.**9. / conversion.mass_in_msol(vo, ro)
    r_init = 3.
    dt = 2. / conversion.time_in_Gyr(vo, ro)
    # Compute evolution with variable ln Lambda
    cdf= potential.ChandrasekharDynamicalFrictionForce(\
        GMs=GMs,rhm=0.125,
        dens=potential.MWPotential2014,sigmar=lambda r: 1./numpy.sqrt(2.))
    o = Orbit([r_init, 0., 1., 0., 0., 0.])
    ts = numpy.linspace(0., dt, 1001)
    o.integrate(ts, [potential.MWPotential2014, cdf], method='odeint')
    lnLs = numpy.array([
        cdf.lnLambda(r, v) for (r, v) in zip(
            o.r(ts), numpy.sqrt(o.vx(ts)**2. + o.vy(ts)**2. + o.vz(ts)**2.))
    ])
    cdfc= potential.ChandrasekharDynamicalFrictionForce(\
        GMs=GMs,rhm=0.125,const_lnLambda=numpy.mean(lnLs),
        dens=potential.MWPotential2014,sigmar=lambda r: 1./numpy.sqrt(2.))
    oc = o()
    oc.integrate(ts, [potential.MWPotential2014, cdfc], method='odeint')
    assert numpy.fabs(
        oc.r(ts[-1]) - o.r(ts[-1])
    ) < 0.05, 'ChandrasekharDynamicalFrictionForce with variable lnLambda for a short radial range is not close to the calculation using a constant lnLambda'
    return None
Esempio n. 6
0
def test_sanders15_setup():
    #Imports
    from galpy.df import streamdf, streamgapdf
    from galpy.orbit import Orbit
    from galpy.potential import LogarithmicHaloPotential
    from galpy.actionAngle import actionAngleIsochroneApprox
    from galpy.util import conversion  #for unit conversions
    lp = LogarithmicHaloPotential(normalize=1., q=0.9)
    aAI = actionAngleIsochroneApprox(pot=lp, b=0.8)
    prog_unp_peri = Orbit([
        2.6556151742081835, 0.2183747276300308, 0.67876510797240575,
        -2.0143395648974671, -0.3273737682604374, 0.24218273922966019
    ])
    global sdf_sanders15
    V0, R0 = 220., 8.
    sigv = 0.365 * (10. / 2.)**(1. / 3.)  # km/s
    sdf_sanders15= streamgapdf(sigv/V0,progenitor=prog_unp_peri,pot=lp,aA=aAI,
                               leading=False,nTrackChunks=26,
                               nTrackIterations=1,
                               sigMeanOffset=4.5,
                               tdisrupt=10.88\
                                   /conversion.time_in_Gyr(V0,R0),
                               Vnorm=V0,Rnorm=R0,
                               impactb=0.,
                               subhalovel=numpy.array([6.82200571,132.7700529,
                                                       149.4174464])/V0,
                               timpact=0.88/conversion.time_in_Gyr(V0,R0),
                               impact_angle=-2.34,
                               GM=10.**-2.\
                                   /conversion.mass_in_1010msol(V0,R0),
                               rs=0.625/R0)
    assert not sdf_sanders15 is None, 'sanders15 streamgapdf setup did not work'
    # Also setup the unperturbed model
    global sdf_sanders15_unp
    sdf_sanders15_unp= streamdf(sigv/V0,progenitor=prog_unp_peri,pot=lp,aA=aAI,
                               leading=False,nTrackChunks=26,
                               nTrackIterations=1,
                               sigMeanOffset=4.5,
                               tdisrupt=10.88\
                                   /conversion.time_in_Gyr(V0,R0),
                               Vnorm=V0,Rnorm=R0)
    assert not sdf_sanders15_unp is None, \
        'sanders15 unperturbed streamdf setup did not work'
    return None
Esempio n. 7
0
def test_units():
    # Import changed becaose of bovy_conversion --> conversion name change
    from galpy.util import 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
    # Loosen tolerances including mass bc of 0.025% change in Msun in astropyv2
    assert numpy.fabs((conversion.dens_in_msolpc3(220., 8.) - 0.175790330079) /
                      0.175790330079) < 0.0003, '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) < 0.0003, '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) < 0.0003, '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
Esempio n. 8
0
def run_orbitIntegration_comparison(orb,pot,tmax,vo,ro,tol=0.01):
    # Integrate in galpy
    ts= numpy.linspace(0.,tmax/conversion.time_in_Gyr(vo,ro),1001)
    orb.integrate(ts,pot)

    # Integrate with amuse
    x,y,z,vx,vy,vz=integrate_amuse(orb,pot,tmax | units.Gyr, vo,ro)

    # Read and compare

    xdiff= numpy.fabs((x-orb.x(ts[-1]))/x)
    ydiff= numpy.fabs((y-orb.y(ts[-1]))/y)
    zdiff= numpy.fabs((z-orb.z(ts[-1]))/z)
    vxdiff= numpy.fabs((vx-orb.vx(ts[-1]))/vx)
    vydiff= numpy.fabs((vy-orb.vy(ts[-1]))/vy)
    vzdiff= numpy.fabs((vz-orb.vz(ts[-1]))/vz)
    assert xdiff < tol, 'galpy and amuse orbit integration inconsistent for x by %g' % xdiff
    assert ydiff < tol, 'galpy and amuse orbit integration inconsistent for y by %g' % ydiff
    assert zdiff < tol, 'galpy and amuse orbit integration inconsistent for z by %g' % zdiff
    assert vxdiff < tol, 'galpy and amuse orbit integration inconsistent for vx by %g' % vxdiff
    assert vydiff < tol, 'galpy and amuse orbit integration inconsistent for vy by %g' % vydiff
    assert vzdiff < tol, 'galpy and amuse orbit integration inconsistent for vz by %g' % vzdiff

    return None
def setup_mockgd1model(leading=True,
                       pot=MWPotential2014,
                       timpact=None,
                       Zsun=0.025,
                       hernquist=True,
                       isob=0.8,
                       age=9.,
                       sigv=0.46,
                       singleImpact=False,
                       length_factor=1.,
                       **kwargs):

    aAI = actionAngleIsochroneApprox(pot=pot, b=isob)
    obs = Orbit.from_name("GD1")

    if timpact is None:
        sdf = streamdf(sigv / 220.,
                       progenitor=obs,
                       pot=pot,
                       aA=aAI,
                       leading=leading,
                       nTrackChunks=11,
                       vsun=[-11.1, 244., 7.25],
                       Zsun=Zsun,
                       tdisrupt=age / conversion.time_in_Gyr(V0, R0),
                       vo=V0,
                       ro=R0)
    elif singleImpact:
        sdf = streamgapdf(sigv / 220.,
                          progenitor=obs,
                          pot=pot,
                          aA=aAI,
                          leading=leading,
                          nTrackChunks=11,
                          vsun=[-11.1, 244., 7.25],
                          Zsun=Zsun,
                          tdisrupt=age / conversion.time_in_Gyr(V0, R0),
                          vo=V0,
                          ro=R0,
                          timpact=timpact,
                          spline_order=3,
                          hernquist=hernquist,
                          **kwargs)
    else:
        sdf = streampepperdf(sigv / 220.,
                             progenitor=obs,
                             pot=pot,
                             aA=aAI,
                             leading=leading,
                             nTrackChunks=101,
                             vsun=[-11.1, 244., 7.25],
                             Zsun=Zsun,
                             tdisrupt=age / conversion.time_in_Gyr(V0, R0),
                             vo=V0,
                             ro=R0,
                             timpact=timpact,
                             spline_order=1,
                             hernquist=hernquist,
                             length_factor=length_factor)
    sdf.turn_physical_off()  #original
    #obs.turn_physical_off()
    return sdf
Esempio n. 10
0
class Snapshot():

    MLU = 8.  #kpc
    MVU = 220.  #km/s
    MTU = time_in_Gyr(MVU, MLU) * 1000.  #Myr
    MMU = mass_in_msol(MVU, MLU)  # msol

    def __init__(self,
                 Filename,
                 Np,
                 hf=0.4,
                 df=0.5,
                 bf=0.1,
                 Nslice=10,
                 dt=0.0078125,
                 frac=True):

        self.Filename = Filename
        self.Np = Np
        if frac:
            self.Nh = int(self.Np * hf)
            self.Nd = int(self.Np * df)
            self.Nb = int(self.Np * bf)
        else:
            self.Nh = hf
            self.Nd = df
            self.Nb = bf
        self._step = int((self.Filename.split('_')[3]).split('.')[0])
        self._Nslice = Nslice
        self._dt = dt
        self.t = self._step * dt

        self._COM = self.calc_COM()
        self._rot = self.calc_AngMom()

    def calc_COM(self):
        mtot = 0
        COMraw = np.zeros(3)
        for i in range(self._Nslice):
            offset = int(i * int(np.ceil(self.Np / self._Nslice)))
            count = int(np.ceil(self.Np / self._Nslice))
            if offset + count > self.Np:
                count = self.Np - offset
            with open(self.Filename, 'rb') as f:
                mxv = np.fromfile(f,
                                  dtype='f4',
                                  offset=offset * 4 * 7,
                                  count=count * 7)
                mxv = np.reshape(mxv, (count, 7)).astype('f8')
                mtot += np.sum(mxv[:, 0])
                COMraw += np.sum(mxv[:, 0][:, None] * (mxv[:, 1:4]), axis=0)
        del mxv
        return COMraw / mtot

    def calc_AngMom(self):
        Ltot = np.zeros(3)
        for i in range(self._Nslice):
            with open(self.Filename, 'rb') as f:
                mxv = np.fromfile(
                    f,
                    dtype='f4',
                    offset=(self.Nh * 7 + i * 7 * int(self.Nd / self._Nslice))
                    * 4,
                    count=7 * int(self.Nd / self._Nslice))
                mxv = np.reshape(mxv, (int(len(mxv) / 7), 7))
                Ltot += np.sum(np.cross((mxv[:, 1:4] - self._COM),
                                        mxv[:, 0][:, None] * mxv[:, 4:]),
                               axis=0)
        Ltot = Ltot / np.sqrt(np.sum(Ltot**2))
        rot = self.calc_Rot_matrix(Ltot)
        del mxv
        return rot

    @staticmethod
    def calc_Rot_matrix(AngMom):
        hyz = np.sqrt(AngMom[1]**2 + AngMom[2]**2)
        costh = AngMom[2] / hyz
        sinth = AngMom[1] / hyz

        Rx = np.array([[1, 0, 0], [0, costh, -sinth], [0, sinth, costh]])

        Lmid = np.matmul(Rx, AngMom)

        hxz = np.sqrt(Lmid[0]**2 + Lmid[2]**2)
        cosph = Lmid[2] / hxz
        sinph = -Lmid[0] / hxz
        Ry = np.array([[cosph, 0, sinph], [0, 1, 0], [-sinph, 0, cosph]])

        return np.matmul(Ry, Rx)

    def calc_density(self,
                     bins=(90, 90, 90),
                     lim=(30., 30., 10.),
                     adjust=True):
        Ntot = np.zeros(bins)

        for i in range(self._Nslice):
            with open(self.Filename, 'rb') as f:
                mxv = np.fromfile(f,
                                  dtype='f4',
                                  offset=i * 7 * int(self.Np / self._Nslice) *
                                  4,
                                  count=7 * int(self.Np / self._Nslice))
                mxv = np.reshape(mxv, (int(len(mxv) / 7), 7))
                if adjust:
                    mxv[:, 1:] = self.adjust(mxv[:, 1:])

                N, edges = np.histogramdd(mxv[:, 1:4],
                                          bins=bins,
                                          range=((-lim[0], lim[0]),
                                                 (-lim[1], lim[1]), (-lim[2],
                                                                     lim[2])),
                                          weights=mxv[:, 0])
                Ntot += N
        del mxv
        self.N = Ntot
        self.Nedge = edges
        return Ntot, edges

    def adjust(self, particles, vel=True):
        particles[:, :3] = np.matmul(self._rot,
                                     particles[:, :3].T - self._COM[:, None]).T
        if vel:
            particles[:, 3:] = np.matmul(self._rot, particles[:, 3:].T).T
        return particles

    def sample(self, frac=0.1):

        ncomp = [self.Nh, self.Nd, self.Nb]
        sample = np.empty([0, 7])

        for i, n in enumerate(ncomp):
            for j in range(self._Nslice):
                offset = int(np.sum(
                    ncomp[:i])) + j * int(np.ceil(n / self._Nslice))
                count = int(np.ceil(n / self._Nslice))
                if offset + count > np.sum(ncomp[:i + 1]):
                    count = np.sum(ncomp[:i + 1]) - offset
                with open(self.Filename, 'rb') as f:
                    mxv = np.fromfile(f,
                                      dtype='f4',
                                      offset=offset * 7 * 4,
                                      count=7 * count)
                    mxv = np.reshape(mxv, (int(len(mxv) / 7), 7))
                    indx = np.random.choice(count,
                                            int(count * frac),
                                            replace=False)
                    sample = np.vstack(
                        [sample, np.reshape(mxv[indx], (len(indx), 7))])
        sample[:, 0] /= frac
        sample[:, 1:] = self.sample(frac=frac)
        return sample

    def calc_vrot(self, Rs=np.linspace(0.01, 5., 51), sample=True, frac=0.01):

        try:
            return self.vrot
        except:
            if sample:
                sample = self.sample(frac=frac)
            else:
                with open(self.Filename, 'rb') as f:
                    sample = np.fromfile(f,
                                         dtype='f4',
                                         offset=4 * 7 * (self.Nh + self.Nd),
                                         count=7 * self.Nb)
                    sample = np.reshape(sample, (self.Nb, 7))
                    sample = self.adjust(sample)

            Nh = len(sample[tuple([sample[:, 0] == sample[0, 0]])])

            f = pb.new(dm=Nh, star=len(sample[:, 0]) - Nh)
            f['mass'] = sample[:, 0] / self.MMU
            f['pos'] = sample[:, 1:4] / self.MLU
            f['vel'] = sample[:, 4:] / self.MVU
            f['eps'] = np.ones(len(sample)) * 0.05 / self.MLU

            sp = galpy.potential.SnapshotRZPotential(f, num_threads=10)
            vrot = galpy.potential.calcRotcurve(sp, Rs, phi=0.)
            self.vrot = vrot
            self._Rs = Rs
            return vrot

    def calc_potential(self,
                       sample=True,
                       frac=0.01,
                       a=[27.68, 3.41, 0.536],
                       N=[5, 15, 3],
                       L=[5, 15, 3]):

        try:
            print('data/equil_potential_coefficients_N' + str(N[0]) +
                  str(N[1]) + str(N[2]) + '.txt')
            with open(
                    'data/equil_potential_coefficients_N' + str(N[0]) +
                    str(N[1]) + str(N[2]) + '.txt', 'rb') as f:
                Acos, Asin = np.load(f, allow_pickle=True)
            pot = [
                SCFPotential(Acos=Acos[i], Asin=Asin[i], a=a[i] / 8.)
                for i in range(3)
            ]
        except:
            ncomp = [self.Nh, self.Nd, self.Nb]
            Acos, Asin = np.empty((2, 3), dtype='object')

            pot = np.empty(3, dtype='object')

            fullsample = self.sample(frac=frac)
            masses = list(set(fullsample[:, 0]))

            for i, n in enumerate(ncomp):
                samples = fullsample[tuple([fullsample[:, 0] == masses[i]])]
                Acos[i], Asin[i] = scf_compute_coeffs_nbody(
                    samples[:, 1:4].T / self.MLU,
                    samples[:, 0] / self.MMU,
                    N[i],
                    L[i],
                    a=a[i] / 8.)
                pot[i] = SCFPotential(Acos=Acos[i], Asin=Asin[i], a=a[i] / 8.)

            coeff = np.vstack([Acos, Asin])
            with open(
                    'data/equil_potential_coefficients_N' + str(N[0]) +
                    str(N[1]) + str(N[2]) + '.txt', 'wb') as f:
                np.save(f, coeff)

        self.pot = list(pot)
        return list(pot)

    def analyze_SN(self,
                   Rcyl,
                   X=8.1,
                   Y=0,
                   correct=True,
                   zrange=[-2, 2],
                   nbins=51):

        calc = True
        try:
            for i, sn in enumerate(self.SN):
                if (sn.Rcyl == Rcyl) * (sn.X == X) * (sn.Y == Y):

                    # If you want a finer grid, replace the old coarser grid
                    if (nbins > sn.nbins):
                        self.SN[i] = SolarNeighbourhood(
                            self, Rcyl, X, Y, correct, zrange, nbins)
                        calc = False

                    # If it already exists, don't do it again
                    else:
                        calc = False
                else:
                    continue

            if calc:
                self.SN = np.append(
                    self.SN,
                    SolarNeighbourhood(self, Rcyl, X, Y, correct, zrange,
                                       nbins))

        except:
            self.SN = np.array(
                [SolarNeighbourhood(self, Rcyl, X, Y, correct, zrange, nbins)])

    def plot_density(self, plot_origin=False, save=False, adjust=True):

        try:
            self.N
        except:
            self.calc_density(adjust=adjust)

        fig, [ax1, ax2] = plt.subplots(2,
                                       sharex=True,
                                       gridspec_kw={'height_ratios': [3, 1]},
                                       figsize=[5, 7])
        ax1.imshow(np.log(np.sum(self.N, axis=2).T),
                   cmap='Greys',
                   extent=[-30, 30, -30, 30])
        ax2.imshow(np.log(np.sum(self.N, axis=1).T),
                   cmap='Greys',
                   extent=[-30, 30, -10, 10])

        if plot_origin:
            ax1.plot(0., 0., 'or')
            ax2.plot(0., 0., 'or')

        ax2.set_xlabel(r'$x \,\mathrm{(kpc)}$')
        ax1.set_ylabel(r'$y \,\mathrm{(kpc)}$')
        ax2.set_ylabel(r'$z \,\mathrm{(kpc)}$')
        fig.subplots_adjust(hspace=0)
        txt = ax1.annotate(r'$t=%.0f\,\mathrm{Myr}$' % (np.round(self.t, 0)),
                           (0.95, 0.95),
                           xycoords='axes fraction',
                           horizontalalignment='right',
                           verticalalignment='top',
                           size=18.)
        if save:
            plt.savefig('plots/Density' +
                        str(np.round(self.t, 0) + '.pdf', bbox_inches='tight'))
Esempio n. 11
0
def test_sanders15_leading_setup():
    #Imports
    from galpy.df import streamdf, streamgapdf
    from galpy.orbit import Orbit
    from galpy.potential import LogarithmicHaloPotential, PlummerPotential
    from galpy.actionAngle import actionAngleIsochroneApprox
    from galpy.util import conversion  #for unit conversions
    lp = LogarithmicHaloPotential(normalize=1., q=0.9)
    aAI = actionAngleIsochroneApprox(pot=lp, b=0.8)
    prog_unp_peri = Orbit([
        2.6556151742081835, 0.2183747276300308, 0.67876510797240575,
        -2.0143395648974671, -0.3273737682604374, 0.24218273922966019
    ])
    global sdfl_sanders15
    V0, R0 = 220., 8.
    sigv = 0.365 * (10. / 2.)**(1. / 3.)  # km/s
    # Use a Potential object for the impact
    pp= PlummerPotential(amp=10.**-2.\
                             /conversion.mass_in_1010msol(V0,R0),
                         b=0.625/R0)
    import warnings
    from galpy.util import galpyWarning
    with warnings.catch_warnings(record=True) as w:
        warnings.simplefilter("always", galpyWarning)
        sdfl_sanders15= streamgapdf(sigv/V0,progenitor=prog_unp_peri,
                                    pot=lp,aA=aAI,
                                    leading=True,nTrackChunks=26,
                                    nTrackChunksImpact=29,
                                    nTrackIterations=1,
                                    sigMeanOffset=4.5,
                                    tdisrupt=10.88\
                                        /conversion.time_in_Gyr(V0,R0),
                                    Vnorm=V0,Rnorm=R0,
                                    impactb=0.,
                                    subhalovel=numpy.array([49.447319,
                                                            116.179436,
                                                            155.104156])/V0,
                                    timpact=0.88/conversion.time_in_Gyr(V0,R0),
                                    impact_angle=2.09,
                                    subhalopot=pp,
                                    nKickPoints=290,
                                    deltaAngleTrackImpact=4.5,
                                    multi=True) # test multi
        # Should raise warning bc of deltaAngleTrackImpact, might raise others
        raisedWarning = False
        for wa in w:
            raisedWarning = (
                str(wa.message) ==
                "WARNING: deltaAngleTrackImpact angle range large compared to plausible value"
            )
            if raisedWarning: break
        assert raisedWarning, 'deltaAngleTrackImpact warning not raised when it should have been'
    assert not sdfl_sanders15 is None, 'sanders15 trailing streamdf setup did not work'
    # Also setup the unperturbed model
    global sdfl_sanders15_unp
    sdfl_sanders15_unp= streamdf(sigv/V0,progenitor=prog_unp_peri,
                                 pot=lp,aA=aAI,
                                 leading=True,nTrackChunks=26,
                                 nTrackIterations=1,
                                 sigMeanOffset=4.5,
                                 tdisrupt=10.88\
                                     /conversion.time_in_Gyr(V0,R0),
                                 Vnorm=V0,Rnorm=R0)
    assert not sdfl_sanders15_unp is None, \
        'sanders15 unperturbed streamdf setup did not work'
    return None
Esempio n. 12
0
def run_orbitIntegration_comparison(orb,
                                    pot,
                                    tmax,
                                    vo,
                                    ro,
                                    isList=False,
                                    tol=0.01):
    # Integrate in galpy
    ts = numpy.linspace(0., tmax / conversion.time_in_Gyr(vo, ro), 1001)
    orb.integrate(ts, pot)
    # Now setup a NEMO snapshot in the correct units ([x] = kpc, [v] = kpc/Gyr)
    numpy.savetxt('orb.dat',
                  numpy.array([[10.**-6.,orb.x(),orb.y(),orb.z(),
                                orb.vx(use_physical=False)\
                                    *conversion.velocity_in_kpcGyr(vo,ro),
                                orb.vy(use_physical=False)\
                                    *conversion.velocity_in_kpcGyr(vo,ro),
                                orb.vz(use_physical=False)\
                                    *conversion.velocity_in_kpcGyr(vo,ro)]]))
    # Now convert to NEMO format
    try:
        convert_to_nemo('orb.dat', 'orb.nemo')
    finally:
        os.remove('orb.dat')
    # Integrate with gyrfalcON
    try:
        if isList:
            integrate_gyrfalcon('orb.nemo', 'orb_evol.nemo', tmax,
                                potential.nemo_accname(pot),
                                potential.nemo_accpars(pot, vo, ro))
        else:
            integrate_gyrfalcon('orb.nemo', 'orb_evol.nemo', tmax,
                                pot.nemo_accname(), pot.nemo_accpars(vo, ro))
    finally:
        os.remove('orb.nemo')
        os.remove('gyrfalcON.log')
    # Convert back to ascii
    try:
        convert_from_nemo('orb_evol.nemo', 'orb_evol.dat')
    finally:
        os.remove('orb_evol.nemo')
    # Read and compare
    try:
        nemodata = numpy.loadtxt('orb_evol.dat', comments='#')
        xdiff = numpy.fabs((nemodata[-1, 1] - orb.x(ts[-1])) / nemodata[-1, 1])
        ydiff = numpy.fabs((nemodata[-1, 2] - orb.y(ts[-1])) / nemodata[-1, 2])
        zdiff = numpy.fabs((nemodata[-1, 3] - orb.z(ts[-1])) / nemodata[-1, 3])
        vxdiff = numpy.fabs(
            (nemodata[-1, 4] - orb.vx(ts[-1], use_physical=False) *
             conversion.velocity_in_kpcGyr(vo, ro)) / nemodata[-1, 4])
        vydiff = numpy.fabs(
            (nemodata[-1, 5] - orb.vy(ts[-1], use_physical=False) *
             conversion.velocity_in_kpcGyr(vo, ro)) / nemodata[-1, 5])
        vzdiff = numpy.fabs(
            (nemodata[-1, 6] - orb.vz(ts[-1], use_physical=False) *
             conversion.velocity_in_kpcGyr(vo, ro)) / nemodata[-1, 6])
        assert xdiff < tol, 'galpy and NEMO gyrfalcON orbit integration inconsistent for x by %g' % xdiff
        assert ydiff < tol, 'galpy and NEMO gyrfalcON orbit integration inconsistent for y by %g' % ydiff
        assert zdiff < tol, 'galpy and NEMO gyrfalcON orbit integration inconsistent for z by %g' % zdiff
        assert vxdiff < tol, 'galpy and NEMO gyrfalcON orbit integration inconsistent for vx by %g' % vxdiff
        assert vydiff < tol, 'galpy and NEMO gyrfalcON orbit integration inconsistent for vy by %g' % vydiff
        assert vzdiff < tol, 'galpy and NEMO gyrfalcON orbit integration inconsistent for vz by %g' % vzdiff
    finally:
        os.remove('orb_evol.dat')
    return None