Example #1
0
def calculate_orbital_parameters(xGC_norm, yGC_norm, zGC_norm, vxGC_norm,
                                 vyGC_norm, vzGC_norm, inttime, numsteps):
    # agama convention
    x_agama = xGC_norm
    y_agama = yGC_norm
    z_agama = zGC_norm
    vx_agama = vxGC_norm
    vy_agama = vyGC_norm
    vz_agama = vzGC_norm

    R_agama = numpy.sqrt(x_agama**2 + y_agama**2)
    vR_agama = (x_agama * vx_agama + y_agama * vy_agama) / R_agama
    vT_agama = -(x_agama * vy_agama - y_agama * vx_agama) / R_agama
    phi_agama = numpy.arctan2(y_agama, x_agama)

    inttime = 1.
    numsteps = 300
    times = numpy.linspace(0, inttime, numsteps)
    times_c, c_orb_car = agama.orbit(
        ic=[x_agama, y_agama, z_agama, vx_agama, vy_agama, vz_agama],
        potential=potentialTotal_local,
        time=inttime,
        trajsize=numsteps)
    #print(c_orb_car[:,0])

    x = c_orb_car[:, 0]
    y = c_orb_car[:, 1]
    z = c_orb_car[:, 2]
    vx = c_orb_car[:, 3]
    vy = c_orb_car[:, 4]
    vz = c_orb_car[:, 5]
    R = numpy.sqrt(x**2 + y**2)
    r = numpy.sqrt(x**2 + y**2 + z**2)

    rmin = numpy.min(r)
    rmax = numpy.max(r)
    zmax = numpy.max(numpy.fabs(z))
    ecc = (rmax - rmin) / (rmax + rmin)
    return rmin, rmax, zmax, ecc
Example #2
0
def run_orbit(ic):
    color = numpy.random.random(
        size=3) * 0.8  #plt.get_cmap('mist')(numpy.random.random())
    time, orbit = agama.orbit(ic=ic,
                              potential=pot,
                              time=100 * pot.Tcirc(ic),
                              trajsize=20000)
    x = orbit[:, 0] if Lz == 0 else (orbit[:, 0]**2 + orbit[:, 1]**2)**0.5
    vx = orbit[:, 3] if Lz == 0 else (orbit[:, 0] * orbit[:, 3] +
                                      orbit[:, 1] * orbit[:, 4]) / x
    z = orbit[:, 2]
    vz = orbit[:, 5]
    splx = agama.CubicSpline(time, x, der=vx)
    splz = agama.CubicSpline(time, z, der=vz)
    hits = (z[:-1] <= 0) * (
        z[1:] > 0)  # segments which contain points in the surface of section
    tcross = numpy.array([
        scipy.optimize.brentq(splz, time[i], time[i + 1])
        for i in numpy.where(hits)[0]
    ])
    axorb.plot(x[:10000], z[:10000], color=color, lw=0.5, alpha=0.5)
    axpss.plot(splx(tcross), splx(tcross, 1), 'o', color=color, mew=0, ms=1.5)
Example #3
0
def main(args: Optional[list] = None,
         opts: Optional[argparse.Namespace] = None):
    """Script Function.

    Parameters
    ----------
    args : list, optional
        an optional single argument that holds the sys.argv list,
        except for the script name (e.g., argv[1:])
    opts : Namespace, optional
        pre-constructed results of parsed args
        if not None, used ONLY if args is None

    """
    if opts is not None and args is None:
        pass
    else:
        if opts is not None:
            warnings.warn("Not using `opts` because `args` are given")
        parser = make_parser()
        opts = parser.parse_args(args)

    foutname = DATA + "result_orbits.txt"

    if not os.path.isfile(foutname):

        # STEP 1: create Monte Carlo realizations of position and velocity of each cluster,
        # sampling from their measured uncertainties.

        # this file should have been produced by run_fit.py
        tab = np.loadtxt(DATA + "summary.txt", dtype=str)
        names = tab[:, 0]  # 0th column is the cluster name (string)
        tab = tab[:, 1:].astype(float)  # remaining columns are numbers
        ra0 = tab[:, 0]  # coordinates of cluster centers [deg]
        dec0 = tab[:, 1]
        dist0 = tab[:, 2]  # distance [kpc]
        vlos0 = tab[:, 3]  # line-of-sight velocity [km/s]
        vlose = tab[:, 4]  # its error estimate
        pmra0 = tab[:, 7]  # mean proper motion [mas/yr]
        pmdec0 = tab[:, 8]
        pmrae = tab[:, 9]  # its uncertainty
        pmdece = tab[:, 10]
        pmcorr = tab[:,
                     11]  # correlation coefficient for errors in two PM components
        vlose = np.maximum(
            vlose,
            2.0)  # assumed error of at least 2 km/s on line-of-sight velocity
        diste = (dist0 * 0.46 * 0.1
                 )  # assumed error of 0.1 mag in distance modulus

        # create bootstrap samples
        np.random.seed(42)  # ensure repeatability of random samples
        nboot = 100  # number of bootstrap samples for each cluster
        nclust = len(tab)
        ra = np.repeat(ra0, nboot)
        dec = np.repeat(dec0, nboot)
        pmra = np.repeat(pmra0, nboot)
        pmdec = np.repeat(pmdec0, nboot)
        for i in range(nclust):
            # draw PM realizations from a correlated 2d gaussian for each cluster
            A = np.random.normal(size=nboot)
            B = (np.random.normal(size=nboot) * (1 - pmcorr[i]**2)**0.5 +
                 A * pmcorr[i])
            pmra[i * nboot:(i + 1) * nboot] += pmrae[i] * A
            pmdec[i * nboot:(i + 1) * nboot] += pmdece[i] * B
        vlos = np.repeat(vlos0, nboot) + np.hstack(
            [np.random.normal(scale=e, size=nboot) for e in vlose])
        dist = np.repeat(dist0, nboot) + np.hstack(
            [np.random.normal(scale=e, size=nboot) for e in diste])

        # convert coordinates from heliocentric (ra,dec,dist,PM,vlos) to Galactocentric (kpc and km/s)
        u.kms = u.km / u.s
        c_sky = coord.ICRS(
            ra=ra * u.degree,
            dec=dec * u.degree,
            pm_ra_cosdec=pmra * u.mas / u.yr,
            pm_dec=pmdec * u.mas / u.yr,
            distance=dist * u.kpc,
            radial_velocity=vlos * u.kms,
        )
        c_gal = c_sky.transform_to(
            coord.Galactocentric(
                galcen_distance=8.2 * u.kpc,
                galcen_v_sun=coord.CartesianDifferential([10.0, 248.0, 7.0] *
                                                         u.kms),
            ))
        pos = np.column_stack(
            (c_gal.x / u.kpc, c_gal.y / u.kpc, c_gal.z / u.kpc))
        vel = np.column_stack(
            (c_gal.v_x / u.kms, c_gal.v_y / u.kms, c_gal.v_z / u.kms))
        # add uncertainties from the solar position and velocity
        pos[:, 0] += np.random.normal(
            scale=0.1, size=nboot *
            nclust)  # uncertainty in solar distance from Galactic center
        vel[:, 0] += np.random.normal(scale=1.0, size=nboot *
                                      nclust)  # uncertainty in solar velocity
        vel[:, 1] += np.random.normal(scale=3.0, size=nboot * nclust)
        vel[:, 2] += np.random.normal(scale=1.0, size=nboot * nclust)
        pos[:, 0] *= (
            -1
        )  # revert back to normal orientation of coordinate system (solar position at x=+8.2)
        vel[:, 0] *= -1  # same for velocity
        posvel = np.column_stack((pos, vel)).value
        np.savetxt(DATA + "posvel.txt", posvel, fmt="%.6g")

        # STEP 2: compute the orbits, min/max galactocentric radii, and actions, for all Monte Carlo samples

        print(agama.setUnits(
            length=1, velocity=1,
            mass=1))  # units: kpc, km/s, Msun; time unit ~ 1 Gyr
        potential = agama.Potential(
            DATA + "McMillan17.ini")  # MW potential from McMillan(2017)

        # compute orbits for each realization of initial conditions,
        # integrated for 100 dynamical times or 20 Gyr (whichever is lower)
        print(
            "Computing orbits for %d realizations of cluster initial conditions"
            % len(posvel))
        inttime = np.minimum(20.0, potential.Tcirc(posvel) * 100)
        orbits = agama.orbit(ic=posvel,
                             potential=potential,
                             time=inttime,
                             trajsize=1000)[:, 1]
        rmin = np.zeros(len(orbits))
        rmax = np.zeros(len(orbits))
        for i, o in enumerate(orbits):
            r = np.sum(o[:, 0:3]**2, axis=1)**0.5
            rmin[i] = np.min(r) if len(r) > 0 else np.nan
            rmax[i] = np.max(r) if len(r) > 0 else np.nan
        # replace nboot samples rmin/rmax with their median and 68% confidence intervals for each cluster
        rmin = np.nanpercentile(rmin.reshape(nclust, nboot), [16, 50, 84],
                                axis=1)
        rmax = np.nanpercentile(rmax.reshape(nclust, nboot), [16, 50, 84],
                                axis=1)

        # compute actions for the same initial conditions
        actfinder = agama.ActionFinder(potential)
        actions = actfinder(posvel)
        # again compute the median and 68% confidence intervals for each cluster
        actions = np.nanpercentile(actions.reshape(nclust, nboot, 3),
                                   [16, 50, 84],
                                   axis=1)

        # compute the same confidence intervals for the total energy
        energy = potential.potential(
            posvel[:, 0:3]) + 0.5 * np.sum(posvel[:, 3:6]**2, axis=1)
        energy = np.percentile(energy.reshape(nclust, nboot), [16, 50, 84],
                               axis=1)

        # write the orbit parameters, actions and energy - one line per cluster, with the median and uncertainties
        fileout = open(foutname, "w")
        fileout.write(
            "# Name         \t     pericenter[kpc]   \t     apocenter[kpc]    \t"
            +
            "       Jr[kpc*km/s]    \t       Jz[kpc*km/s]    \t      Jphi[kpc*km/s]   \t    Energy[km^2/s^2]   \n"
        )
        for i in range(nclust):
            fileout.write(("%-15s" + "\t%7.2f" * 6 + "\t%7.0f" * 12 + "\n") % (
                names[i],
                rmin[0, i],
                rmin[1, i],
                rmin[2, i],
                rmax[0, i],
                rmax[1, i],
                rmax[2, i],
                actions[0, i, 0],
                actions[1, i, 0],
                actions[2, i, 0],
                actions[0, i, 1],
                actions[1, i, 1],
                actions[2, i, 1],
                actions[0, i, 2],
                actions[1, i, 2],
                actions[2, i, 2],
                energy[0, i],
                energy[1, i],
                energy[2, i],
            ))
        fileout.close()
