def modified_gradient_en_ang_attractor(y): r = np.array([y[2][0] - y[3][0], y[2][1] - y[3][1]]) #r from 1 to 0 rabs = np.sqrt(normsq(r)) grady = [] grady.append(-r * G * M1 * M2 * (rabs**(-3))) grady.append(r * G * M1 * M2 * (rabs**(-3))) grady.append(y[0] / M1) grady.append(y[1] / M2) grady = np.array(grady) n_grady = math.sqrt(supervec_norm(grady)) # an attractive term as in the naive approach, first energy energy_y = get_energy(y) energy_attracting_term = nabla_H(y) energy_attracting_term *= (ENERGY_0 - energy_y) * math.exp(ENERGY_0 - energy_y) e_att_n = np.sqrt(supervec_norm(energy_attracting_term)) # make the attracting term smaller than the initial term (1/10th at most) if e_att_n * 10 > n_grady: energy_attracting_term *= n_grady / (10 * e_att_n) # then angular momentum ang_y = get_total_angular_momentum(y) ang_attracting_term = nabla_l(y) ang_attracting_term *= (TOTAL_ANG_MOMENTUM_0 - ang_y) * math.exp(TOTAL_ANG_MOMENTUM_0 - ang_y) ang_att_n = np.sqrt(supervec_norm(energy_attracting_term)) # make the attracting term smaller if it's too big if ang_att_n * 10 > n_grady: ang_attracting_term *= n_grady / (10 * e_att_n) return grady + energy_attracting_term + ang_attracting_term
def nabla_H(y): r = np.array([y[2][0] - y[3][0], y[2][1] - y[3][1]]) # r from 1 to 0 rabs = np.sqrt(normsq(r)) nabla_h = [] nabla_h.append(y[0] / M1) nabla_h.append(y[1] / M2) nabla_h.append(r * G * M1 * M2 * (rabs**(-3))) nabla_h.append(-r * G * M1 * M2 * (rabs**(-3))) return np.array(nabla_h)
def nabla_q(q): # assume 2bp # takes q returns it's gradient, which is negative the derivative of p r = np.array([q[0][0] - q[1][0], q[0][1] - q[1][1]]) #r from 1 to 0 rabs = np.sqrt(normsq(r)) nablaq = [] nablaq.append(-r * G * M1 * M2 * (rabs**(-3))) # vector nablaq.append(r * G * M1 * M2 * (rabs**(-3))) return nablaq
def gradient(y): # assume 2 body problem # here gradient is a bit of misnomer, it's the J^{-1}\nabla H that I label grad y r = np.array([y[2][0] - y[3][0], y[2][1] - y[3][1]]) #r from 1 to 0 rabs = np.sqrt(normsq(r)) grady = [] grady.append(-r * G * M1 * M2 * (rabs**(-3))) grady.append(r * G * M1 * M2 * (rabs**(-3))) grady.append(y[0] / M1) grady.append(y[1] / M2) return np.array(grady)
def modified_gradient_energy_attractor(y): r = np.array([y[2][0] - y[3][0], y[2][1] - y[3][1]]) #r from 1 to 0 rabs = np.sqrt(normsq(r)) grady = [] grady.append(-r * G * M1 * M2 * (rabs**(-3))) grady.append(r * G * M1 * M2 * (rabs**(-3))) grady.append(y[0] / M1) grady.append(y[1] / M2) grady = np.array(grady) # an attracive term is added along nabla H energy_y = get_energy(y) attracting_term = nabla_H(y) # attracting_term = attracting_term / supervec_norm(attracting_term) attracting_term *= (ENERGY_0 - energy_y) * math.exp(ENERGY_0 - energy_y) / 5 return grady + attracting_term
def update_dta(y,first_int_nablas=[(nabla_H,"energy"), (nabla_l,"angular_m"), (nabla_lin_x,"linear_x"), (nabla_lin_y,"linear_y")]): global position_arr,energy_arr,ang_momentum_arr,linear_momentum_arr,time_arr,radius_arr # update time_arr.append(time) position_arr.append(y[2:])# update the position array velocity_arr.append(np.array([y[0]/M1 , y[1]/M2])) energy_arr.append(get_energy(y)) ang_momentum_arr.append(get_total_angular_momentum(y)) linear_momentum_arr.append(get_total_linear_momentum_abs(y)) net_lin_mom_x_arr.append(get_lin_mom_x(y)) net_lin_mom_y_arr.append(get_lin_mom_y(y)) update_lev_set_uvec(y,first_int_nablas) k_factor_arr.append(k_factor(y)) r = np.array([y[2][0]-y[3][0] , y[2][1]-y[3][1]])#r from 1 to 0 rabs = np.sqrt(normsq(r)) radius_arr.append(rabs)