Пример #1
0
def testing_inverse_kick(Ai=133,
                         M1=5.5,
                         M2=55,
                         Mns=1.4,
                         test_sigma=1000,
                         num_sample=100,
                         seed="Tamlin",
                         tolerance=1e-4):
    """Test for the post_explosions_params_general function that kicks
    a circular system with mass loss, then reverses that with mass 
    gain back into a circular orbit. There are four different possible
    ways to reverse the kick that are dependent on the true anomaly 
    and theta. 1) the inital kick sends the masses into an eccentric
    orbit in the same initial direction, with a true anomaly between
    0 and pi. 2) the inital kick sends the masses into an eccentric
    orbit in the same initial direction, with a true anomaly between
    pi and 2pi. 3)the inital kick sends the masses into an eccentric
    orbit in the opposit direction, with a true anomaly between
    0 and pi. 4) the inital kick sends the masses into an eccentric
    orbit in the opposit direction, with a true anomaly between
    pi and 2pi.
        
    Arguments:
    - Ai: the initial semi-major axis of the system
    - M1: solar mass of the first mass pre-explosion
    - M2: solar mass of the second mass
    - Mns: solar mass of the first mass post-explosion
    - test_sigma: a sample sigma for the rand_velocity function
    - num_sample: number of points sampled
    - seed: the seed used for the random number generator
    - tolerance: tolerance for the test
    Returns: True or False as to whether the test was successful
    """
    rd.seed(seed)

    for i in range(num_sample):
        theta = kicks.rand_theta()
        V_kick = kicks.rand_velocity(test_sigma)

        semi_major_i, e_i, boulean_i = kicks.post_explosion_params_general(
            Ai, M1, M2, Mns, 0, theta, 0, V_kick, 0)
        k = semi_major_i * (1 - e_i**2) / (e_i * Ai) - 1 / e_i

        true_anomaly = np.arccos(k)

        semi_major_f, e_f, boulean_f = kicks.post_explosion_params_general(
            semi_major_i, Mns, M2, M1, e_i, np.pi - theta, np.pi, V_kick,
            true_anomaly)

        Worked = True

        if e_f > tolerance:
            true_anomaly = 2 * np.pi - true_anomaly
            semi_major_f, e_f, boulean_f = kicks.post_explosion_params_general(
                semi_major_i, Mns, M2, M1, e_i, np.pi - theta, np.pi, V_kick,
                true_anomaly)
            if e_f > tolerance:
                semi_major_f, e_f, boulean_f = kicks.post_explosion_params_general(
                    semi_major_i, Mns, M2, M1, e_i, theta, np.pi, V_kick,
                    true_anomaly)
                if e_f > tolerance:
                    true_anomaly = 2 * np.pi - true_anomaly
                    semi_major_f, e_f, boulean_f = kicks.post_explosion_params_general(
                        semi_major_i, Mns, M2, M1, e_i, theta, np.pi, V_kick,
                        true_anomaly)
                    if e_f > tolerance:
                        Worked = False

    rd.seed()

    return Worked