def test(gpot, Gpot, Apot, test_hessian=False):
    '''
    gpot is the native gala potential;
    Gpot is the same one accessed through wrapper;
    Apot is the equivalent native agama potential
    '''
    print("\nTesting G=%s and A=%s" % (repr(Gpot), repr(Apot)))
    #0. retrieve dimensional factors for converting the output of agama-related methods
    # to the potential's unit system (assuming it is identical for both potentials)
    lu = Gpot.units['length']
    pu = Gpot.units['energy'] / Gpot.units['mass']
    fu = Gpot.units['length'] / Gpot.units['time']**2
    du = Gpot.units['mass'] / Gpot.units['length']**3
    #1. test that the values of potential coincide, using both interfaces
    print("G energy vs potential: %.3g" % numpy.max(
        abs(Gpot.energy(points.T) / Gpot.potential(points) / pu - 1)))
    print("A energy vs potential: %.3g" % numpy.max(
        abs(Apot.energy(points.T) / Apot.potential(points) / pu - 1)))
    print("G energy vs A energy:  %.3g" %
          numpy.max(abs(Gpot.energy(points.T) / Apot.energy(points.T) - 1)))
    #2. test the accelerations - these don't exactly match,
    # because agama evaluates them by finite-differencing if initialized from a "foreign" gala potential
    print("G acceleration vs force:  %.3g" % numpy.max(
        abs(Gpot.acceleration(points.T).T / Gpot.force(points) / fu - 1)))
    print("A acceleration vs force:  %.3g" % numpy.max(
        abs(Apot.acceleration(points.T).T / Apot.force(points) / fu - 1)))
    print(
        "G gradient vs A gradient: %.3g" %
        numpy.max(abs(Gpot.gradient(points.T) / Apot.gradient(points.T) - 1)))
    #3. test the hessian
    print("G forceDeriv vs A forceDeriv: %.3g" % numpy.max(
        abs(Gpot.forceDeriv(points)[1] / Apot.forceDeriv(points)[1] - 1)))
    print("G hessian vs A hessian:       %.3g" %
          numpy.max(abs(Gpot.hessian(points.T) / Apot.hessian(points.T) - 1)))
    #4. test density - again no exact match since it is computed by finite differences in Gpot
    print("G density [gala] vs [agama]: %.3g" % numpy.max(
        abs(Gpot.density(points.T) / Gpot.agamadensity(points) / du - 1)))
    print("A density [gala] vs [agama]: %.3g" % numpy.max(
        abs(Apot.density(points.T) / Apot.agamadensity(points) / du - 1)))
    print("G density vs A density:      %.3g" %
          numpy.max(abs(Gpot.density(points.T) / Apot.density(points.T) - 1)))
    #5. test orbit integration using both gala and agama routines with either potential
    # create some initial conditions for orbits:
    # take the positions and assign velocity to be comparable to circular velocity at each point
    ic = numpy.hstack((points, numpy.random.normal(size=points.shape) *
                       Apot.circular_velocity(points.T)[:, None]))
    t0 = time.time()
    g_orb_g = gpot.integrate_orbit(
        ic.T,
        dt=10,
        n_steps=100,
        Integrator=gala.integrate.DOPRI853Integrator,
        Integrator_kwargs=dict(rtol=1e-8, atol=0))
    t1 = time.time()
    g_orb_G = Gpot.integrate_orbit(
        ic.T,
        dt=10,
        n_steps=100,
        Integrator=gala.integrate.DOPRI853Integrator,
        Integrator_kwargs=dict(rtol=1e-8, atol=0))
    t2 = time.time()
    g_orb_A = Apot.integrate_orbit(
        ic.T,
        dt=10,
        n_steps=100,
        Integrator=gala.integrate.DOPRI853Integrator,
        Integrator_kwargs=dict(rtol=1e-8, atol=0))
    t3 = time.time()
    a_orb_G = numpy.dstack(
        agama.orbit(potential=Gpot,
                    ic=ic,
                    time=1000,
                    trajsize=101,
                    dtype=float)[:, 1])
    t4 = time.time()
    a_orb_A = numpy.dstack(
        agama.orbit(potential=Apot,
                    ic=ic,
                    time=1000,
                    trajsize=101,
                    dtype=float)[:, 1])
    t5 = time.time()
    print("gala  orbit integration for g (native): %.4g s" % (t1 - t0) +
          ", G (wrapper): %.4g s" % (t2 - t1) + ", A: %.4g s" % (t3 - t2))
    print("agama orbit integration for G: %.4g s" % (t4 - t3) + ", A: %.4g s" %
          (t5 - t4))
    deltaEg = numpy.max(abs(g_orb_G.energy()[-1] / g_orb_G.energy()[0] - 1))
    Eainit = Apot.potential(
        a_orb_A[0, 0:3].T) + 0.5 * numpy.sum(a_orb_A[0, 3:6]**2, axis=0)
    Eafinal = Apot.potential(
        a_orb_A[-1, 0:3].T) + 0.5 * numpy.sum(a_orb_A[-1, 3:6]**2, axis=0)
    deltaEa = numpy.max(abs(Eafinal / Eainit - 1))
    # shape of the output is different: for gala, it is 3 x nsteps x norbits; for agama (dstack'ed) - nsteps x 6 x norbits
    g_orb_G = g_orb_G.xyz.reshape(3, len(g_orb_G.t), len(ic))
    g_orb_A = g_orb_A.xyz.reshape(3, len(g_orb_A.t), len(ic))
    a_orb_G = numpy.swapaxes(a_orb_G * lu, 0,
                             1)[0:3]  # now the shape is 3 x nsteps x norbits
    a_orb_A = numpy.swapaxes(a_orb_A * lu, 0, 1)[0:3]
    maxrad = numpy.max(
        numpy.sum(a_orb_A**2, axis=0)**0.5,
        axis=0)  # normalization factor for relative deviations in position
    print("gala  orbits G vs A: %.3g" %
          numpy.max(numpy.sum(abs(g_orb_G - g_orb_A), axis=0) / maxrad))
    print("agama orbits G vs A: %.3g" %
          numpy.max(numpy.sum(abs(a_orb_G - a_orb_A), axis=0) / maxrad))
    print("gala vs agama: %.3g" %
          numpy.max(numpy.sum(abs(g_orb_G - a_orb_G), axis=0) / maxrad))
    print("energy error in gala: %.3g, agama: %.3g" % (deltaEg, deltaEa))
    # illustrate that the hessian is broken (?) - compute it once for all points, then for each point in a loop
    if test_hessian:
        print(
            "Checking vectorization of hessian for G: the two arrays should be equivalent, but they are not"
        )
        print("Vectorized:\n", Gpot.hessian(points.T))
        print("Pointwise:\n",
              numpy.dstack([Gpot.hessian(point) for point in points]))
        print(
            "Checking vectorization of hessian for A: the two arrays should be equivalent"
        )
        print("Vectorized:\n", Apot.hessian(points.T))
        print("Pointwise:\n",
              numpy.dstack([Apot.hessian(point) for point in points]))
def compare(ic, inttime, numsteps):
    g_orb_obj = galpy.orbit.Orbit([ic[0],ic[3],ic[5],ic[1],ic[4],ic[2]])
    times = numpy.linspace(0, inttime, numsteps)
    dt = time.time()
    g_orb_obj.integrate(times, g_pot)
    g_orb = g_orb_obj.getOrbit()
    print 'Time to integrate orbit in galpy: %s s' % (time.time()-dt)

    dt = time.time()
    c_orb_car = agama.orbit(ic=[ic[0],0,ic[1],ic[3],ic[5],ic[4]], pot=w_pot._pot, time=inttime, step=inttime/numsteps)
    print 'Time to integrate orbit in Agama: %s s' % (time.time()-dt)
    times_c = numpy.linspace(0,inttime,len(c_orb_car[:,0]))
    ### make it compatible with galpy's convention (native output is in cartesian coordinates)
    c_orb = c_orb_car*1.0
    c_orb[:,0] = (c_orb_car[:,0]**2+c_orb_car[:,1]**2)**0.5
    c_orb[:,3] = c_orb_car[:,2]

    ### in galpy, this is the only tool that can estimate interfocal distance,
    ### but it requires the orbit to be computed first
    delta = estimateDeltaStaeckel(g_orb[:,0], g_orb[:,3], pot=g_pot)
    print "interfocal distance Delta=",delta

    ### plot the orbit(s) in R,z plane, along with the prolate spheroidal coordinate grid
    plt.axes([0.05, 0.55, 0.45, 0.45])
    plotCoords(delta, 1.5)
    plt.plot(g_orb[:,0],g_orb[:,3], 'b', label='galpy')  # R,z
    plt.plot(c_orb[:,0],c_orb[:,3], 'g', label='Agama')  # R,z
    plt.xlabel("R/8kpc")
    plt.ylabel("z/8kpc")
    plt.xlim(0, 1.2)
    plt.ylim(-1,1)
    plt.legend()

    ### plot R(t), z(t)
    plt.axes([0.55, 0.55, 0.45, 0.45])
    plt.plot(times, g_orb[:,0], label='R')
    plt.plot(times, g_orb[:,3], label='z')
    plt.xlabel("t")
    plt.ylabel("R,z")
    plt.legend()
    plt.xlim(0,50)

    ### create galpy action/angle finder for the given value of Delta
    ### note: using c=False in the routine below is much slower but apparently more accurate,
    ### comparable to the Agama for the same value of delta
    g_actfinder = galpy.actionAngle.actionAngleStaeckel(pot=g_pot, delta=delta, c=True)

    ### find the actions for each point of the orbit
    dt = time.time()
    g_act = g_actfinder(g_orb[:,0],g_orb[:,1],g_orb[:,2],g_orb[:,3],g_orb[:,4],fixed_quad=True)
    print 'Time to compute actions in galpy: %s s' % (time.time()-dt)

    ### use the Agama action routine for the same value of Delta as in galpy
    dt = time.time()
    c_act = agama.actions(point=c_orb_car, pot=w_pot._pot, ifd=delta)   # explicitly specify interfocal distance
    print 'Time to compute actions in Agama: %s s' % (time.time()-dt)

    ### use the Agama action finder (initialized at the beginning) that automatically determines the best value of Delta
    dt = time.time()
    a_act = c_actfinder(c_orb_car)   # use the interfocal distance estimated by action finder
    print 'Time to compute actions in Agama: %s s' % (time.time()-dt)

    ### plot Jr vs Jz
    plt.axes([0.05, 0.05, 0.45, 0.45])
    plt.plot(g_act[0],g_act[2], label='galpy')
    plt.plot(c_act[:,0],c_act[:,1], label=r'Agama,$\Delta='+str(delta)+'$')
    plt.plot(a_act[:,0],a_act[:,1], label=r'Agama,$\Delta=$auto')
    plt.xlabel("$J_r$")
    plt.ylabel("$J_z$")
    plt.legend()

    ### plot Jr(t) and Jz(t)
    plt.axes([0.55, 0.05, 0.45, 0.45])
    plt.plot(times, g_act[0], label='galpy', c='b')
    plt.plot(times, g_act[2], c='b')
    plt.plot(times_c, c_act[:,0], label='Agama,$\Delta='+str(delta)+'$', c='g')
    plt.plot(times_c, c_act[:,1], c='g')
    plt.plot(times_c, a_act[:,0], label='Agama,$\Delta=$auto', c='r')
    plt.plot(times_c, a_act[:,1], c='r')
    plt.text(0, c_act[0,0], '$J_r$', fontsize=16)
    plt.text(0, c_act[0,1], '$J_z$', fontsize=16)
    plt.xlabel("t")
    plt.ylabel("$J_r, J_z$")
    plt.legend(loc='center right')
    plt.xlim(0,50)
    plt.show()
