def velocity_in_plane(times,parameters,component='primary',coordinate_frame='polar'): """ Calculate the velocity in the orbital plane. @param times: times of observations (days) @type times: array @param parameters: list of parameters (P,e,a,T0) @type parameters: list @param component: component to calculate the orbit of. If it's the secondary, the angles will be shifted by 180 degrees @type component: string, one of 'primary' or 'secondary' @param coordinate_frame: type of coordinates @type coordinate_frame: str, ('polar' or 'cartesian') @return: coord1,coord2 @rtype: 2xarray """ #-- calculate the orbit in the plane r,theta = orbit_in_plane(times,parameters,component=component,coordinate_frame='polar') P,e,a,T0 = parameters P = conversions.convert('d','s',P) a = conversions.convert('au','m',a) #-- compute rdot and thetadot l = r*(1+e*np.cos(theta)) L = 2*np.pi*a**2/P*np.sqrt(1-e**2) rdot = L/l*e*np.sin(theta) thetadot = L/r**2 #-- convert to the right coordinate frame if coordinate_frame=='polar': return rdot,thetadot elif coordinate_frame=='cartesian': vx,vy,vz = vectors.spher2cart((r,theta,np.pi/2.),(rdot,r*thetadot,0)) return vx,vy
def surface_normals(r,phi,theta,grid,gtype='spher'): """ Numerically compute surface normals of a grid (in absence of analytical alternative). Also computes the surface elements, making L{surface_elements} obsolete. """ if gtype=='spher': raise NotImplementedError elif gtype=='delaunay': raise NotImplementedError elif gtype=='triangular': #-- compute the angle between the surface normal and the radius vector x,y,z = vectors.spher2cart_coord(r,phi,theta) centers = np.zeros((len(grid.convex_hull),3)) normals = np.zeros((len(grid.convex_hull),3)) sizes = np.zeros(len(grid.convex_hull)) #vertx,verty,vertz = points.T #-- compute centers,normals and sizes for i,indices in enumerate(grid.convex_hull): #-- center is triangle's barycenter centers[i] = [x[indices].sum()/3,y[indices].sum()/3,z[indices].sum()/3] #-- size is size of triangle a = sqrt((x[indices[0]]-x[indices[1]])**2 + (y[indices[0]]-y[indices[1]])**2 + (z[indices[0]]-z[indices[1]])**2) b = sqrt((x[indices[0]]-x[indices[2]])**2 + (y[indices[0]]-y[indices[2]])**2 + (z[indices[0]]-z[indices[2]])**2) c = sqrt((x[indices[1]]-x[indices[2]])**2 + (y[indices[1]]-y[indices[2]])**2 + (z[indices[1]]-z[indices[2]])**2) s = 0.5*(a+b+c) sizes[i] = sqrt( s*(s-a)*(s-b)*(s-c)) #-- normal is cross product of two sides side1 = [x[indices[1]]-x[indices[0]],y[indices[1]]-y[indices[0]],z[indices[1]]-z[indices[0]]] side2 = [x[indices[2]]-x[indices[0]],y[indices[2]]-y[indices[0]],z[indices[2]]-z[indices[0]]] normals[i] = np.cross(side1,side2) #-- make sure the normal is pointed outwards normal_r,normal_phi,normal_theta = vectors.cart2spher(centers.T,normals.T) normal_r = np.abs(normal_r) centers_sph = vectors.cart2spher_coord(*centers.T) normals = np.array(vectors.spher2cart(centers_sph,(normal_r,normal_phi,normal_theta))) #-- normalise and compute angles normals_T = normals.T normals = normals_T / vectors.norm(normals_T) #cos_gamma = vectors.cos_angle(a,normals) print centers.shape,sizes.shape,normals.shape return centers, sizes, normals#, cos_gamma
def fastrot_roche_surface_gravity(r, theta, phi, r_pole, omega, M, norm=False): """ Calculate components of the local surface gravity of the fast rotating Roche model. Input units are solar units. Output units are SI. Omega is fraction of critical velocity. See Cranmer & Owocki, Apj (1995) @param r: radius of the surface element to calculate the surface gravity @type r: float/ndarray @param theta: colatitude of surface element @type theta: float/ndarray @param phi: longitude of surface element @type phi: float/ndarray @param r_pole: polar radius of model @type r_pole: float @param omega: fraction of critical rotation velocity @type omega: float @param M: mass of the star @type M: float @param norm: compute magnitude of surface gravity (True) or vector (False) @type norm: boolean @return: surface gravity magnitude or vector @rtype: 3Xfloat/3Xndarray """ GG = constants.GG_sol #-- calculate r-component of local gravity x = r / r_pole grav_r = GG * M / r_pole**2 * (-1. / x**2 + 8. / 27. * x * omega**2 * sin(theta)**2) #-- calculate theta-component of local gravity grav_th = GG * M / r_pole**2 * (8. / 27. * x * omega**2 * sin(theta) * cos(theta)) grav = np.array([grav_r, grav_th]) #-- now we transform to spherical coordinates grav = np.array(vectors.spher2cart((r, phi, theta), (grav[0], 0., grav[1]))) grav = grav * constants.Rsol if norm: return vectors.norm(grav) else: return grav
def fastrot_roche_surface_gravity(r,theta,phi,r_pole,omega,M,norm=False): """ Calculate components of the local surface gravity of the fast rotating Roche model. Input units are solar units. Output units are SI. Omega is fraction of critical velocity. See Cranmer & Owocki, Apj (1995) @param r: radius of the surface element to calculate the surface gravity @type r: float/ndarray @param theta: colatitude of surface element @type theta: float/ndarray @param phi: longitude of surface element @type phi: float/ndarray @param r_pole: polar radius of model @type r_pole: float @param omega: fraction of critical rotation velocity @type omega: float @param M: mass of the star @type M: float @param norm: compute magnitude of surface gravity (True) or vector (False) @type norm: boolean @return: surface gravity magnitude or vector @rtype: 3Xfloat/3Xndarray """ GG = constants.GG_sol #-- calculate r-component of local gravity x = r/r_pole grav_r = GG*M/r_pole**2 * (-1./x**2 + 8./27.*x*omega**2*sin(theta)**2) #-- calculate theta-component of local gravity grav_th = GG*M/r_pole**2 * (8./27.*x*omega**2*sin(theta)*cos(theta)) grav = np.array([grav_r,grav_th]) #-- now we transform to spherical coordinates grav = np.array(vectors.spher2cart( (r,phi,theta),(grav[0],0.,grav[1]) )) grav = grav*constants.Rsol if norm: return vectors.norm(grav) else: return grav
def velocity_in_plane(times, parameters, component='primary', coordinate_frame='polar'): """ Calculate the velocity in the orbital plane. @param times: times of observations (days) @type times: array @param parameters: list of parameters (P,e,a,T0) @type parameters: list @param component: component to calculate the orbit of. If it's the secondary, the angles will be shifted by 180 degrees @type component: string, one of 'primary' or 'secondary' @param coordinate_frame: type of coordinates @type coordinate_frame: str, ('polar' or 'cartesian') @return: coord1,coord2 @rtype: 2xarray """ #-- calculate the orbit in the plane r, theta = orbit_in_plane(times, parameters, component=component, coordinate_frame='polar') P, e, a, T0 = parameters P = conversions.convert('d', 's', P) a = conversions.convert('au', 'm', a) #-- compute rdot and thetadot l = r * (1 + e * np.cos(theta)) L = 2 * np.pi * a**2 / P * np.sqrt(1 - e**2) rdot = L / l * e * np.sin(theta) thetadot = L / r**2 #-- convert to the right coordinate frame if coordinate_frame == 'polar': return rdot, thetadot elif coordinate_frame == 'cartesian': vx, vy, vz = vectors.spher2cart((r, theta, np.pi / 2.), (rdot, r * thetadot, 0)) return vx, vy
def diffrot_roche_surface_gravity(r,theta,phi,r_pole,M,omega_eq,omega_pole,norm=False): """ Surface gravity from differentially rotation Roche potential. Magnitude is OK, please carefully check direction. @param r: radius of the surface element to calculate the surface gravity @type r: float/ndarray @param theta: colatitude of surface element @type theta: float/ndarray @param phi: longitude of surface element @type phi: float/ndarray @param r_pole: polar radius of model @type r_pole: float @param M: mass of the star @type M: float @param omega_eq: fraction of critical rotation velocity at equator @type omega_eq: float @param omega_pole: fraction of critical rotation velocity at pole @type omega_pole: float @param norm: compute magnitude of surface gravity (True) or vector (False) @type norm: boolean @return: surface gravity magnitude or vector @rtype: 3Xfloat/3Xndarray """ GG = constants.GG_sol Omega_crit = sqrt(8*GG*M/ (27*r_pole**3)) omega_eq = omega_eq*Omega_crit omega_pole = omega_pole*Omega_crit x = omega_eq / omega_pole #-- find R_equator solving a cubic equation: a = omega_eq**2/(GG*M) X = (x**2+x+1)/(6*x**2) b,c = -1./(a*X*r_pole), +1./(a*X) m,k = 27*c+0*1j,-3*b+0*1j n = m**2-4*k**3 + 0*1j om1 = -0.5 + 0.5*sqrt(3)*1j om2 = -0.5 - 0.5*sqrt(3)*1j c1 = (0.5*(m+sqrt(n)))**(1./3.) c2 = (0.5*(m-sqrt(n)))**(1./3.) x1 = -1./3. * ( c1 + c2 ) x2 = -1./3. * ( om2*c1 + om1*c2 ) x3 = -1./3. * ( om1*c1 + om2*c2 ) re = x2.real # ratio of centrifugal to gravitational force at the equator f = re**3 * omega_eq**2 / (GG*M) # ratio Re/Rp rat = 1 + (f*(x**2+x+1))/(6.*x**2) # some coefficients for easy evaluation alpha = f*(x-1)**2/(6*x**2)*(1/rat)**7 beta = f*(x-1) /(2*x**2)*(1/rat)**5 gamma = f /(2*x**2)*(1/rat)**3 # implicit equation for the surface sinth = sin(theta) y = r/r_pole grav_th = (6*alpha*y**7*sinth**5 + 4*beta*y**5*sinth**3 + 2*gamma*y**3*sinth)*cos(theta) grav_r = 7*alpha/r_pole*y**6*sinth**6 + 5*beta/r_pole*y**4*sinth**4 + 3*gamma/r_pole*y**2*sinth**2 - 1./r_pole fr = 6*alpha*y**7*sinth**4 + 4*beta*y**5*sinth**2 + 2*gamma*y**3 magn = GG*M/r**2 * sqrt(cos(theta)**2 + (1-fr)**2 *sin(theta)**2) magn_fake = np.sqrt(grav_r**2+(grav_th/r)**2) grav_r,grav_th = grav_r/magn_fake*magn,(grav_th/r)/magn_fake*magn grav = np.array([grav_r*constants.Rsol,grav_th*constants.Rsol]) #-- now we transform to spherical coordinates grav = vectors.spher2cart( (r,phi,theta),(grav[0],0.,grav[1]) ) if norm: return vectors.norm(grav) else: return grav
def surface_normals(r, phi, theta, grid, gtype='spher'): """ Numerically compute surface normals of a grid (in absence of analytical alternative). Also computes the surface elements, making L{surface_elements} obsolete. """ if gtype == 'spher': raise NotImplementedError elif gtype == 'delaunay': raise NotImplementedError elif gtype == 'triangular': #-- compute the angle between the surface normal and the radius vector x, y, z = vectors.spher2cart_coord(r, phi, theta) centers = np.zeros((len(grid.convex_hull), 3)) normals = np.zeros((len(grid.convex_hull), 3)) sizes = np.zeros(len(grid.convex_hull)) #vertx,verty,vertz = points.T #-- compute centers,normals and sizes for i, indices in enumerate(grid.convex_hull): #-- center is triangle's barycenter centers[i] = [ x[indices].sum() / 3, y[indices].sum() / 3, z[indices].sum() / 3 ] #-- size is size of triangle a = sqrt((x[indices[0]] - x[indices[1]])**2 + (y[indices[0]] - y[indices[1]])**2 + (z[indices[0]] - z[indices[1]])**2) b = sqrt((x[indices[0]] - x[indices[2]])**2 + (y[indices[0]] - y[indices[2]])**2 + (z[indices[0]] - z[indices[2]])**2) c = sqrt((x[indices[1]] - x[indices[2]])**2 + (y[indices[1]] - y[indices[2]])**2 + (z[indices[1]] - z[indices[2]])**2) s = 0.5 * (a + b + c) sizes[i] = sqrt(s * (s - a) * (s - b) * (s - c)) #-- normal is cross product of two sides side1 = [ x[indices[1]] - x[indices[0]], y[indices[1]] - y[indices[0]], z[indices[1]] - z[indices[0]] ] side2 = [ x[indices[2]] - x[indices[0]], y[indices[2]] - y[indices[0]], z[indices[2]] - z[indices[0]] ] normals[i] = np.cross(side1, side2) #-- make sure the normal is pointed outwards normal_r, normal_phi, normal_theta = vectors.cart2spher( centers.T, normals.T) normal_r = np.abs(normal_r) centers_sph = vectors.cart2spher_coord(*centers.T) normals = np.array( vectors.spher2cart(centers_sph, (normal_r, normal_phi, normal_theta))) #-- normalise and compute angles normals_T = normals.T normals = normals_T / vectors.norm(normals_T) #cos_gamma = vectors.cos_angle(a,normals) print(centers.shape, sizes.shape, normals.shape) return centers, sizes, normals #, cos_gamma