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
Example #2
0
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
Example #5
0
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
Example #7
0
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 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