Example #6
0
numpy.savetxt('posvel.txt', posvel, fmt='%.6g')

# STEP 2: compute the orbits, min/max galactocentric radii, and actions, for all Monte Carlo samples
import agama
print(agama.setUnits(length=1, velocity=1,
                     mass=1))  # units: kpc, km/s, Msun; time unit ~ 1 Gyr
potential = agama.Potential(
    'McMillan17.ini')  # MW potential from McMillan(2017)

# compute orbits for each realization of initial conditions,
# integrated for 100 dynamical times or 20 Gyr (whichever is lower)
print("Computing orbits for %d realizations of cluster initial conditions" %
      len(posvel))
inttime = numpy.minimum(20., potential.Tcirc(posvel) * 100)
orbits = agama.orbit(ic=posvel,
                     potential=potential,
                     time=inttime,
                     trajsize=1000)[:, 1]
rmin = numpy.zeros(len(orbits))
rmax = numpy.zeros(len(orbits))
for i, o in enumerate(orbits):
    r = numpy.sum(o[:, 0:3]**2, axis=1)**0.5
    rmin[i] = numpy.min(r) if len(r) > 0 else numpy.nan
    rmax[i] = numpy.max(r) if len(r) > 0 else numpy.nan
# replace nboot samples rmin/rmax with their median and 68% confidence intervals for each cluster
rmin = numpy.nanpercentile(rmin.reshape(nclust, nboot), [16, 50, 84], axis=1)
rmax = numpy.nanpercentile(rmax.reshape(nclust, nboot), [16, 50, 84], axis=1)

# compute actions for the same initial conditions
actfinder = agama.ActionFinder(potential)
actions = actfinder(posvel)
# again compute the median and 68% confidence intervals for each cluster
# compute some orbits in the axisymmetric and perturbed potentials
# (the latter rotating with pattern speed Omega)
R0 = 3.0
V0 = (
    -R0 *
    pot_disk.force(R0, 0, 0)[0])**0.5  # circular velocity at the given radius
# note that we set the pattern speed to a negative value, so that the spirals are trailing
Omega = -0.8 * V0 / R0
ic = [-R0, 0.0, 0.0, 0.0, 0.9 * V0, 0.1 * V0
      ]  # and make the angular momentum negative as well (i.e.prograde)
time = 20 * R0 / V0
nsteps = 200
# trajectories are stored in the rotating frame
t, orbit_disk = agama.orbit(potential=pot_disk,
                            ic=ic,
                            time=time,
                            trajsize=nsteps,
                            Omega=Omega)
_, orbit_spir = agama.orbit(potential=pot_total,
                            ic=ic,
                            time=time,
                            trajsize=nsteps,
                            Omega=Omega)
# convert the trajectories to the inertial frame
cosa, sina = numpy.cos(t * Omega), numpy.sin(t * Omega)
orbit_disk_x = orbit_disk[:, 0] * cosa - orbit_disk[:, 1] * sina
orbit_disk_y = orbit_disk[:, 1] * cosa + orbit_disk[:, 0] * sina
orbit_spir_x = orbit_spir[:, 0] * cosa - orbit_spir[:, 1] * sina
orbit_spir_y = orbit_spir[:, 1] * cosa + orbit_spir[:, 0] * sina

# plot the animated orbit and rotating potential
Example #8
0
def cost_function_Zej(x_, y_, z_, vx_, vy_, vz_):

    #normalize position
    #normalize flip velocity
    vx_ = -vx_
    vy_ = -vy_
    vz_ = -vz_

    inttime_back_Myr = _inttime_back_Myr
    #numpy.sqrt(x_**2 + y_**2 + z_**2)*_R0_norm*2.0/(numpy.sqrt(vx_**2 + vy_**2 + vz_**2)*_V0_norm/1000.)
    inttime_back_ = inttime_back_Myr * (
        numpy.pi /
        (102.396349 * (240. / _V0) *
         (_R0 / 8.)))  #Roughly: 102Myr = 3.14 if _R0_norm=8 and _V0_norm=240
    times_c, c_orb_car = agama.orbit(ic=[x_, y_, z_, vx_, vy_, vz_],
                                     potential=c_pot,
                                     time=inttime_back_,
                                     trajsize=5000)

    #xGC_kpc  = _R0 * c_orb_car[:,0]
    #yGC_kpc  = _R0 * c_orb_car[:,1]
    zGC_kpc_tmp = _R0 * c_orb_car[:, 2]
    #vxGC_kms = _V0 * c_orb_car[:,3]
    #vyGC_kms = _V0 * c_orb_car[:,4]
    #vzGC_kms = _V0 * c_orb_car[:,5]

    # most recent ejection
    flag_dc = 0
    i_dc = 0
    time_dc = 0.
    z_i = zGC_kpc_tmp[0]
    z_iplus1 = zGC_kpc_tmp[1]
    for i in range(len(zGC_kpc_tmp) - 1):
        z_i = zGC_kpc_tmp[i]
        z_iplus1 = zGC_kpc_tmp[i + 1]
        i_dc = i
        time_dc = times_c[i]
        if (z_i * z_iplus1 < 0.):
            flag_dc = 1
            break

    print(times_c[i_dc], z_i)
    print(times_c[i_dc + 1], z_iplus1)
    #assert((z_i*z_iplus1<=0.) or (z_i>10.))
    inttime_back_ = 1.05 * times_c[i_dc + 1]

    # backward orbit until the most recent disc crossing
    times_c, c_orb_car = agama.orbit(ic=[x_, y_, z_, vx_, vy_, vz_],
                                     potential=c_pot,
                                     time=inttime_back_,
                                     trajsize=3000)

    xGC_kpc = _R0 * c_orb_car[:, 0]
    yGC_kpc = _R0 * c_orb_car[:, 1]
    zGC_kpc = _R0 * c_orb_car[:, 2]
    vxGC_kms = _V0 * c_orb_car[:, 3]
    vyGC_kms = _V0 * c_orb_car[:, 4]
    vzGC_kms = _V0 * c_orb_car[:, 5]

    xGC_kpc_func = scipy.interpolate.interp1d(times_c, xGC_kpc, kind='cubic')
    yGC_kpc_func = scipy.interpolate.interp1d(times_c, yGC_kpc, kind='cubic')
    zGC_kpc_func = scipy.interpolate.interp1d(times_c, zGC_kpc, kind='cubic')
    vxGC_kpc_func = scipy.interpolate.interp1d(times_c, vxGC_kms, kind='cubic')
    vyGC_kpc_func = scipy.interpolate.interp1d(times_c, vyGC_kms, kind='cubic')
    vzGC_kpc_func = scipy.interpolate.interp1d(times_c, vzGC_kms, kind='cubic')

    # distance from ejection location (x_ej,y_ej)
    distance2_from_disc_kpc_func = lambda x: (zGC_kpc_func(x)**2)

    result2 = scipy.optimize.minimize_scalar(distance2_from_disc_kpc_func,
                                             bounds=(times_c[0], times_c[-1]),
                                             method='bounded')

    #print ('%lf %lf %lf' % (muellstar_test, mubee_test, rGC_kpc_func_2(result2.x)))

    x_ej = xGC_kpc_func(result2.x)
    y_ej = yGC_kpc_func(result2.x)
    z_ej = zGC_kpc_func(result2.x)
    vx_ej = -vxGC_kpc_func(result2.x)
    vy_ej = -vyGC_kpc_func(result2.x)
    vz_ej = -vzGC_kpc_func(result2.x)

    flightTime_Myr = (result2.x) / (numpy.pi / (102.396349 * (240. / _V0) *
                                                (_R0 / 8.)))

    return x_ej, y_ej, z_ej, vx_ej, vy_ej, vz_ej, flightTime_Myr
Example #9
0
def calculate_orbital_shape_PAST(xGC_norm, yGC_norm, zGC_norm, vxGC_norm,
                                 vyGC_norm, vzGC_norm, inttime, numsteps):
    # agama convention
    # already normalized position
    x_agama = xGC_norm
    y_agama = yGC_norm
    z_agama = zGC_norm
    # FLIP already normalized velocity
    vx_agama = -vxGC_norm
    vy_agama = -vyGC_norm
    vz_agama = -vzGC_norm

    inttime_back_Myr = _inttime_back_Myr
    inttime_back_ = inttime_back_Myr * (
        numpy.pi /
        (102.396349 * (240. / _V0) *
         (_R0 / 8.)))  #Roughly: 102Myr = 3.14 if _R0_norm=8 and _V0_norm=240

    inttime = inttime_back_
    numsteps = 3000
    times = numpy.linspace(0, inttime, numsteps)
    times_c, c_orb_car = agama.orbit(
        ic=[x_agama, y_agama, z_agama, vx_agama, vy_agama, vz_agama],
        potential=potentialTotal_local,
        time=inttime,
        trajsize=numsteps)
    #print(c_orb_car[:,0])

    x = c_orb_car[:, 0]
    y = c_orb_car[:, 1]
    z = c_orb_car[:, 2]
    vx = c_orb_car[:, 3]
    vy = c_orb_car[:, 4]
    vz = c_orb_car[:, 5]
    R = numpy.sqrt(x**2 + y**2)
    r = numpy.sqrt(x**2 + y**2 + z**2)

    out_filename = 'timeMyr_x_y_z_vx_vy_vz_vR_vTHETA_vPHI__Orbit__AsObserved_LAMOSThvs%d.txt' % (
        LAMOSTHVSid)
    outfile = open(out_filename, 'a')
    outfile.write(
        '#(orbit in the past)\n#time_Myr x y z vx vy vz vR vTHETA vPHI [all normalized by (x,v)=(1 kpc, 1 km/s)]\n'
    )
    for i in range(len(x)):
        #flip the time to get the correct time
        Time_Myr = (-1.) * times_c[i] / (numpy.pi /
                                         (102.396349 * (240. / _V0) *
                                          (_R0 / 8.)))
        #position
        x_ = x[i] * _R0
        y_ = y[i] * _R0
        z_ = z[i] * _R0
        #re-flip the velocity to get the velocity in the past
        vx_ = -vx[i] * _V0
        vy_ = -vy[i] * _V0
        vz_ = -vz[i] * _V0

        R_, phi_, vR_, vTHETA_, vPHI_ = cartesian_2_cylindrical(
            x_, y_, z_, vx_, vy_, vz_)

        printline = '%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n' % (
            Time_Myr, x_, y_, z_, vx_, vy_, vz_, vR_, vTHETA_, vPHI_)
        outfile.write(printline)

    return None
