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 projected_intensity(teff,gravity,areas,line_of_sight,photband='OPEN.BOL'): """ Compute projected intensity in the line of sight. gravity is vector directed inwards in the star line of sight is vector. """ ones = np.ones_like(gravity[0]) losx = line_of_sight[0]*ones losy = line_of_sight[1]*ones losz = line_of_sight[2]*ones angles = vectors.angle(-gravity,np.array([losx,losy,losz])) mus = cos(angles) grav_ = vectors.norm(gravity) #-- intensity is less if we look at the limb intens = intensity(teff,grav_,mu=mus,photband=photband) #-- intensity is less if the surface element area is small (it does not need # to be projected anymore!) return intens*areas*mus,mus
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 projected_intensity(teff, gravity, areas, line_of_sight, photband='OPEN.BOL'): """ Compute projected intensity in the line of sight. gravity is vector directed inwards in the star line of sight is vector. """ ones = np.ones_like(gravity[0]) losx = line_of_sight[0] * ones losy = line_of_sight[1] * ones losz = line_of_sight[2] * ones angles = vectors.angle(-gravity, np.array([losx, losy, losz])) mus = cos(angles) grav_ = vectors.norm(gravity) #-- intensity is less if we look at the limb intens = intensity(teff, grav_, mu=mus, photband=photband) #-- intensity is less if the surface element area is small (it does not need # to be projected anymore!) return intens * areas * mus, mus
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