Пример #2
0
def testing_momentum_full_eccentric(Ai=133,
                                    M1=5.5,
                                    M2=55,
                                    Mns=1.4,
                                    test_sigma=15,
                                    num_sample=100,
                                    seed="Lucien",
                                    tolerance=1e-4):
    """Test that the post_explosion_params_general function produces
    a correct angular momentum against a calculated angular momentum. This 
    angular momentum is calculated by first finding the velocity of M1 pre-
    explosion, then adding to that the components of the kick to get a velocity
    in the theta, phi, and radial direction. This velocity is then changed to 
    x and y components. Next the center of mass possition and velocity are 
    calculated, and using those values the relative velocities and postion are
    calculated. From there, the angular momentum is calculated using the cross-
    product method, and adding the resulting values.
    Arguments:
    - Ai: the initial semi-major axis of the system
    - M1: solar mass of the first mass pre-explosion
    - M2: solar mass of the second mass
    - Mns: solar mass of the first mass post-explosion
    - test_sigma: a sample sigma for the rand_velocity function
    - num_sample: number of points sampled
    - seed: the seed used for the random number generator
    - tolerance: tolerance for the test
    Returns: True or False as to whether the test was successful
    """
    rd.seed(seed)
    e_samples = np.linspace(0, .99, num_sample)

    for e in e_samples:

        #establishing random parameters
        Vk = kicks.rand_velocity(test_sigma) * 1e5
        theta = kicks.rand_theta()
        phi = kicks.rand_phi()
        true_anomaly = kicks.rand_true_anomaly(e)
        separation_i = Rsun * separation_function(Ai, e, true_anomaly)

        #getting values from the post_explosion_params_general function
        semi_major_f, e_f, boolean = kicks.post_explosion_params_general(
            Ai, M1, M2, Mns, e, theta, phi, Vk * 1e-5, true_anomaly)

        #calculating the momentum using the results from the function
        Momentum_function = angular_momentum(semi_major_f, Mns, M2, e_f)

        V_theta_i = np.sqrt(cgrav * (M1 + M2) * Msun * Rsun * Ai *
                            (1 - e**2)) / separation_i
        V_radius_i = np.sqrt(cgrav * (M1 + M2) * Msun *
                             (2 / separation_i - 1 / (Rsun * Ai) - Ai * Rsun *
                              (1 - e**2) / (separation_i**2)))

        V_radius = V_radius_i + Vk * np.sin(theta) * np.cos(phi)
        V_theta = V_theta_i + Vk * np.cos(theta)
        V_phi = Vk * np.sin(theta) * np.sin(phi)

        V1x = V_radius
        V1y = np.sqrt(V_theta**2 + V_phi**2)

        R_cm = Mns * separation_i / (Mns + M2)  #x direction
        V_cm_x = Mns * V1x / (Mns + M2)  #x dirrection
        V_cm_y = Mns * V1y / (Mns + M2)  #y dirrection

        Vx1_prime = V1x - V_cm_x
        Vy1_prime = V1y - V_cm_y

        Rx1_prime = separation_i - R_cm  #+x direction
        Ry1_prime = 0

        Vx2_prime = -V_cm_x
        Vy2_prime = -V_cm_y

        Rx2_prime = 0 - R_cm  #-x direction
        Ry2_prime = 0

        momentum1x = Vx1_prime * Mns * Msun
        momentum1y = Vy1_prime * Mns * Msun

        momentum2x = Vx2_prime * M2 * Msun
        momentum2y = Vy2_prime * M2 * Msun

        angular1 = Rx1_prime * momentum1y - Ry1_prime * momentum1x  #z direction
        angular2 = Rx2_prime * momentum2y - Ry2_prime * momentum2x  #z direction

        Momentum_calculated = (angular1 + angular2)

        if abs(Momentum_function -
               Momentum_calculated) / Momentum_function > tolerance:
            print(Vk, theta, phi, true_anomaly, Momentum_calculated,
                  Momentum_function, e)
            return False

    rd.seed()

    return True
Пример #3
0
def testing_eccentric_function_momentum(Ai=133,
                                        M1=5.5,
                                        M2=55,
                                        Mns=1.4,
                                        test_sigma=100,
                                        num_sample=10000,
                                        seed="Clara",
                                        tolerance=1e-3):
    """Test that the post_explosion_params_general function produces
    a correct angular momentum against a calculated angular momentum using an 
    eccentricityof zero. This angular momentum is calculated by first finding 
    the anglar velocity, and the individual relative velocities in the center 
    of mass frame pre-explosion. The components of the kick velocity were then 
    added to the velocity of mass 1, which is the super nova mass. The 
    separation in the final center of mass frame accounting for the loss of 
    mass in mass 1 is crossed with the velocities to get the components of 
    angular momentum. The total angular momentum is calculated by taking the 
    absolute value of these components. 
    Arguments:
        - Ai: the initial semi-major axis of the system
        - M1: solar mass of the first mass pre-explosion
        - M2: solar mass of the second mass
        - Mns: solar mass of the first mass post-explosion
        - test_sigma: a sample sigma for the rand_velocity function
        - num_sample: number of points sampled
        - seed: the seed used for the random number generator
        - tolerance: tolerance for the test
    Returns: True or False as to whether the test was successful
    """
    rd.seed(seed)

    for i in range(num_sample):
        #establishing random parameters
        Vk = kicks.rand_velocity(test_sigma) * 1e5
        theta = kicks.rand_theta()
        true_anomaly = kicks.rand_true_anomaly(0)
        phi = kicks.rand_phi()

        #getting values from the post_explosion_params_general function
        semi_major, e, boolean = kicks.post_explosion_params_general(
            Ai, M1, M2, Mns, 0, theta, phi, Vk, true_anomaly)

        #calculating the momentum using the results from the function
        Momentum_function = angular_momentum(semi_major, Mns, M2, e)

        #Calculating the momentum without using the results of the function

        #establishing angular velocity
        omega = np.sqrt(cgrav * Msun * (M1 + M2) / (Ai * Rsun)**3)  #rad/second

        #velocities of the masses before the kick
        V1_initial = M2 / (M1 + M2) * omega * Ai * Rsun  #cm/second
        V2 = M1 / (M1 + M2) * omega * Ai * Rsun  #cm/second,-y direction

        #velocities after the kick, V2 is unaffected by the kick
        V1x_final = Vk * 1e5 * np.sin(phi) * np.cos(theta)
        V1y_final = V1_initial + Vk * 1e5 * np.cos(theta)
        V1z_final = Vk * 1e5 * np.sin(phi) * np.sin(theta)

        #separations from the center of mass in the center of mass frame post-explosion
        R2 = Ai * Rsun * Mns / (Mns + M2)  #cm
        R1 = Ai * Rsun - R2  #cm

        #calculating the components of the angular momentum using the cross product
        Momentum_1y = -R1 * V1z_final * Mns * Msun
        Momentum_1z = R1 * V1y_final * Mns * Msun
        Momentum_2 = R2 * V2 * M2 * Msun  #z direction

        #absolute value of the components of the angular momentum
        Momentum_calculated = np.sqrt(Momentum_1y**2 + Momentum_1z**2 +
                                      Momentum_2**2)

        #checking that the two momentums are relatively equal
        if abs(Momentum_function -
               Momentum_calculated) / Momentum_function > tolerance:
            print(Vk, theta, phi, true_anomaly, Momentum_calculated,
                  Momentum_function, i)
            return False

    rd.seed()

    return True