Example #10
0
def compare(ic, inttime, numsteps):
    times = numpy.linspace(0, inttime, numsteps)

    ### integrate the orbit in galpy using MWPotential2014 from galpy
    g_orb_obj = galpy.orbit.Orbit([ic[0], ic[3], ic[5], ic[1], ic[4], ic[2]])
    dt = time.time()
    g_orb_obj.integrate(times, g_pot)
    g_orb = g_orb_obj.getOrbit()
    print('Time to integrate orbit in galpy: %.4g s' % (time.time() - dt))

    ### integrate the orbit with the galpy routine, but using Agama potential instead
    ### (much slower because of repeated transfer of control between C++ and Python
    dt = time.time()
    g_orb_obj.integrate(times[:numsteps // 10], a_pot)
    a_orb = g_orb_obj.getOrbit()
    print(
        'Time to integrate 1/10th of the orbit in galpy using Agama potential: %.4g s'
        % (time.time() - dt))

    ### integrate the same orbit (note different calling conventions - cartesian coordinates as input)
    ### using both the orbit integration routine and the potential from Agama - much faster
    dt = time.time()
    times_c, c_orb_car = agama.orbit(ic=[ic[0],0,ic[1],ic[3],ic[5],ic[4]], \
        potential=a_pot, time=inttime, trajsize=numsteps)
    print('Time to integrate orbit in Agama: %.4g s' % (time.time() - dt))

    ### make it compatible with galpy's convention (native output is in cartesian coordinates)
    c_orb = c_orb_car * 1.0
    c_orb[:, 0] = (c_orb_car[:, 0]**2 + c_orb_car[:, 1]**2)**0.5
    c_orb[:, 3] = c_orb_car[:, 2]

    ### in galpy, this is the only tool that can estimate focal distance,
    ### but it requires the orbit to be computed first
    delta = float(
        galpy.actionAngle.estimateDeltaStaeckel(g_pot, g_orb[:, 0], g_orb[:,
                                                                          3]))
    print('Focal distance estimated from the entire trajectory: Delta=%.4g' %
          delta)

    ### plot the orbit(s) in R,z plane, along with the prolate spheroidal coordinate grid
    plt.figure(figsize=(12, 8))
    plt.axes([0.04, 0.54, 0.45, 0.45])
    plotCoords(delta, 1.5)
    plt.plot(g_orb[:, 0], g_orb[:, 3], 'b', label='galpy')  # R,z
    plt.plot(c_orb[:, 0], c_orb[:, 3], 'g', label='Agama')
    plt.plot(a_orb[:, 0],
             a_orb[:, 3],
             'r',
             label='galpy using Agama potential')
    plt.xlabel("R/8kpc")
    plt.ylabel("z/8kpc")
    plt.xlim(0, 1.2)
    plt.ylim(-1, 1)
    plt.legend(loc='lower left', frameon=False)

    ### create galpy action/angle finder for the given value of Delta
    ### note: using c=False in the routine below is much slower but apparently more accurate,
    ### comparable to the Agama for the same value of delta
    g_actfinder = galpy.actionAngle.actionAngleStaeckel(pot=g_pot,
                                                        delta=delta,
                                                        c=True)

    ### find the actions for each point of the orbit using galpy action finder
    dt = time.time()
    g_act = g_actfinder(g_orb[:, 0],
                        g_orb[:, 1],
                        g_orb[:, 2],
                        g_orb[:, 3],
                        g_orb[:, 4],
                        fixed_quad=True)
    print('Time to compute actions in galpy: %.4g s' % (time.time() - dt))
    print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \
        (numpy.mean(g_act[0]), numpy.std(g_act[0]), numpy.mean(g_act[2]), numpy.std(g_act[2])))

    ### use the Agama action routine for the same value of Delta as in galpy -
    ### the result is almost identical but computed much faster
    dt = time.time()
    c_act = agama.actions(point=c_orb_car, potential=a_pot,
                          fd=delta)  # explicitly specify focal distance
    print(
        'Time to compute actions in Agama using Galpy-estimated focal distance: %.4g s'
        % (time.time() - dt))
    print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \
        (numpy.mean(c_act[:,0]), numpy.std(c_act[:,0]), numpy.mean(c_act[:,1]), numpy.std(c_act[:,1])))

    ### use the Agama action finder (initialized at the beginning) that automatically determines
    ### the best value of Delta (same computational cost as the previous one)
    dt = time.time()
    a_act = a_actfinder(
        c_orb_car)  # use the focal distance estimated by action finder
    print(
        'Time to compute actions in Agama using pre-initialized focal distance: %.4g s'
        % (time.time() - dt))
    print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \
        (numpy.mean(a_act[:,0]), numpy.std(a_act[:,0]), numpy.mean(a_act[:,1]), numpy.std(a_act[:,1])))

    ### use the interpolated Agama action finder (initialized at the beginning) - less accurate but faster
    dt = time.time()
    i_act = i_actfinder(c_orb_car)
    print(
        'Time to compute actions in Agama with interpolated action finder: %.4g s'
        % (time.time() - dt))
    print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \
        (numpy.mean(i_act[:,0]), numpy.std(i_act[:,0]), numpy.mean(i_act[:,1]), numpy.std(i_act[:,1])))

    ### plot Jr vs Jz
    plt.axes([0.54, 0.54, 0.45, 0.45])
    plt.plot(g_act[0], g_act[2], c='b', label='galpy')
    plt.plot(c_act[:, 0],
             c_act[:, 1],
             c='g',
             label=r'Agama,$\Delta=%.4f$' % delta)
    plt.plot(a_act[:, 0], a_act[:, 1], c='r', label=r'Agama,$\Delta=$auto')
    plt.plot(i_act[:, 0], i_act[:, 1], c='c', label=r'Agama,interpolated')
    plt.xlabel("$J_r$")
    plt.ylabel("$J_z$")
    plt.legend(loc='lower left', frameon=False)

    ### plot Jr(t) and Jz(t)
    plt.axes([0.04, 0.04, 0.95, 0.45])
    plt.plot(times, g_act[0], c='b', label='galpy')
    plt.plot(times, g_act[2], c='b')
    plt.plot(times_c, c_act[:, 0], c='g', label='Agama,$\Delta=%.4f$' % delta)
    plt.plot(times_c, c_act[:, 1], c='g')
    plt.plot(times_c, a_act[:, 0], c='r', label='Agama,$\Delta=$auto')
    plt.plot(times_c, a_act[:, 1], c='r')
    plt.plot(times_c, i_act[:, 0], c='c', label='Agama,interpolated')
    plt.plot(times_c, i_act[:, 1], c='c')
    plt.text(0, c_act[0, 0], '$J_r$', fontsize=16)
    plt.text(0, c_act[0, 1], '$J_z$', fontsize=16)
    plt.xlabel("t")
    plt.ylabel("$J_r, J_z$")
    plt.legend(loc='center right', ncol=2, frameon=False)
    #plt.ylim(0.14,0.25)
    plt.xlim(0, 50)
    plt.show()
for i in range(len(gridr)):
    print("%s: mass= %g" % (target[i], rhs[i]))

# construct initial conditions for the orbit library:
# use the anisotropic Jeans eqs to set the (approximate) shape of the velocity ellipsoid and the mean v_phi;
beta = 0.0  # velocity anisotropy in R/z plane: >0 - sigma_R>sigma_z, <0 - reverse.
kappa = 0.8  # sets the amount of rotation v_phi vs. dispersion sigma_phi; 1 is rather fast rotation, 0 - no rot.
initcond, _ = potstars.sample(10000, potential=pot, beta=beta, kappa=kappa)

# integration time is 100 orbital periods
inttimes = 100 * pot.Tcirc(initcond)

# integrate all orbits, storing the recorded density data and trajectories
data, trajs = agama.orbit(potential=pot,
                          ic=initcond,
                          time=inttimes,
                          trajsize=100,
                          targets=target)

# assemble the matrix equation which contains two blocks:
# total mass, discretized density

# a single value for the total mass constraint, each orbit contributes 1 to it
mass = potstars.totalMass()
data0 = numpy.ones((len(initcond), 1))

# solve the matrix equation for orbit weights
weights = agama.solveOpt(matrix=(data0.T, data.T),
                         rhs=([mass], rhs),
                         rpenl=([numpy.inf], numpy.ones(len(rhs)) * numpy.inf),
                         xpenq=numpy.ones(len(initcond)))
Example #12
0
ax[0].plot(r, (-r * pot_axi[1].force(xyz)[:, 0])**0.5, 'y', label='halo')
ax[0].plot(r, (-r * pot_axi.force(xyz)[:, 0])**0.5, 'r', label='total')
ax[0].legend(loc='lower right', frameon=False)
ax[0].set_xlabel('radius [kpc]')
ax[0].set_ylabel('circular velocity [km/s]')

# integrate and show a few orbits
numorbits = 10
numpy.random.seed(42)
ic = numpy.random.normal(size=(numorbits, 6)) * numpy.array(
    [2.0, 0.0, 0.4, 50., 40., 30.])
ic[:, 0] += -6.
ic[:, 4] += 220
orbits = agama.orbit(potential=pot,
                     ic=ic,
                     time=10.,
                     trajsize=1000,
                     Omega=-39.0)[:, 1]
bar_angle = -25.0 * numpy.pi / 180  # orientation of the bar w.r.t. the Sun
sina, cosa = numpy.sin(bar_angle), numpy.cos(bar_angle)
rmax = 10.0  # plotting range
cmap = plt.get_cmap('mist')
for i, o in enumerate(orbits):
    ax[1].plot(o[:, 0] * cosa - o[:, 1] * sina,
               o[:, 0] * sina + o[:, 1] * cosa,
               color=cmap(i * 1.0 / numorbits),
               lw=0.5)
