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
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
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"
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"
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
def test_rand_phi(num_sample=10000, nbins=20, tolerance=1e-3, seed="Jean", plot=False, save=True): """Test that phi is sampled as flat from zero to pi Arguments: - num_sample: number of random phi 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) phi_array = np.zeros(num_sample) for i in range(0, len(phi_array)): phi_array[i] = kicks.rand_phi() #do a histogram #TODO: use numpy histogram, to avoid plotting if its not neccesary vals_phi, bins_phi = np.histogram(phi_array, bins=np.linspace(0, 2 * np.pi, nbins)) prob_test = np.zeros(len(vals_phi)) for k in range(0, len(vals_phi)): prob_test[k] = (1 / (2 * np.pi)) * (bins_phi[k + 1] - bins_phi[k]) 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_phi[j]) if plot: plt.hist(phi_array, bins=np.linspace(0, 2 * np.pi, nbins), alpha=0.5, label="function output") plt.hist(test_array, bins=np.linspace(0, 2 * np.pi, nbins), alpha=0.5, label="expected value") plt.title("phi distribution") plt.xlabel("phi value") plt.ylabel("distribution") plt.legend(loc='upper right') plt.show() plt.close() if save: plt.hist(phi_array, bins=np.linspace(0, 2 * np.pi, nbins), alpha=0.5, label="function output") plt.hist(test_array, bins=np.linspace(0, 2 * np.pi, nbins), alpha=0.5, label="expected value") plt.title("phi distribution") plt.xlabel("phi value") plt.ylabel("distribution") plt.legend(loc='upper right') plt.savefig("phi_distribution.png") plt.close() #check if the probability computed for each bin is within the tolerance success = True tolerance = max(vals_phi) * tolerance for k in range(0, len(vals_phi)): prob_hist = vals_phi[k] / (sum(vals_phi)) if abs(prob_test[k] - prob_hist) > tolerance: success = False break #re-seed the random number generator rd.seed() return success