Exemplo n.º 1
0
def compare_evolutions():
    '''
    Compare precession averaged and orbit averaged integrations. Plot the
    evolution of xi, J, S and their relative differences between the two
    approaches. Since precession-averaged estimates of S require a random
    sampling, this plot will look different every time this routine is executed.
    Output is saved in ./spin_angles.pdf.
    
    **Run using**

        import precession.test
        precession.test.compare_evolutions()
    '''

    fig = pylab.figure(figsize=(6, 6))  # Create figure object and axes
    L, Ws, Wm, G = 0.85, 0.15, 0.3, 0.03  # Sizes
    ax_Sd = fig.add_axes([0, 0, L, Ws])  # bottom-small
    ax_S = fig.add_axes([0, Ws, L, Wm])  # bottom-main
    ax_Jd = fig.add_axes([0, Ws + Wm + G, L, Ws])  # middle-small
    ax_J = fig.add_axes([0, Ws + Ws + Wm + G, L, Wm])  # middle-main
    ax_xid = fig.add_axes([0, 2 * (Ws + Wm + G), L, Ws])  # top-small
    ax_xi = fig.add_axes([0, Ws + 2 * (Ws + Wm + G), L, Wm])  # top-main

    q = 0.8  # Mass ratio. Must be q<=1.
    chi1 = 0.6  # Primary spin. Must be chi1<=1
    chi2 = 1.  # Secondary spin. Must be chi2<=1
    M, m1, m2, S1, S2 = precession.get_fixed(q, chi1,
                                             chi2)  # Total-mass units M=1
    ri = 100. * M  # Initial separation.
    rf = 10. * M  # Final separation.
    r_vals = numpy.linspace(ri, rf, 1001)  # Output requested
    Ji = 2.24  # Magnitude of J: Jmin<J<Jmax as given by J_lim
    xi = -0.5  # Effective spin: xi_low<xi<xi_up as given by xi_allowed

    Jf_P = precession.evolve_J(xi, Ji, r_vals, q, S1, S2)  # Pr.av. integration
    Sf_P = [
        precession.samplingS(xi, J, q, S1, S2, r)
        for J, r in zip(Jf_P[0::10], r_vals[0::10])
    ]  # Resample S (reduce output for clarity)
    Sb_min, Sb_max = zip(*[
        precession.Sb_limits(xi, J, q, S1, S2, r)
        for J, r in zip(Jf_P, r_vals)
    ])  # Envelopes
    S = numpy.average([precession.Sb_limits(xi, Ji, q, S1, S2,
                                            ri)])  # Initialize S
    Jf_O, xif_O, Sf_O = precession.orbit_averaged(Ji, xi, S, r_vals, q, S1,
                                                  S2)  # Orb.av. integration

    Pcol, Ocol, Dcol = 'blue', 'red', 'green'
    Pst, Ost = 'solid', 'dashed'
    ax_xi.axhline(xi, c=Pcol, ls=Pst, lw=2)  # Plot xi, pr.av. (constant)
    ax_xi.plot(r_vals, xif_O, c=Ocol, ls=Ost, lw=2)  # Plot xi, orbit averaged
    ax_xid.plot(r_vals, (xi - xif_O) / xi * 1e11, c=Dcol,
                lw=2)  # Plot xi deviations (rescaled)
    ax_J.plot(r_vals, Jf_P, c=Pcol, ls=Pst, lw=2)  # Plot J, pr.av.
    ax_J.plot(r_vals, Jf_O, c=Ocol, ls=Ost, lw=2)  # Plot J, orb.av
    ax_Jd.plot(r_vals, (Jf_P - Jf_O) / Jf_O * 1e3, c=Dcol,
               lw=2)  # Plot J deviations (rescaled)
    ax_S.scatter(r_vals[0::10], Sf_P, facecolor='none',
                 edgecolor=Pcol)  # Plot S, pr.av. (resampled)
    ax_S.plot(r_vals, Sb_min, c=Pcol, ls=Pst,
              lw=2)  # Plot S, pr.av. (envelopes)
    ax_S.plot(r_vals, Sb_max, c=Pcol, ls=Pst,
              lw=2)  # Plot S, pr.av. (envelopes)
    ax_S.plot(r_vals, Sf_O, c=Ocol, ls=Ost, lw=2)  # Plot S, orb.av (evolved)
    ax_Sd.plot(r_vals[0::10], (Sf_P - Sf_O[0::10]) / Sf_O[0::10], c=Dcol,
               lw=2)  # Plot S deviations

    # Options for nice plotting
    for ax in [ax_xi, ax_xid, ax_J, ax_Jd, ax_S, ax_Sd]:
        ax.set_xlim(ri, rf)
        ax.yaxis.set_label_coords(-0.16, 0.5)
        ax.spines['left'].set_lw(1.5)
        ax.spines['right'].set_lw(1.5)
    for ax in [ax_xi, ax_J, ax_S]:
        ax.spines['top'].set_lw(1.5)
    for ax in [ax_xid, ax_Jd, ax_Sd]:
        ax.axhline(0, c='black', ls='dotted')
        ax.spines['bottom'].set_lw(1.5)
    for ax in [ax_xid, ax_J, ax_Jd, ax_S]:
        ax.set_xticklabels([])
    ax_xi.set_ylim(-0.55, -0.45)
    ax_J.set_ylim(0.4, 2.3)
    ax_S.set_ylim(0.24, 0.41)
    ax_xid.set_ylim(-0.2, 1.2)
    ax_Jd.set_ylim(-3, 5.5)
    ax_Sd.set_ylim(-0.7, 0.7)
    ax_xid.yaxis.set_major_locator(matplotlib.ticker.MultipleLocator(0.5))
    ax_Jd.yaxis.set_major_locator(matplotlib.ticker.MultipleLocator(2))
    ax_S.yaxis.set_major_locator(matplotlib.ticker.MultipleLocator(0.05))
    ax_Sd.yaxis.set_major_locator(matplotlib.ticker.MultipleLocator(0.5))
    ax_xi.xaxis.set_ticks_position('top')
    ax_xi.xaxis.set_label_position('top')
    ax_Sd.set_xlabel("$r/M$")
    ax_xi.set_xlabel("$r/M$")
    ax_xi.set_ylabel("$\\xi$")
    ax_J.set_ylabel("$J/M^2$")
    ax_S.set_ylabel("$S/M^2$")
    ax_xid.set_ylabel("$\\Delta\\xi/\\xi \;[10^{-11}]$")
    ax_Jd.set_ylabel("$\\Delta J/J \;[10^{-3}]$")
    ax_Sd.set_ylabel("$\\Delta S / S$")

    fig.savefig("compare_evolutions.pdf", bbox_inches='tight')  # Save pdf file