ax[1].plot(-8.2, 0.0, 'ko', ms=5)  # Solar position
ax[1].text(-8.0, 0.0, 'Sun')
ax[1].set_xlabel('x [kpc]')
ax[1].set_ylabel('y [kpc]')
Example #13
0
    return numpy.column_stack(
        (o[:, 0] * numpy.cos(om * t) + o[:, 1] * numpy.sin(om * t),
         o[:, 1] * numpy.cos(om * t) - o[:, 0] * numpy.sin(om * t), o[:, 2],
         o[:, 3] * numpy.cos(om * t) + o[:, 4] * numpy.sin(om * t),
         o[:, 4] * numpy.cos(om * t) - o[:, 3] * numpy.sin(om * t), o[:, 5]))


# variant 1: set up two fixed point masses (Sun and super-Earth of mass 0.001 Msun),
# and integrate the test-particle orbit in the rotating frame, in which Sun&Earth are stationary
p1 = agama.Potential(
    dict(type='plummer', mass=0.999, scaleradius=0, center="0.001,0,0"),  # Sun
    dict(type='plummer', mass=0.001, scaleradius=0,
         center="-.999,0,0"))  # Earth (very massive one)
t1, o1 = agama.orbit(potential=p1,
                     ic=[r0, 0, 0, 0, v0, 0],
                     time=tmax,
                     trajsize=501,
                     Omega=om)
E1 = p1.potential(o1[:, 0:3]) + 0.5 * numpy.sum(
    o1[:, 3:6]**2, axis=1) - (o1[:, 0] * o1[:, 4] - o1[:, 1] * o1[:, 3]) * om
ax[0].plot(o1[:, 0], o1[:, 1])
ax[1].plot(t1 * tu, o1[:, 0], c='b')
ax[1].plot(t1 * tu, o1[:, 1], c='b', dashes=[3, 2])
ax[2].plot(t1 * tu, E1, label='Two fixed point masses in rotating frame')

# variant 2: same setup, but now make the two point masses move on circular orbits,
# and integrate the orbit of the test particle in the inertial frame
tt = numpy.linspace(0, tmax, 2001)
numpy.savetxt(
    'tmp_center1',
    numpy.column_stack(
def compare(ic, inttime, numsteps):
    times = numpy.linspace(0, inttime, numsteps)
    times1 = times[:numsteps //
                   10]  # compute only 1/10th of the orbit to save time in galpy

    ### integrate the orbit in galpy using the native MWPotential2014 from galpy
    g_orb_obj = galpy.orbit.Orbit(ic)
    dt = time.time()
    g_orb_obj.integrate(times, g_pot_native)
    g_orb_g_native = g_orb_obj.getOrbit()
    print(
        'Time to integrate the orbit in galpy, using galpy-native potential [1]: %.4g s'
        % (time.time() - dt))

    ### integrate the orbit again with the galpy routine, but now using the chimera potential
    ### representing a galpy-native underlying potential.
    ### since galpy has no idea that this potential has a C implementation, it switches to a slower
    ### pure-Python integration algorithm, so to save time, we compute only 1/10th of the orbit
    dt = time.time()
    g_orb_obj.integrate(times1, g_pot_hybrid)
    g_orb_g_hybrid = g_orb_obj.getOrbit()
    print(
        'Time to integrate 1/10th of the orbit in galpy, using galpy-hybrid potential [2]: %.4g s'
        % (time.time() - dt))

    ### integrate the orbit with the galpy routine, but using the chimera potential
    ### representing an agama-native underlying potential instead
    ### (also much slower because of repeated transfer of control between C++ and Python)
    dt = time.time()
    g_orb_obj.integrate(times1, a_pot_hybrid)
    g_orb_a_hybrid = g_orb_obj.getOrbit()
    print(
        'Time to integrate 1/10th of the orbit in galpy, using agama-hybrid potential [3]: %.4g s'
        % (time.time() - dt))

    ### integrate the orbit with the agama routine, using the galpy-native potential through the chimera
    ### (note different calling conventions and the use of cartesian coordinates)
    dt = time.time()
    a_orb_g_hybrid = agama.orbit(potential=g_pot_hybrid,
                                 time=inttime,
                                 trajsize=numsteps,
                                 ic=toCar(ic))[1]
    print(
        'Time to integrate the orbit in agama, using galpy-hybrid potential [4]: %.4g s'
        % (time.time() - dt))

    ### integrate the orbit in a native agama potential approximation constructed from the galpy potential
    dt = time.time()
    a_orb_g_approx = agama.orbit(potential=g_pot_approx,
                                 time=inttime,
                                 trajsize=numsteps,
                                 ic=toCar(ic))[1]
    print(
        'Time to integrate the orbit in agama, using galpy-approx potential [5]: %.4g s'
        % (time.time() - dt))

    ### using both the orbit integration routine and the native potential from agama - much faster
    dt = time.time()
    a_orb_a_native = agama.orbit(potential=a_pot_native,
                                 time=inttime,
                                 trajsize=numsteps,
                                 ic=toCar(ic))[1]
    print(
        'Time to integrate the orbit in agama, using agama-native potential [6]: %.4g s'
        % (time.time() - dt))

    ### the same but with the chimera potential representing an agama-native potential
    ### (should be identical to the above, since in both cases the same underlying C++ object is used)
    dt = time.time()
    a_orb_a_hybrid = agama.orbit(potential=a_pot_hybrid,
                                 time=inttime,
                                 trajsize=numsteps,
                                 ic=toCar(ic))[1]
    print(
        'Time to integrate the orbit in agama, using agama-hybrid potential [7]: %.4g s'
        % (time.time() - dt))

    ### compare the differences between the orbits computed in different ways
    ### (both the potentials and integration routines are not exactly equivalent);
    ### use only common initial segment (1/10th of the orbit) for comparison
    print('Differences between orbits: ' + '[1]-[2]=%g, ' % numpy.max(
        numpy.abs(toCar(g_orb_g_native[:len(times1)]) - toCar(g_orb_g_hybrid))
    ) + '[1]-[3]=%g, ' % numpy.max(
        numpy.abs(toCar(g_orb_g_native[:len(times1)]) - toCar(g_orb_a_hybrid)))
          + '[1]-[4]=%g, ' % numpy.max(
              numpy.abs(toCar(g_orb_g_native) - a_orb_g_hybrid)[:len(times1)])
          + '[1]-[5]=%g, ' % numpy.max(
              numpy.abs(toCar(g_orb_g_native) - a_orb_g_approx)[:len(times1)])
          + '[1]-[6]=%g, ' % numpy.max(
              numpy.abs(toCar(g_orb_g_native) - a_orb_a_native)[:len(times1)])
          + '[6]-[4]=%g, ' %
          numpy.max(numpy.abs(a_orb_a_native - a_orb_g_hybrid)[:len(times1)]) +
          '[6]-[7]=%g' %
          numpy.max(numpy.abs(a_orb_a_native - a_orb_a_hybrid)[:len(times1)])
          )  # should be zero

    ### convert the orbits to the same galpy coordinate convention
    gg_orb = g_orb_g_native  # it's already in this convention
    ga_orb = g_orb_a_hybrid
    ag_orb = toCyl(a_orb_g_hybrid)
    aa_orb = toCyl(a_orb_a_native)
    ### in galpy, this is the only tool that can estimate focal distance,
    ### but it requires the orbit to be computed first
    delta = float(
        galpy.actionAngle.estimateDeltaStaeckel(g_pot_hybrid, gg_orb[:, 0],
                                                gg_orb[:, 3]))
    print('Focal distance estimated from the entire trajectory: Delta=%.4g' %
          delta)

    ### plot the orbit(s) in R,z plane, along with the prolate spheroidal coordinate grid
    plt.figure(figsize=(12, 8))
    plt.axes([0.06, 0.56, 0.43, 0.43])
    plotCoords(delta, 1.5)
    plt.plot(gg_orb[:, 0], gg_orb[:, 3], 'b', label='galpy native')  # R,z
    plt.plot(aa_orb[:, 0],
             aa_orb[:, 3],
             'g',
             label='agama native',
             dashes=[4, 2])
    plt.plot(ag_orb[:, 0],
             ag_orb[:, 3],
             'y',
             label='agama using galpy potential',
             dashes=[1, 1])
    plt.plot(ga_orb[:, 0],
             ga_orb[:, 3],
             'r',
             label='galpy using agama potential')
    plt.xlabel("R/8kpc")
    plt.ylabel("z/8kpc")
    plt.xlim(0, 1.2)
    plt.ylim(-1, 1)
    plt.legend(loc='lower left', ncol=2)

    ### create galpy action/angle finder for the given value of Delta
    ### note: using c=False in the routine below is much slower but apparently more accurate,
    ### comparable to the agama for the same value of delta
    g_actfinder = galpy.actionAngle.actionAngleStaeckel(pot=g_pot_native,
                                                        delta=delta,
                                                        c=True)

    ### find the actions for each point of the orbit using galpy action finder
    dt = time.time()
    g_act = g_actfinder(gg_orb[:, 0],
                        gg_orb[:, 1],
                        gg_orb[:, 2],
                        gg_orb[:, 3],
                        gg_orb[:, 4],
                        fixed_quad=True)
    print('Time to compute actions in galpy: %.4g s' % (time.time() - dt))
    print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \
        (numpy.mean(g_act[0]), numpy.std(g_act[0]), numpy.mean(g_act[2]), numpy.std(g_act[2])))

    ### use the agama action routine for the same value of Delta as in galpy (explicity specify focal distance):
    ### the result is almost identical but computed much faster
    dt = time.time()
    c_act = agama.actions(point=a_orb_a_hybrid,
                          potential=a_pot_hybrid,
                          fd=delta)
    print(
        'Time to compute actions in agama using galpy-estimated focal distance: %.4g s'
        % (time.time() - dt))
    print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \
        (numpy.mean(c_act[:,0]), numpy.std(c_act[:,0]), numpy.mean(c_act[:,1]), numpy.std(c_act[:,1])))

    ### use the agama action finder (initialized at the beginning) that automatically determines
    ### the best value of Delta (same computational cost as the previous one)
    dt = time.time()
    a_act = a_actfinder(
        a_orb_a_hybrid)  # use the focal distance estimated by action finder
    print(
        'Time to compute actions in agama using pre-initialized focal distance: %.4g s'
        % (time.time() - dt))
    print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \
        (numpy.mean(a_act[:,0]), numpy.std(a_act[:,0]), numpy.mean(a_act[:,1]), numpy.std(a_act[:,1])))

    ### use the interpolated agama action finder (initialized at the beginning) - less accurate but faster
    dt = time.time()
    i_act = i_actfinder(a_orb_a_hybrid)
    print(
        'Time to compute actions in agama with interpolated action finder: %.4g s'
        % (time.time() - dt))
    print('Jr = %.6g +- %.4g, Jz = %.6g +- %.4g' % \
        (numpy.mean(i_act[:,0]), numpy.std(i_act[:,0]), numpy.mean(i_act[:,1]), numpy.std(i_act[:,1])))

    ### plot Jr vs Jz
    plt.axes([0.55, 0.56, 0.43, 0.43])
    plt.plot(g_act[0], g_act[2], c='b', label='galpy')
    plt.plot(c_act[:, 0],
             c_act[:, 1],
             c='g',
             label=r'agama, $\Delta=%.4f$' % delta,
             dashes=[4, 2])
    plt.plot(a_act[:, 0], a_act[:, 1], c='r', label=r'agama, $\Delta=$auto')
    plt.plot(i_act[:, 0], i_act[:, 1], c='c', label=r'agama, interpolated')
    plt.xlabel("$J_r$")
    plt.ylabel("$J_z$")
    plt.legend(loc='lower left', frameon=False)

    ### plot Jr(t) and Jz(t)
    plt.axes([0.06, 0.06, 0.92, 0.43])
    plt.plot(times, g_act[0], c='b', label='galpy')
    plt.plot(times, g_act[2], c='b')
    plt.plot(times,
             c_act[:, 0],
             c='g',
             label='agama, $\Delta=%.4f$' % delta,
             dashes=[4, 2])
    plt.plot(times, c_act[:, 1], c='g', dashes=[4, 2])
    plt.plot(times, a_act[:, 0], c='r', label='agama, $\Delta=$auto')
    plt.plot(times, a_act[:, 1], c='r')
    plt.plot(times, i_act[:, 0], c='c', label='agama, interpolated')
    plt.plot(times, i_act[:, 1], c='c')
    plt.text(0, c_act[0, 0], '$J_r$', fontsize=16)
    plt.text(0, c_act[0, 1], '$J_z$', fontsize=16)
    plt.xlabel("t")
    plt.ylabel("$J_r, J_z$")
    plt.legend(loc='center right', ncol=2, frameon=False)
    #plt.ylim(0.14,0.25)
    plt.xlim(0, 50)
    plt.show()