Пример #4
0
def testing_eccentric_function_graph(test_sigma=100,
                                     test_M1=5.5,
                                     test_M2=55,
                                     test_Ai=133,
                                     test_Mns=1.4,
                                     seed="David Berne",
                                     sample_velocity=100,
                                     npoints=10000,
                                     plot=True,
                                     save=False):
    """Test that the graph of the eccentricity vs the period looks correct
    Arguments:
        - test_sigma: a sample sigma for the rand_velocity function
        - test_M1: solar mass of the first mass pre-explosion
        - test_M2: solar mass of the second mass
        - test_Ai: the initial semi-major axis of the system
        - test_Mns: solar mass of the first mass post-explosion
        - seed: the seed used for the random number generator
        - sample_velocity: a constant velocity over which a line is
            drawn on the graph
        - npoints: number of points sampled
        - plot: if true, plot results
        - save: if true, saves the plot
    Returns: 'Compare graph to paper'
    """
    rd.seed(seed)
    testing_function = np.zeros([npoints, 2])
    constant_velocity = np.zeros([npoints, 2])

    for i in range(len(testing_function)):
        semi_major, e, boolean = kicks.post_explosion_params_general(test_Ai,\
        test_M1, test_M2, test_Mns, 0, kicks.rand_theta(), kicks.rand_phi(),\
        kicks.rand_velocity(test_sigma),kicks.rand_true_anomaly(0))
        if semi_major > 0:
            testing_function[i][0] = semi_major
            testing_function[i][1] = e

    theta = np.linspace(0, 3.14, npoints)
    velocity = np.linspace(0, 400, npoints)

    for j in range(len(constant_velocity)):
        semi_major, e, boolean = kicks.post_explosion_params_general(
            test_Ai, test_M1, test_M2, test_Mns, 0, theta[j], 0,
            sample_velocity, 0)
        if semi_major > 0:
            constant_velocity[j][0] = semi_major
            constant_velocity[j][1] = e
    """changing the semi-major axis to period values in days"""

    for k in range(len(testing_function)):
        testing_function[k][0] = keplers_third_law(testing_function[k][0],
                                                   test_M2, test_Mns)
        constant_velocity[k][0] = keplers_third_law(constant_velocity[k][0],
                                                    test_M2, test_Mns)

    if plot:
        plt.plot(testing_function[:, 0], testing_function[:, 1], "o")
        plt.xlim(0, 50)
        plt.ylim(0, 1)
        plt.plot(constant_velocity[:, 0], constant_velocity[:, 1], 'k-')
        plt.title("post-explosion results")
        plt.xlabel("Period in days")
        plt.ylabel("Eccentricity")
        plt.show()
        plt.close()
    if save:
        plt.plot(testing_function[:, 0], testing_function[:, 1], "o")
        plt.xlim(0, 50)
        plt.ylim(0, 1)
        plt.plot(constant_velocity[:, 0], constant_velocity[:, 1], 'k-')
        plt.title("post-explosion results")
        plt.xlabel("Period in days")
        plt.ylabel("Eccentricity")
        plt.savefig("post_explosion_circular_graph.png")
        plt.close()

    rd.seed()

    return "True"