Exemplo n.º 2
0
def PNwrappers():
    '''
    Wrappers of the PN integrators. Here we show how to perform orbit-averaged,
    precession-averaged and hybrid PN inspirals using the various wrappers
    implemented in the code. We also show how to estimate the final mass, spin
    and recoil of the BH remnant following a merger.


    **Run using**

        import precession.test
        precession.test.PNwrappers()
    '''

    q = 0.9  # Mass ratio. Must be q<=1.
    chi1 = 0.5  # Primary spin. Must be chi1<=1
    chi2 = 0.5  # Secondary spin. Must be chi2<=1
    print "We study a binary with\n\tq=%.3f, chi1=%.3f, chi2=%.3f" % (q, chi1,
                                                                      chi2)
    M, m1, m2, S1, S2 = precession.get_fixed(q, chi1,
                                             chi2)  # Total-mass units M=1
    ri = 1000 * M  # Initial separation.
    rf = 10. * M  # Final separation.
    rt = 100. * M  # Intermediate separation for hybrid evolution.
    r_vals = numpy.logspace(numpy.log10(ri), numpy.log10(rf),
                            10)  # Output requested
    t1i = numpy.pi / 4.
    t2i = numpy.pi / 4.
    dpi = numpy.pi / 4.  # Initial configuration
    xii, Ji, Si = precession.from_the_angles(t1i, t2i, dpi, q, S1, S2, ri)
    print "Configuration at ri=%.0f\n\t(xi,J,S)=(%.3f,%.3f,%.3f)\n\t(theta1,theta2,deltaphi)=(%.3f,%.3f,%.3f)" % (
        ri, xii, Ji, Si, t1i, t2i, dpi)

    print " *Orbit-averaged evolution*"
    print "Evolution ri=%.0f --> rf=%.0f" % (ri, rf)
    Jf, xif, Sf = precession.orbit_averaged(Ji, xii, Si, r_vals, q, S1, S2)
    print "\t(xi,J,S)=(%.3f,%.3f,%.3f)" % (xif[-1], Jf[-1], Sf[-1])
    t1f, t2f, dpf = precession.orbit_angles(t1i, t2i, dpi, r_vals, q, S1, S2)
    print "\t(theta1,theta2,deltaphi)=(%.3f,%.3f,%.3f)" % (t1f[-1], t2f[-1],
                                                           dpf[-1])
    Jvec, Lvec, S1vec, S2vec, Svec = precession.Jframe_projection(
        xii, Si, Ji, q, S1, S2, ri)
    Lxi, Lyi, Lzi = Lvec
    S1xi, S1yi, S1zi = S1vec
    S2xi, S2yi, S2zi = S2vec
    Lx, Ly, Lz, S1x, S1y, S1z, S2x, S2y, S2z = precession.orbit_vectors(
        Lxi, Lyi, Lzi, S1xi, S1yi, S1zi, S2xi, S2yi, S2zi, r_vals, q)
    print "\t(Lx,Ly,Lz)=(%.3f,%.3f,%.3f)\n\t(S1x,S1y,S1z)=(%.3f,%.3f,%.3f)\n\t(S2x,S2y,S2z)=(%.3f,%.3f,%.3f)" % (
        Lx[-1], Ly[-1], Lz[-1], S1x[-1], S1y[-1], S1z[-1], S2x[-1], S2y[-1],
        S2z[-1])

    print " *Precession-averaged evolution*"
    print "Evolution ri=%.0f --> rf=%.0f" % (ri, rf)
    Jf = precession.evolve_J(xii, Ji, r_vals, q, S1, S2)
    print "\t(xi,J,S)=(%.3f,%.3f,-)" % (xii, Jf[-1])
    t1f, t2f, dpf = precession.evolve_angles(t1i, t2i, dpi, r_vals, q, S1, S2)
    print "\t(theta1,theta2,deltaphi)=(%.3f,%.3f,%.3f)" % (t1f[-1], t2f[-1],
                                                           dpf[-1])
    print "Evolution ri=%.0f --> infinity" % ri
    kappainf = precession.evolve_J_backwards(xii, Jf[-1], rf, q, S1, S2)
    print "\tkappainf=%.3f" % kappainf
    Jf = precession.evolve_J_infinity(xii, kappainf, r_vals, q, S1, S2)
    print "Evolution infinity --> rf=%.0f" % rf
    print "\tJ=%.3f" % Jf[-1]

    print " *Hybrid evolution*"
    print "Prec.Av. infinity --> rt=%.0f & Orb.Av. rt=%.0f --> rf=%.0f" % (
        rt, rt, rf)
    t1f, t2f, dpf = precession.hybrid(xii, kappainf, r_vals, q, S1, S2, rt)
    print "\t(theta1,theta2,deltaphi)=(%.3f,%.3f,%.3f)" % (t1f[-1], t2f[-1],
                                                           dpf[-1])

    print " *Properties of the BH remnant*"
    Mfin = precession.finalmass(t1f[-1], t2f[-1], dpf[-1], q, S1, S2)
    print "\tM_f=%.3f" % Mfin
    chifin = precession.finalspin(t1f[-1], t2f[-1], dpf[-1], q, S1, S2)
    print "\tchi_f=%.3f, S_f=%.3f" % (chifin, chifin * Mfin**2)
    vkick = precession.finalkick(t1f[-1], t2f[-1], dpf[-1], q, S1, S2)
    print "\tvkick=%.5f" % (vkick)  # Geometrical units c=1