Example #15
0
ax = plt.subplots(2, 2, figsize=(15, 10))[1]
pot = agama.Potential(type='Plummer', mass=10, axisratioz=.6)
act = [1.0, 2.0, 3.0]  # Jr, Jz, Jphi - some fiducial values
am = agama.ActionMapper(pot,
                        act)  # J,theta -> x,v (Torus), with the given actions
af = agama.ActionFinder(pot)  # x,v -> J,theta (Staeckel fudge)
t = numpy.linspace(0, 100, 1001)
# construct the orbit using Torus
xv_torus = am(
    numpy.column_stack((am.Omegar * t, am.Omegaz * t, am.Omegaphi * t)))
ax[0, 0].plot((xv_torus[:, 0]**2 + xv_torus[:, 1]**2)**0.5,
              xv_torus[:, 2],
              label='torus')
# construct the orbit by numerically integrating the equations of motion
_, xv_orbit = agama.orbit(ic=xv_torus[0],
                          potential=pot,
                          time=t[-1],
                          trajsize=len(t))
ax[0, 0].plot((xv_orbit[:, 0]**2 + xv_orbit[:, 1]**2)**0.5,
              xv_orbit[:, 2],
              label='orbit')
# compute actions for the torus orbit using Staeckel approximation
J, theta, Omega = af(xv_torus, angles=True)
ax[0, 1].plot(t, J, label='J,torus')
ax[1, 1].plot(t, Omega, label='Omega,torus')
ax[1, 0].plot(t, theta, label='theta,torus')
# same for the actual orbit
J, theta, Omega = af(xv_orbit, angles=True)
ax[0, 1].plot(t, J, label='J,orbit')
ax[1, 1].plot(t, Omega, label='Omega,orbit')
ax[1, 0].plot(t, theta, label='theta,orbit')
ax[0, 0].legend()
Example #16
0
tar_shell = agama.Target(type='KinemShell', gridr=gridr, degree=1)
degree = 2  # B-spline degree for LOSVD representation (2 or 3 are strongly recommended)
tar_losvd = agama.Target(type='LOSVD',
                         degree=degree,
                         apertures=poly,
                         gridx=gridx,
                         gridv=gridv,
                         symmetry='s')

# generate N-body samples from the model,
# and integrate orbits with (some of) these initial conditions
xv, mass = gm.sample(1000000)
ic = xv[:10000]  # use only a subset of ICs, to save time
mat_dens, mat_shell, mat_losvd = agama.orbit(
    potential=pot,
    ic=ic,
    time=100 * pot.Tcirc(ic),
    targets=[tar_dens, tar_shell, tar_losvd])

# as the IC were drawn from the actual DF of the model,
# we expect that all orbits have the same weight in the model
orbitweight = pot.totalMass() / len(ic)

# now apply the targets to several kinds of objects:
print("Applying Targets to various objects (takes time)...")
# 1) collection of orbits, summing up equally-weighted contributions of all orbits
dens_orb = numpy.sum(mat_dens, axis=0) * orbitweight
shell_orb = numpy.sum(mat_shell, axis=0) * orbitweight
losvd_orb = numpy.sum(mat_losvd, axis=0) * orbitweight
# 2) the entire model (df + potential)
dens_df = tar_dens(gm)
Example #17
0
def calculate_orbital_shape(xGC_norm, yGC_norm, zGC_norm, vxGC_norm, vyGC_norm,
                            vzGC_norm, inttime, numsteps):
    # agama convention
    x_agama = xGC_norm
    y_agama = yGC_norm
    z_agama = zGC_norm
    vx_agama = vxGC_norm
    vy_agama = vyGC_norm
    vz_agama = vzGC_norm

    R_agama = numpy.sqrt(x_agama**2 + y_agama**2)
    vR_agama = (x_agama * vx_agama + y_agama * vy_agama) / R_agama
    vT_agama = -(x_agama * vy_agama - y_agama * vx_agama) / R_agama
    phi_agama = numpy.arctan2(y_agama, x_agama)

    inttime_back_Myr = _inttime_back_Myr
    #numpy.sqrt(x_**2 + y_**2 + z_**2)*_R0_norm*2.0/(numpy.sqrt(vx_**2 + vy_**2 + vz_**2)*_V0_norm/1000.)
    inttime_back_ = inttime_back_Myr * (
        numpy.pi /
        (102.396349 * (240. / _V0) *
         (_R0 / 8.)))  #Roughly: 102Myr = 3.14 if _R0_norm=8 and _V0_norm=240
    numsteps = 3000
    times = numpy.linspace(0, inttime, numsteps)
    times_c, c_orb_car = agama.orbit(
        ic=[x_agama, y_agama, z_agama, vx_agama, vy_agama, vz_agama],
        potential=potentialTotal_local,
        time=inttime,
        trajsize=numsteps)
    #print(c_orb_car[:,0])

    x = c_orb_car[:, 0]
    y = c_orb_car[:, 1]
    z = c_orb_car[:, 2]
    vx = c_orb_car[:, 3]
    vy = c_orb_car[:, 4]
    vz = c_orb_car[:, 5]
    R = numpy.sqrt(x**2 + y**2)
    r = numpy.sqrt(x**2 + y**2 + z**2)

    out_filename = 'x_y_z_vx_vy_vz_vR_vTHETA_vPHI__Orbit__AsObserved_LAMOSThvs%d.txt' % (
        LAMOSTHVSid)
    outfile = open(out_filename, 'a')
    outfile.write(
        '# x y z vx vy vz vR vTHETA vPHI [all normalized by (x,v)=(1 kpc, 1 km/s)]\n'
    )
    for i in range(len(x)):
        x_ = x[i] * _R0
        y_ = y[i] * _R0
        z_ = z[i] * _R0
        vx_ = vx[i] * _V0
        vy_ = vy[i] * _V0
        vz_ = vz[i] * _V0

        R_, phi_, vR_, vTHETA_, vPHI_ = cartesian_2_cylindrical(
            x_, y_, z_, vx_, vy_, vz_)

        printline = '%lf %lf %lf %lf %lf %lf %lf %lf %lf\n' % (
            x_, y_, z_, vx_, vy_, vz_, vR_, vTHETA_, vPHI_)
        outfile.write(printline)

    return None