Пример #5
0
def testing_circular_function_graph(test_sigma=100,
                                    test_m1=5.5,
                                    test_m2=55,
                                    test_ai=133,
                                    test_m1f=1.4,
                                    seed="Flay",
                                    sample_velocity=100,
                                    npoints=10000,
                                    plot=False,
                                    save=True):
    """Test that the graph of the eccentricity vs the period looks correct
    Arguments:
        - test_sigma: a sample sigma for the rand_velocity function in km/s
        - test_m1: mass of the pre-explosion star in Msun
        - test_m2: smass of the companion in Msun
        - test_ai: the initial semi-major axis of the system
            pre-explosion in Rsun
        - test_m1f: post explosion mass of the exploding star in Msun
        - seed: the seed used for the random number generator
        - sample_velocity: a constant velocity over which a line is
            drawn on the graph
        - npoints: number of points sampled
        - plot: if true, plot results
        - save: if true, saves the plot
    Returns: 'Compare graph to paper'
    """
    rd.seed(seed)
    testing_function = np.zeros([npoints, 2])
    constant_velocity = np.zeros([npoints, 2])

    for i in range(len(testing_function)):
        semi_major, e, angle, boolean = kicks.post_explosion_params_circular(
            test_ai, test_m1, test_m2, test_m1f, kicks.rand_theta(),
            kicks.rand_phi(), kicks.rand_velocity(test_sigma))
        if semi_major > 0:
            testing_function[i][0] = semi_major
            testing_function[i][1] = e

    theta = np.linspace(0, 3.14, npoints)
    velocity = np.linspace(0, 400, npoints)

    for j in range(len(constant_velocity)):
        semi_major, e, angle, boolean = kicks.post_explosion_params_circular(
            test_ai, test_m1, test_m2, test_m1f, theta[j], 0, sample_velocity)
        if semi_major > 0:
            constant_velocity[j][0] = semi_major
            constant_velocity[j][1] = e
    """changing the semi-major axis to period values in days"""

    for k in range(len(testing_function)):
        testing_function[k][0] = kepler3_P(testing_function[k][0], test_m2,
                                           test_m1f)
        constant_velocity[k][0] = kepler3_P(constant_velocity[k][0], test_m2,
                                            test_m1f)

    if plot:
        plt.plot(testing_function[:, 0], testing_function[:, 1], "o")
        plt.xlim(0, 50)
        plt.ylim(0, 1)
        plt.plot(constant_velocity[:, 0], constant_velocity[:, 1], 'k-')
        plt.title("post-explosion results")
        plt.xlabel("Period in days")
        plt.ylabel("Eccentricity")
        plt.show()
        plt.close()
    if save:
        plt.plot(testing_function[:, 0], testing_function[:, 1], "o")
        plt.xlim(0, 50)
        plt.ylim(0, 1)
        plt.plot(constant_velocity[:, 0], constant_velocity[:, 1], 'k-')
        plt.title("post-explosion results")
        plt.xlabel("Period in days")
        plt.ylabel("Eccentricity")
        plt.savefig("post_explosion_circular_graph.png")
        plt.close()

    rd.seed()

    return "True"