Example #18
0
def compare(ic, inttime, numsteps):
    g_orb_obj = galpy.orbit.Orbit([ic[0],ic[3],ic[5],ic[1],ic[4],ic[2]])
    times = numpy.linspace(0, inttime, numsteps)
    dt = time.time()
    g_orb_obj.integrate(times, g_pot)
    g_orb = g_orb_obj.getOrbit()
    print 'Time to integrate orbit in galpy: %s s' % (time.time()-dt)
    dt = time.time()
    times_c, c_orb_car = agama.orbit(ic=[ic[0],0,ic[1],ic[3],ic[5],ic[4]], potential=w_pot._pot, time=inttime, trajsize=numsteps)
    print 'Time to integrate orbit in Agama: %s s' % (time.time()-dt)
    ### make it compatible with galpy's convention (native output is in cartesian coordinates)
    c_orb = c_orb_car*1.0
    c_orb[:,0] = (c_orb_car[:,0]**2+c_orb_car[:,1]**2)**0.5
    c_orb[:,3] = c_orb_car[:,2]

    ### in galpy, this is the only tool that can estimate focal distance,
    ### but it requires the orbit to be computed first
    delta = estimateDeltaStaeckel(g_pot, g_orb[:,0], g_orb[:,3])
    print "interfocal distance Delta=",delta

    ### plot the orbit(s) in R,z plane, along with the prolate spheroidal coordinate grid
    plt.axes([0.05, 0.55, 0.45, 0.45])
    plotCoords(delta, 1.5)
    plt.plot(g_orb[:,0],g_orb[:,3], 'b', label='galpy')  # R,z
    plt.plot(c_orb[:,0],c_orb[:,3], 'g', label='Agama')  # R,z
    plt.xlabel("R/8kpc")
    plt.ylabel("z/8kpc")
    plt.xlim(0, 1.2)
    plt.ylim(-1,1)
    plt.legend()

    ### plot R(t), z(t)
    plt.axes([0.55, 0.55, 0.45, 0.45])
    plt.plot(times, g_orb[:,0], label='R')
    plt.plot(times, g_orb[:,3], label='z')
    plt.xlabel("t")
    plt.ylabel("R,z")
    plt.legend()
    plt.xlim(0,50)

    ### create galpy action/angle finder for the given value of Delta
    ### note: using c=False in the routine below is much slower but apparently more accurate,
    ### comparable to the Agama for the same value of delta
    g_actfinder = galpy.actionAngle.actionAngleStaeckel(pot=g_pot, delta=delta, c=True)

    ### find the actions for each point of the orbit
    dt = time.time()
    g_act = g_actfinder(g_orb[:,0],g_orb[:,1],g_orb[:,2],g_orb[:,3],g_orb[:,4],fixed_quad=True)
    print 'Time to compute actions in galpy: %s s' % (time.time()-dt)

    ### use the Agama action routine for the same value of Delta as in galpy
    dt = time.time()
    c_act = agama.actions(point=c_orb_car, potential=w_pot._pot, fd=delta)   # explicitly specify focal distance
    print 'Time to compute actions in Agama using Galpy-estimated focal distance: %s s' % (time.time()-dt)

    ### use the Agama action finder (initialized at the beginning) that automatically determines the best value of Delta
    dt = time.time()
    a_act = c_actfinder(c_orb_car)   # use the focal distance estimated by action finder
    print 'Time to compute actions in Agama using pre-initialized focal distance: %s s' % (time.time()-dt)

    ### use the interpolated Agama action finder (initialized at the beginning) - less accurate but faster
    dt = time.time()
    i_act = i_actfinder(c_orb_car)
    print 'Time to compute actions in Agama with interpolated action finder: %s s' % (time.time()-dt)

    ### plot Jr vs Jz
    plt.axes([0.05, 0.05, 0.45, 0.45])
    plt.plot(g_act[0],g_act[2], label='galpy')
    plt.plot(c_act[:,0],c_act[:,1], label=r'Agama,$\Delta='+str(delta)+'$')
    plt.plot(a_act[:,0],a_act[:,1], label=r'Agama,$\Delta=$auto')
    plt.plot(i_act[:,0],i_act[:,1], label=r'Agama,interpolated')
    plt.xlabel("$J_r$")
    plt.ylabel("$J_z$")
    plt.legend(loc='lower left')

    ### plot Jr(t) and Jz(t)
    plt.axes([0.55, 0.05, 0.45, 0.45])
    plt.plot(times, g_act[0], label='galpy', c='b')
    plt.plot(times, g_act[2], c='b')
    plt.plot(times_c, c_act[:,0], label='Agama,$\Delta='+str(delta)+'$', c='g')
    plt.plot(times_c, c_act[:,1], c='g')
    plt.plot(times_c, a_act[:,0], label='Agama,$\Delta=$auto', c='r')
    plt.plot(times_c, a_act[:,1], c='r')
    plt.plot(times_c, i_act[:,0], label='Agama,interpolated', c='c')
    plt.plot(times_c, i_act[:,1], c='c')
    plt.text(0, c_act[0,0], '$J_r$', fontsize=16)
    plt.text(0, c_act[0,1], '$J_z$', fontsize=16)
    plt.xlabel("t")
    plt.ylabel("$J_r, J_z$")
    plt.legend(loc='center right')
    plt.ylim(0.14,0.25)
    plt.xlim(0,50)
    plt.show()
Example #19
0
def calculate_star_and_LMC_orbits_PAST(xGC_norm, yGC_norm, zGC_norm, vxGC_norm,
                                       vyGC_norm,
                                       vzGC_norm):  #, inttime, numsteps):
    # agama convention
    # already normalized position
    x_agama = xGC_norm
    y_agama = yGC_norm
    z_agama = zGC_norm
    # FLIP already normalized velocity
    vx_agama = -vxGC_norm
    vy_agama = -vyGC_norm
    vz_agama = -vzGC_norm

    inttime_back_Myr = _inttime_back_Myr
    inttime_back_ = inttime_back_Myr * (
        numpy.pi /
        (102.396349 * (240. / _V0) *
         (_R0 / 8.)))  #Roughly: 102Myr = 3.14 if _R0_norm=8 and _V0_norm=240

    inttime = inttime_back_
    numsteps = 3000
    times = numpy.linspace(0, inttime, numsteps)
    times_c, c_orb_car = agama.orbit(
        ic=[x_agama, y_agama, z_agama, vx_agama, vy_agama, vz_agama],
        potential=potentialTotal_local,
        time=inttime,
        trajsize=numsteps)
    #print(c_orb_car[:,0])

    x = c_orb_car[:, 0]
    y = c_orb_car[:, 1]
    z = c_orb_car[:, 2]
    vx = c_orb_car[:, 3]
    vy = c_orb_car[:, 4]
    vz = c_orb_car[:, 5]
    R = numpy.sqrt(x**2 + y**2)
    r = numpy.sqrt(x**2 + y**2 + z**2)

    #LMC position in the MW-center coordinate system.
    xLMC_norm, yLMC_norm, zLMC_norm, vxLMC_norm, vyLMC_norm, vzLMC_norm = get_LMC_6D(
    )
    # already normalized position
    xLMC_agama = xLMC_norm
    yLMC_agama = yLMC_norm
    zLMC_agama = zLMC_norm
    # FLIP already normalized velocity
    vxLMC_agama = -vxLMC_norm
    vyLMC_agama = -vyLMC_norm
    vzLMC_agama = -vzLMC_norm

    #The same orbit integration as the target star
    times_cLMC, c_orb_carLMC = agama.orbit(ic=[
        xLMC_agama, yLMC_agama, zLMC_agama, vxLMC_agama, vyLMC_agama,
        vzLMC_agama
    ],
                                           potential=potentialTotal_local,
                                           time=inttime,
                                           trajsize=numsteps)

    xLMC = c_orb_carLMC[:, 0]
    yLMC = c_orb_carLMC[:, 1]
    zLMC = c_orb_carLMC[:, 2]
    vxLMC = c_orb_carLMC[:, 3]
    vyLMC = c_orb_carLMC[:, 4]
    vzLMC = c_orb_carLMC[:, 5]

    t_dmin_Myr = 99999.
    dmin_kpc = 99999.

    #out_filename = 'timeMyr_x_y_z_vx_vy_vz__timeMyr_xLMC_yLMC_zLMC_vxLMC_vyLMC_vzLMC__timeMyr_dx_dy_dz_dvx_dvy_dvz__AsObserved.txt'
    #outfile      = open(out_filename,'a')
    #outfile.write('#(orbit in the past)\n#[time_Myr x y z vx vy vz]  [time_Myr x y z vx vy vz]LMC  [time_Myr x y z vx vy vz]diff\n')
    for i in range(len(x)):
        #flip the time to get the correct time
        Time_Myr = (-1.) * times_c[i] / (numpy.pi /
                                         (102.396349 * (240. / _V0) *
                                          (_R0 / 8.)))
        #position
        x_ = x[i] * _R0
        y_ = y[i] * _R0
        z_ = z[i] * _R0
        #re-flip the velocity to get the velocity in the past
        vx_ = -vx[i] * _V0
        vy_ = -vy[i] * _V0
        vz_ = -vz[i] * _V0

        #flip the time to get the correct time
        Time_Myr_LMC = (-1.) * times_c[i] / (numpy.pi /
                                             (102.396349 * (240. / _V0) *
                                              (_R0 / 8.)))
        #position
        xL_ = xLMC[i] * _R0
        yL_ = yLMC[i] * _R0
        zL_ = zLMC[i] * _R0
        #re-flip the velocity to get the velocity in the past
        vxL_ = -vxLMC[i] * _V0
        vyL_ = -vyLMC[i] * _V0
        vzL_ = -vzLMC[i] * _V0

        #flip the time to get the correct time
        Time_Myr_LMC = (-1.) * times_c[i] / (numpy.pi /
                                             (102.396349 * (240. / _V0) *
                                              (_R0 / 8.)))
        #relative position
        dx_ = x_ - xL_
        dy_ = y_ - yL_
        dz_ = z_ - zL_
        dvx_ = vx_ - vxL_
        dvy_ = vy_ - vxL_
        dvz_ = vz_ - vxL_

        d_kpc = numpy.sqrt(dx_**2 + dy_**2 + dz_**2) * _R0
        dv_kms = numpy.sqrt(dvx_**2 + dvy_**2 + dvz_**2) * _V0
        if (d_kpc < dmin_kpc):
            t_dmin_Myr = Time_Myr
        #print(t_dmin_Myr, d_kpc)
        """
        printline='%lf %.3lf %.3lf %.3lf %.3lf %.3lf %.3lf   %lf %.3lf %.3lf %.3lf %.3lf %.3lf %.3lf   %lf %.3lf %.3lf %.3lf %.3lf %.3lf %.3lf\n' % (Time_Myr,      x_,  y_,  z_,  vx_,  vy_,  vz_,
                        Time_Myr_LMC,  xL_, yL_, zL_, vxL_, vyL_, vzL_,
                        Time_Myr,     dx_, dy_, dz_, dvx_, dvy_, dvz_ )
        """
        #outfile.write(printline)

    x_func = scipy.interpolate.interp1d(times_c, x, kind='cubic')
    y_func = scipy.interpolate.interp1d(times_c, y, kind='cubic')
    z_func = scipy.interpolate.interp1d(times_c, z, kind='cubic')
    vx_func = scipy.interpolate.interp1d(times_c, vx, kind='cubic')
    vy_func = scipy.interpolate.interp1d(times_c, vy, kind='cubic')
    vz_func = scipy.interpolate.interp1d(times_c, vz, kind='cubic')

    xLMC_func = scipy.interpolate.interp1d(times_c, xLMC, kind='cubic')
    yLMC_func = scipy.interpolate.interp1d(times_c, yLMC, kind='cubic')
    zLMC_func = scipy.interpolate.interp1d(times_c, zLMC, kind='cubic')
    vxLMC_func = scipy.interpolate.interp1d(times_c, vxLMC, kind='cubic')
    vyLMC_func = scipy.interpolate.interp1d(times_c, vyLMC, kind='cubic')
    vzLMC_func = scipy.interpolate.interp1d(times_c, vzLMC, kind='cubic')

    # distance from ejection location (x_ej,y_ej)
    distance2_from_LMC_kpc_func = lambda x: (_R0**2 * (
        (x_func(x) - xLMC_func(x))**2 + (y_func(x) - yLMC_func(x))**2 +
        (z_func(x) - zLMC_func(x))**2))

    result2 = scipy.optimize.minimize_scalar(distance2_from_LMC_kpc_func,
                                             bounds=(times_c[0], times_c[-1]),
                                             method='bounded')

    x_ej = x_func(result2.x) * _R0
    y_ej = y_func(result2.x) * _R0
    z_ej = z_func(result2.x) * _R0
    vx_ej = -vx_func(result2.x) * _V0
    vy_ej = -vy_func(result2.x) * _V0
    vz_ej = -vz_func(result2.x) * _V0

    xLMC_ej = xLMC_func(result2.x) * _R0
    yLMC_ej = yLMC_func(result2.x) * _R0
    zLMC_ej = zLMC_func(result2.x) * _R0
    vxLMC_ej = -vxLMC_func(result2.x) * _V0
    vyLMC_ej = -vyLMC_func(result2.x) * _V0
    vzLMC_ej = -vzLMC_func(result2.x) * _V0

    dx_ej = x_ej - xLMC_ej
    dy_ej = y_ej - yLMC_ej
    dz_ej = z_ej - zLMC_ej
    dvx_ej = vx_ej - vxLMC_ej
    dvy_ej = vy_ej - vyLMC_ej
    dvz_ej = vz_ej - vzLMC_ej

    dmin_kpc = numpy.sqrt(distance2_from_LMC_kpc_func(result2.x))
    dv_kms = numpy.sqrt(dvx_ej**2 + dvy_ej**2 + dvz_ej**2)

    Time_Myr_ej = (result2.x) / (numpy.pi / (102.396349 * (240. / _V0) *
                                             (_R0 / 8.)))

    out_filename = 'timeMyr_dmin_dv__timeMyr_x_y_z_vx_vy_vz__timeMyr_xLMC_yLMC_zLMC_vxLMC_vyLMC_vzLMC__timeMyr_dx_dy_dz_dvx_dvy_dvz__AsObserved_LAMOSThvs%d.txt' % (
        LAMOSTHVSid)
    outfile = open(out_filename, 'a')
    printline = '%.3lf %.3lf %.3lf   %.3lf %.3lf %.3lf %.3lf %.3lf %.3lf %.3lf   %lf %.3lf %.3lf %.3lf %.3lf %.3lf %.3lf   %lf %.3lf %.3lf %.3lf %.3lf %.3lf %.3lf\n' % (
        Time_Myr_ej, dmin_kpc, dv_kms, Time_Myr_ej, x_ej, y_ej, z_ej, vx_ej,
        vy_ej, vz_ej, Time_Myr_ej, xLMC_ej, yLMC_ej, zLMC_ej, vxLMC_ej,
        vyLMC_ej, vzLMC_ej, Time_Myr_ej, dx_, dy_, dz_, dvx_, dvy_, dvz_)
    outfile.write(printline)
    outfile.close()

    print('---')
    print(Time_Myr_ej, dmin_kpc, dv_kms)
    print('===')

    return Time_Myr_ej, dmin_kpc, dv_kms
Example #20
0
def runComponent(comp, pot):
    """
    run the orbit integration, optimization, and construction of an N-body model
    for a given component of the Schwarzschild model
    """
    if comp.has_key('trajsize'):
        result = agama.orbit(potential=pot, ic=comp['ic'], time=comp['inttime'], \
            targets=comp['targets'], trajsize=comp['trajsize'])
        traj = result[-1]
    else:
        result = agama.orbit(potential=pot,
                             ic=comp['ic'],
                             time=comp['inttime'],
                             targets=comp['targets'])
    if type(result) == numpy.array: result = (result, )
    # targets[0] is density, targets[1], if provided, is kinematics
    matrix = list()
    rhs = list()
    rpenl = list()
    matrix.append(result[0].T)
    rhs.append(comp['targets'][0].values())
    mass = rhs[0][-1]  # the last constraint is the total mass
    avgrhs = mass / len(rhs[0])  # typical constraint magnitude
    rpenl.append(numpy.ones_like(rhs[0]) / avgrhs)
    if len(comp['targets']) == 2 and comp.has_key('beta'):
        numrow = len(comp['targets'][1]) / 2
        matrix.append(result[1].T[0:numrow] * 2 * (1 - comp['beta']) -
                      result[1].T[numrow:2 * numrow])
        rhs.append(numpy.zeros(numrow))
        rpenl.append(numpy.ones(numrow) * 10.)
    avgweight = mass / len(comp['ic'])
    xpenq = numpy.ones(len(comp['ic'])) / avgweight**2 / len(comp['ic']) * 0.1
    weights = agama.optsolve(matrix=matrix, rhs=rhs, rpenl=rpenl, xpenq=xpenq)

    # check for any outstanding constraints
    for t in range(len(matrix)):
        delta = matrix[t].dot(weights) - rhs[t]
        norm = 1e-4 * abs(comp['targets'][t].values()) + 1e-8
        for c, d in enumerate(delta):
            if abs(d) > norm[c]:
                print "Constraint", t, " #", c, "not satisfied:", comp[
                    'targets'][t][c], d
    print "Entropy:", -sum(weights * numpy.log(weights+1e-100)) / mass + numpy.log(avgweight), \
        " # of useful orbits:", len(numpy.where(weights >= avgweight)[0]), "/", len(comp['ic'])

    # create an N-body model if needed
    if comp.has_key('nbody'):
        status, particles = agama.sampleOrbitLibrary(comp['nbody'], traj,
                                                     weights)
        if not status:
            indices, trajsizes = particles
            print "reintegrating", len(
                indices), "orbits; max # of sampling points is", max(trajsizes)
            traj[indices] = agama.orbit(potential=pot, ic=comp['ic'][indices], \
                time=comp['inttime'][indices], trajsize=trajsizes)
            status, particles = agama.sampleOrbitLibrary(
                comp['nbody'], traj, weights)
            if not status: print "Failed to produce output N-body model"
        comp['nbodymodel'] = particles

    # output
    comp['weights'] = weights
    comp['densitydata'] = result[0]
    if len(matrix) == 2: comp['kinemdata'] = result[1]
    if comp.has_key('trajsize'): comp['traj'] = traj
    return comp
Example #21
0
def runComponent(comp, pot):
    """
    run the orbit integration, optimization, and construction of an N-body model
    for a given component of the Schwarzschild model
    """
    if hasattr(comp, 'trajsize'):
        result = agama.orbit(potential=pot,
                             ic=comp.ic,
                             time=comp.inttime,
                             Omega=comp.Omega,
                             targets=comp.targets,
                             trajsize=comp.trajsize)
        traj = result[-1]
    else:
        result = agama.orbit(potential=pot,
                             ic=comp.ic,
                             time=comp.inttime,
                             Omega=comp.Omega,
                             targets=comp.targets)
        traj = None
    if type(result) == numpy.array: result = (result, )
    # targets[0] is density, targets[1], if provided, is kinematics
    matrix = list()
    rhs = list()
    rpenl = list()
    mass = comp.density.totalMass()
    # density constraints
    matrix.append(result[0].T)
    rhs.append(comp.targets[0](comp.density))
    avgrhs = mass / len(rhs[0])  # typical magnitude of density constraints
    rpenl.append(numpy.ones_like(rhs[0]) / avgrhs)
    # kinematic constraints
    if len(comp.targets) == 2 and hasattr(comp, 'beta'):
        numrow = len(comp.targets[1]) // 2
        matrix.append(result[1].T[0:numrow] * 2 * (1 - comp.beta) -
                      result[1].T[numrow:2 * numrow])
        rhs.append(numpy.zeros(numrow))
        rpenl.append(numpy.ones(numrow))
    # total mass constraint
    matrix.append(numpy.ones((len(comp.ic), 1)).T)
    rhs.append(numpy.array([mass]))
    rpenl.append(numpy.array([numpy.inf]))
    # regularization (penalty for unequal weights)
    avgweight = mass / len(comp.ic)
    xpenq = numpy.ones(len(comp.ic)) / avgweight**2 / len(comp.ic) * 0.1

    # solve the linear equation for weights
    weights = agama.solveOpt(matrix=matrix, rhs=rhs, rpenl=rpenl, xpenq=xpenq)

    # check for any outstanding constraints
    for t in range(len(matrix)):
        delta = matrix[t].dot(weights) - rhs[t]
        norm = 1e-4 * abs(rhs[t]) + 1e-8
        for c, d in enumerate(delta):
            if abs(d) > norm[c]:
                print("Constraint %i:%i not satisfied: %s, val=%.4g, dif=%.4g" % \
                (t, c, comp.targets[t][c], rhs[t][c], d))
    print("Entropy: %f, # of useful orbits: %i / %i" %\
        ( -sum(weights * numpy.log(weights+1e-100)) / mass + numpy.log(avgweight), \
        len(numpy.where(weights >= avgweight)[0]), len(comp.ic)))

    # create an N-body model if needed
    if hasattr(comp, 'nbody'):
        status, particles = agama.sampleOrbitLibrary(comp.nbody, traj, weights)
        if not status:
            indices, trajsizes = particles
            print("reintegrating %i orbits; max # of sampling points is %i" %
                  (len(indices), max(trajsizes)))
            traj[indices] = agama.orbit(potential=pot, ic=comp.ic[indices], \
                time=comp.inttime[indices], trajsize=trajsizes)
            status, particles = agama.sampleOrbitLibrary(
                comp.nbody, traj, weights)
            if not status: print("Failed to produce output N-body model")
        comp.nbodymodel = particles

    # output
    comp.weights = weights
    comp.densitydata = result[0]
    if len(comp.targets) >= 2: comp.kinemdata = result[1]
    if not traj is None: comp.traj = traj
Example #22
0
target1 = agama.Target(type='DensityClassicLinear', gridr=agama.nonuniformGrid(25, 0.1, 20.0), \
    axisratioy=0.8, axisratioz=0.6, stripsPerPane=2)

# target2 is discretized kinematic constraint (we will enforce velocity isotropy)
target2 = agama.Target(type='KinemShell',
                       gridR=agama.nonuniformGrid(15, 0.2, 10.0),
                       degree=1)

# construct initial conditions for the orbit library
initcond, weightprior = den.sample(5000, potential=pot)

# integration time is 50 orbital periods
inttimes = 50 * pot.Tcirc(initcond)
# integrate all orbits, storing the recorded data corresponding to each target
# in the data1 and data2 arrays, and the trajectories - in trajs
data1, data2, trajs = agama.orbit(potential=pot, ic=initcond, time=inttimes, \
    trajsize=101, targets=[target1,target2])

# assemble the matrix equation which contains three blocks:
# total mass, discretized density, and velocity anisotropy

# a single value for the total mass constraint, each orbit contributes 1 to it
mass = den.totalMass()
data0 = numpy.ones((len(initcond), 1))

# discretized density profile to be used as the density constraint
rhs1 = target1(den)

# data2 is kinematic data: for each orbit (row) it contains
# Ngrid values of rho sigma_r^2, then the same number of values of rho sigma_t^2;
# we combine them into a single array of Ngrid values that enforce isotropy (sigma_t^2 - 2 sigma_r^2 = 0)
Ngrid = len(target2) // 2