Пример #6
0
def testing_circular_function_momentum(ai=133,
                                       m1=5.5,
                                       m2=55,
                                       m1f=1.4,
                                       test_sigma=100,
                                       num_sample=1000,
                                       seed="Lela",
                                       tolerance=1e-3):
    """Test that the post_explosion_params_circular function produces
    a correct angular momentum against a calculated angular momentum. This 
    angular momentum is calculated by first finding the anglar velocity, and 
    the individual relative velocities in the center of mass frame pre-
    explosion. The components of the kick velocity were then added to the 
    velocity of mass 1, which is the super nova mass. The separation in the 
    final center of mass frame accounting for the loss of mass of mass 1 is 
    crossed with the velocities to get the components of angular momentum. The 
    total angular momentum is calculated by taking the absolute value of these 
    components. 
    Arguments:
        - ai: the initial semi-major axis of the system
            pre-explosion in Rsun
        - m1: mass of the pre-explosion star in Msun
        - m2: smass of the companion in Msun
        - m1f: post explosion mass of the exploding star in Msun
        - test_sigma: a sample sigma for the rand_velocity function in km/s
        - num_sample: number of points sampled
        - seed: the seed used for the random number generator
        - tolerance: tolerance for the test
    Returns: True or False as to whether the test was successful
    """
    rd.seed(seed)

    for i in range(num_sample):
        #establishing random parameters
        Vk = kicks.rand_velocity(test_sigma) * 1e5
        theta = kicks.rand_theta()
        phi = kicks.rand_phi()

        #getting values from the post_explosion_params_circular function
        semi_major, e, angle, boolean = kicks.post_explosion_params_circular(
            ai, m1, m2, m1f, theta, phi, Vk)

        #calculating the momentum using the results from the function
        Momentum_function = orbital_angular_momentum(semi_major, m1f, m2, e)

        #Calculating the momentum without using the results of the function

        #establishing angular velocity
        omega = np.sqrt(cgrav * Msun * (m1 + m2) / (ai * Rsun)**3)  #rad/second

        #velocities of the masses before the kick
        V1_initial = m2 / (m1 + m2) * omega * ai * Rsun  #cm/second
        V2 = m1 / (m1 + m2) * omega * ai * Rsun  #cm/second,-y direction

        #velocities after the kick, V2 is unaffected by the kick
        V1x_final = Vk * 1e5 * np.sin(phi) * np.cos(theta)
        V1y_final = V1_initial + Vk * 1e5 * np.cos(theta)
        V1z_final = Vk * 1e5 * np.sin(phi) * np.sin(theta)

        #separations from the center of mass in the center of mass frame post-explosion
        R2 = ai * Rsun * m1f / (m1f + m2)  #cm
        R1 = ai * Rsun - R2  #cm

        #calculating the components of the angular momentum using the cross product
        Momentum_1y = -R1 * V1z_final * m1f * Msun
        Momentum_1z = R1 * V1y_final * m1f * Msun
        Momentum_2 = R2 * V2 * m2 * Msun  #z direction

        #absolute value of the components of the angular momentum
        Momentum_calculated = np.sqrt(Momentum_1y**2 + Momentum_1z**2 +
                                      Momentum_2**2)

        #checking that the two momentums are relatively equal
        if abs(Momentum_function -
               Momentum_calculated) / Momentum_function > tolerance:
            return False

    rd.seed()

    return True
Пример #7
0
def test_rand_theta(num_sample=10000,
                    nbins=20,
                    tolerance=1e-3,
                    seed="Jubilee",
                    plot=False,
                    save=True):
    """Test that theta is sampled as a sign graph from zero to pi
    Arguments:
        - num_sample: number of random theta generated
        - nbins: random sampled numbers will be binned to compute
            probabilities and compare to expected values. This variable
            specifies the number of bins used.
        - tolerance: tolerance for the test
        - seed: the seed used for the random number generator
        - plot: if true, plot results
        - save: if true, saves the plot
    Returns: True if the test is succesful, False otherwise
    """
    rd.seed(seed)
    theta_array = np.zeros(num_sample)
    for i in range(0, len(theta_array)):
        theta_array[i] = kicks.rand_theta()

    #do a histogram
    #TODO: use numpy histogram, to avoid plotting if its not neccesary
    vals_theta, bins_theta = np.histogram(theta_array,
                                          bins=np.linspace(0, np.pi, nbins))

    prob_test = np.zeros(len(vals_theta))

    for k in range(0, len(vals_theta)):
        prob_test[k] = -(np.cos(bins_theta[k + 1]) - np.cos(bins_theta[k])) / 2

    test_array = []

    for j in range(0, len(prob_test)):
        test_array = np.append(
            test_array,
            np.ones(int(round(prob_test[j] * num_sample))) * bins_theta[j])

    if plot:
        plt.hist(theta_array,
                 bins=np.linspace(0, np.pi, nbins),
                 alpha=0.5,
                 label="function output")
        plt.hist(test_array,
                 bins=np.linspace(0, np.pi, nbins),
                 alpha=0.5,
                 label="expected value")
        plt.title("theta distribution")
        plt.xlabel("theta value")
        plt.ylabel("distribution")
        plt.legend(loc='upper right')
        plt.show()
        plt.close()
    if save:
        plt.hist(theta_array,
                 bins=np.linspace(0, np.pi, nbins),
                 alpha=0.5,
                 label="function output")
        plt.hist(test_array,
                 bins=np.linspace(0, np.pi, nbins),
                 alpha=0.5,
                 label="expected value")
        plt.title("theta distribution")
        plt.xlabel("theta value")
        plt.ylabel("distribution")
        plt.legend(loc='upper right')
        plt.savefig("theta_distribution.png")
        plt.close()
    #check if the probability computed for each bin is within the tolerance
    success = True
    tolerance = max(vals_theta) * tolerance
    for k in range(0, len(vals_theta)):
        prob_hist = vals_theta[k] / (sum(vals_theta))
        if abs(prob_test[k] - prob_hist) > tolerance:
            success = False
            break

    #re-seed the random number generator
    rd.seed()

    return success