コード例 #1
0
ファイル: make_snapshot.py プロジェクト: ibackus/diskpy
def setup_sinks(IC, snapshot, param):
    """
    Sets up snapshot and param for stars that are sinks.
    
    Parameters
    ----------
    IC : IC obj
    snapshot : SimSnap
    param : param dict
    
    Returns
    -------
    None
    """
    units = diskpy.pychanga.units_from_param(param)
    # Set the star tforms to a negative number.  This allows UW ChaNGa treat 
    # stars as sink particles
    snapshot.star['tform'] = -1.0   
    # Set sink radius for stars
    r_sink = sink_radius(IC)
    r_sink = float(strip_units(r_sink))
    param['dSinkBoundOrbitRadius'] = r_sink
    param['dSinkRadius'] = r_sink
    # Set sink mass to be 90% of the smallest star
    Mstar = snapshot.s['mass'].min()
    Mstar.convert_units(units['m_unit'])
    param['dSinkMassMin'] = 0.9 * strip_units(Mstar)
    # Turn sinks on
    param['bDoSinks'] = 1
コード例 #2
0
ファイル: make_snapshot.py プロジェクト: philchang/diskpy
def setup_sinks(IC, snapshot, param):
    """
    Sets up snapshot and param for stars that are sinks.
    
    Parameters
    ----------
    IC : IC obj
    snapshot : SimSnap
    param : param dict
    
    Returns
    -------
    None
    """
    units = diskpy.pychanga.units_from_param(param)
    # Set the star tforms to a negative number.  This allows UW ChaNGa treat 
    # stars as sink particles
    snapshot.star['tform'] = -1.0   
    # Set sink radius for stars
    r_sink = sink_radius(IC)
    r_sink = float(strip_units(r_sink))
    param['dSinkBoundOrbitRadius'] = r_sink
    param['dSinkRadius'] = r_sink
    # Set sink mass to be 90% of the smallest star
    Mstar = snapshot.s['mass'].min()
    Mstar.convert_units(units['m_unit'])
    param['dSinkMassMin'] = 0.9 * strip_units(Mstar)
    # Turn sinks on
    param['bDoSinks'] = 1
コード例 #3
0
ファイル: AddBinary.py プロジェクト: dflemin3/diskpy
def calcCOM(m1=0.5, m2=0.5, x1=1, x2=1):
    """
    Given pynbody arrays for the mass and position of the two binary stars,
    function calculates the CoM of the two particles in order to check that
    it's still roughly 0.
    
    Deprecated

    Parameters
    ----------
    
    (as pynbody SimArrays)
    m1, m2 : SimArrays
        Primary and secondary mass arrays (in Msol)
    x1, x2 : SimArrays
        Primary and secondary position arrays (in AU)

    Returns
    -------
    center of mass: array
        Center of mass position vector (numpy array in AU)
    """

    # Strip units from inputs
    x1 = np.asarray(strip_units(x1))
    x2 = np.asarray(strip_units(x2))
    m1 = np.asarray(strip_units(m1))
    m2 = np.asarray(strip_units(m2))

    # Compute,return CoM
    return (1.0 / (m1 + m2)) * ((m1 * x1) + (m2 * x2))
コード例 #4
0
def calcCOM(m1=0.5, m2=0.5, x1=1, x2=1):
    """
    Given pynbody arrays for the mass and position of the two binary stars,
    function calculates the CoM of the two particles in order to check that
    it's still roughly 0.
    
    Deprecated

    Parameters
    ----------
    
    (as pynbody SimArrays)
    m1, m2 : SimArrays
        Primary and secondary mass arrays (in Msol)
    x1, x2 : SimArrays
        Primary and secondary position arrays (in AU)

    Returns
    -------
    center of mass: array
        Center of mass position vector (numpy array in AU)
    """

    # Strip units from inputs
    x1 = np.asarray(strip_units(x1))
    x2 = np.asarray(strip_units(x2))
    m1 = np.asarray(strip_units(m1))
    m2 = np.asarray(strip_units(m2))

    # Compute,return CoM
    return (1.0 / (m1 + m2)) * ((m1 * x1) + (m2 * x2))
コード例 #5
0
def setup(IC, R):
    """
    Initialize values for solving vertical hydrostatic equlibrium.
    
    Parameters
    ----------
    
    IC : IC object
        Initial conditions object
    R : SimArray
        Radius at which to solve hydrostatic equilibrium
    
    Returns
    -------
    
    z : array
        Dimensionless z bins, in units of h
    r : float
        Radius in units of h
    c : float
        Constant in residual equation
    zscale : SimArray
        Amount to scale z (all lengths) by to get dimensions back.
        ie, Z(actual) = z*zscale
    rhoscale : SimArray
        Scale for dimensionless rho
    """

    # Load everything from IC
    sigma = IC.sigma(R)
    T = IC.T(R)
    M = IC.settings.physical.M
    m = IC.settings.physical.m
    zmax = IC.settings.rho_calc.zmax
    nz = IC.settings.rho_calc.nz

    # Set-up constants
    a = G * M * m / (kB * T)
    b = 2 * np.pi * G * m / (kB * T)
    ha = np.sqrt(R * R * R / a).in_units('au')
    c = b * ha * sigma
    c.convert_units('1')
    h = estHeight(sigma, T, M, m, R)
    zscale = h
    rhoscale = sigma / h

    # Set-up z bins
    if zmax is None:

        zmax = 6 * h

    zmax = strip_units((zmax / h).in_units('1'))
    z = np.linspace(0, zmax, nz)

    # Make everything dimensionless
    r = strip_units((R / h).in_units('1'))
    c = strip_units(c)

    return z, r, c, zscale, rhoscale
コード例 #6
0
ファイル: vertical_solver.py プロジェクト: dflemin3/diskpy
def setup(IC, R):
    """
    Initialize values for solving vertical hydrostatic equlibrium.
    
    Parameters
    ----------
    
    IC : IC object
        Initial conditions object
    R : SimArray
        Radius at which to solve hydrostatic equilibrium
    
    Returns
    -------
    
    z : array
        Dimensionless z bins, in units of h
    r : float
        Radius in units of h
    c : float
        Constant in residual equation
    zscale : SimArray
        Amount to scale z (all lengths) by to get dimensions back.
        ie, Z(actual) = z*zscale
    rhoscale : SimArray
        Scale for dimensionless rho
    """
    
    # Load everything from IC
    sigma = IC.sigma(R)
    T = IC.T(R)
    M = IC.settings.physical.M
    m = IC.settings.physical.m
    zmax = IC.settings.rho_calc.zmax
    nz = IC.settings.rho_calc.nz
    
    # Set-up constants
    a = G*M*m/(kB*T)
    b = 2*np.pi*G*m/(kB*T)
    h = np.sqrt(R*R*R/a).in_units('au')
    c = b*h*sigma
    c.convert_units('1')
    zscale = h
    rhoscale = sigma/h
    
    # Set-up z bins
    if zmax is None:
        
        zmax = 6*h
        
    zmax = strip_units((zmax/h).in_units('1'))
    z = np.linspace(0, zmax, nz)
    
    # Make everything dimensionless
    r = strip_units((R/h).in_units('1'))
    c = strip_units(c)
    
    return z, r, c, zscale, rhoscale
コード例 #7
0
ファイル: make_snapshot.py プロジェクト: philchang/diskpy
def sink_radius(IC):
    """
    Determine a reasonable sink radius for the star particles depending on 
    the star system type (e.g., single star, binary, etc...)
    
    Parameters
    ----------
    IC : IC object
    
    Returns
    -------
    r_sink : SimArray
        Sink radius for star particles
    """
    
    # Set up the sink radius
    starMode = IC.settings.physical.starMode.lower()
    
    if starMode == 'binary':
        
        binsys = IC.settings.physical.binsys
        #Set Sink Radius to be mass-weighted average of Roche lobes of two stars
        r1 = AddBinary.calcRocheLobe(binsys.m1/binsys.m2,binsys.a) 
        r2 = AddBinary.calcRocheLobe(binsys.m2/binsys.m1,binsys.a)
        p = strip_units(binsys.m1/(binsys.m1 + binsys.m2))
        r_sink = (r1*p) + (r2*(1.0-p))
    
    else:
    
        r_sink = IC.pos.r.min()
        
    return r_sink
コード例 #8
0
ファイル: AddBinary.py プロジェクト: dflemin3/diskpy
def binaryPrecession(s,r_in,r_out):
    """
    Computes the period of the binary precession due to an axisymmetric disk
    given by Rafikov 2013.

    Parameters
    ----------
    s : Tipsy snapshot
    r_in, r_out : float
        inner and outer radii of the circumbinary disk [AU]
        
    Returns
    -------
    T : SimArray
        Period of binary argument of periastron precession in yr
    """
    x1 = s.stars[0]['pos'].in_units('cm')
    x2 = s.stars[1]['pos'].in_units('cm')
    v1 = s.stars[0]['vel'].in_units('cm s**-1')
    v2 = s.stars[1]['vel'].in_units('cm s**-1')
    m1 = s.stars[0]['mass'].in_units('g')
    m2 = s.stars[1]['mass'].in_units('g')    
    
    # Define required parameters in cgs
    M_bin = m1 + m2
    M_disk = np.sum(s.gas['mass']).in_units('g')    
    a = SimArray(calcSemi(x1,x2,v1,v2,m1,m2,flag=False),'au').in_units('cm') #semimajor axis in cm
    n = calcMeanMotion(x1, x2, v1, v2, m1, m2, flag=False) #mean motion in 1/s    
    r_in = SimArray(r_in,'au').in_units('cm')
    r_out = SimArray(r_out,'au').in_units('cm')    
    
    T = 8.0*np.pi*(M_bin/M_disk)*(np.power(r_out,0.5)*np.power(r_in,2.5)/(np.power(a,3)*0.5*n))
    return strip_units(T)/YEARSEC
コード例 #9
0
    def _generate_theta(self):
        """
        Generate angular positions
        """

        nParticles = self.nParticles

        if self.method == 'glass':

            #already done in generate_r
            assert (len(self.theta) == nParticles)

        if self.method == 'grid':

            r = self.r

            dtheta = np.sqrt(2 * np.pi * (1 - r[0:-1] / r[1:]))
            dtheta = strip_units(dtheta)
            theta = np.zeros(nParticles)

            for n in range(nParticles - 1):

                # NOTE: it's import to subtract (not add) dtheta.  The particles
                # will be moving counter-clockwise.  To prevent the particle
                # spirals from kinking, the particle spirals must go out
                # clockwise
                theta[n + 1] = theta[n] - dtheta[n]

            self.theta = theta

        if self.method == 'random':

            np.random.seed(self._seed)
            theta = 2 * np.pi * np.random.rand(nParticles)
            self.theta = theta
コード例 #10
0
ファイル: pos_class.py プロジェクト: dflemin3/diskpy
 def _generate_theta(self):
     """
     Generate angular positions
     """
     
     nParticles = self.nParticles
     
     if self.method == 'grid':
         
         r = self.r
         
         dtheta = np.sqrt(2*np.pi*(1 - r[0:-1]/r[1:]))
         dtheta = strip_units(dtheta)
         theta = np.zeros(nParticles)
         
         for n in range(nParticles - 1):
             
             # NOTE: it's import to subtract (not add) dtheta.  The particles
             # will be moving counter-clockwise.  To prevent the particle
             # spirals from kinking, the particle spirals must go out
             # clockwise
             theta[n+1] = theta[n] - dtheta[n]
             
         self.theta = theta
         
     if self.method == 'random':
         
         np.random.seed(self._seed)
         theta = 2*np.pi*np.random.rand(nParticles)
         self.theta = theta
コード例 #11
0
ファイル: make_snapshot.py プロジェクト: ibackus/diskpy
def sink_radius(IC):
    """
    Determine a reasonable sink radius for the star particles depending on 
    the star system type (e.g., single star, binary, etc...)
    
    Parameters
    ----------
    IC : IC object
    
    Returns
    -------
    r_sink : SimArray
        Sink radius for star particles
    """
    
    # Set up the sink radius
    starMode = IC.settings.physical.starMode.lower()
    
    if starMode == 'binary':
        
        binsys = IC.settings.physical.binsys
        #Set Sink Radius to be mass-weighted average of Roche lobes of two stars
        r1 = AddBinary.calcRocheLobe(binsys.m1/binsys.m2,binsys.a) 
        r2 = AddBinary.calcRocheLobe(binsys.m2/binsys.m1,binsys.a)
        p = strip_units(binsys.m1/(binsys.m1 + binsys.m2))
        r_sink = (r1*p) + (r2*(1.0-p))
    
    else:
    
        r_sink = IC.pos.r.min()
        
    return r_sink
コード例 #12
0
    def T_adiabatic(self, r):
        """
        Estimates the adiabatic temperature profile as a function of r
        
        setup_interior must be run first
        """
#        if not self.adiabatic_ready:
#            
#            # Try to setup the adiabatic profile
#            self.setup_interior()
            
#        p = self.p
#        A = self.Tscale
#        print A
#        
#        r = match_units(r, 'au')[0]
#        sigma = self._parent.sigma(r)
#        sigma.convert_units('Msol au**-2')
#        sigma = strip_units(sigma)
#        r = strip_units(r)
#        return A * ((sigma**2)/(r**3))**p
            
        b = 1.5
        
        sigma = self._parent.sigma(r)
        r_a = self.r_a
        r = match_units(r, r_a.units)[0]
        x = (r/r_a).in_units('1')
        sigma_a = self.sigma_a
        y = (sigma/sigma_a).in_units('1')
        
        x = strip_units(x)
        y = strip_units(y)
        
        gamma = self._parent.settings.physical.gamma
        p = (gamma-1.)/(gamma+1.)
        
        T_a = self.T_a
        
        T = T_a * (y**(2*p)) * (x**-b)
        
        return T
        
#        r = strip_units(match_units(r,'au')[0])
#        
#        return A * (r**2)
コード例 #13
0
ファイル: rhosolver.py プロジェクト: dflemin3/diskpy
def setup_r_bins(IC, r=None):
        
    if IC.settings.rho_calc.nr is not None:
        
        nr = IC.settings.rho_calc.nr
        rmax = IC.sigma.r_bins[[-1]]
        rbins = np.linspace(0, rmax, nr)
        return rbins
    
    if r is None:
        # Setup the initial r bins
        rmax = IC.sigma.r_bins[[-1]]
        nr = len(IC.sigma.r_bins) * 10
        #r = np.linspace(0, rmax, nr)
        # dflemin3 Nov 4, 2015: made units more explicit
        # via SimArrays
        r_units = IC.sigma.r_bins.units
        r = SimArray(np.linspace(0, rmax, nr),r_units)        
        
    bin_error_tol = IC.settings.rho_calc.r_bin_tol
    minbins = IC.settings.rho_calc.min_r_bins
        
    # Estimate the disk height
    M = IC.settings.physical.M
    m = IC.settings.physical.m
    T = IC.T(r)
    h = h_est(r, M, m, T, gamma=1)
    
    # Estimate midplane density
    sigma = IC.sigma(r)
    rho0 = rho0_est(h, sigma)
    
    # Estimate a reasonable function tolerance for the bins
    # This is done by taking a weighted mean of midplane density: weighted
    # by the number of particles at each radius (the PDF)
    w = abs(IC.sigma.pdf(r))
    w /= w.sum()
    w = strip_units(w)
    # also weight the midplane density
    rho0 = w*rho0
    # Now do the mean
    rho0mean = (rho0*w).sum()
    ftol = bin_error_tol * rho0mean
    
    # Estimate reasonable bins.  This is done by removing as many bins as
    # possible to still allow the midplane density to be well resolved
    rbins = resolvedbins(r, rho0, minbins=minbins, ftol=ftol)
    rbins = rbins.copy()
    
    print '{} radial bins used for density calculation'.format(len(rbins))
    
    return rbins
コード例 #14
0
ファイル: rhosolver.py プロジェクト: philchang/diskpy
def setup_r_bins(IC, r=None):

    if IC.settings.rho_calc.nr is not None:

        nr = IC.settings.rho_calc.nr
        rmax = IC.sigma.r_bins[[-1]]
        rbins = np.linspace(0, rmax, nr)
        return rbins

    if r is None:
        # Setup the initial r bins
        rmax = IC.sigma.r_bins[[-1]]
        nr = len(IC.sigma.r_bins) * 10
        #r = np.linspace(0, rmax, nr)
        # dflemin3 Nov 4, 2015: made units more explicit
        # via SimArrays
        r_units = IC.sigma.r_bins.units
        r = SimArray(np.linspace(0, rmax, nr), r_units)

    bin_error_tol = IC.settings.rho_calc.r_bin_tol
    minbins = IC.settings.rho_calc.min_r_bins

    # Estimate the disk height
    M = IC.settings.physical.M
    m = IC.settings.physical.m
    T = IC.T(r)
    h = h_est(r, M, m, T, gamma=1)

    # Estimate midplane density
    sigma = IC.sigma(r)
    rho0 = rho0_est(h, sigma)

    # Estimate a reasonable function tolerance for the bins
    # This is done by taking a weighted mean of midplane density: weighted
    # by the number of particles at each radius (the PDF)
    w = abs(IC.sigma.pdf(r))
    w /= w.sum()
    w = strip_units(w)
    # also weight the midplane density
    rho0 = w * rho0
    # Now do the mean
    rho0mean = (rho0 * w).sum()
    ftol = bin_error_tol * rho0mean

    # Estimate reasonable bins.  This is done by removing as many bins as
    # possible to still allow the midplane density to be well resolved
    rbins = resolvedbins(r, rho0, minbins=minbins, ftol=ftol)
    rbins = rbins.copy()

    print '{} radial bins used for density calculation'.format(len(rbins))

    return rbins
コード例 #15
0
ファイル: AddBinary.py プロジェクト: dflemin3/diskpy
def calcCircularFrequency(x1, x2, v1, v2, m1, m2, flag=True):
    """
    Given pynbody arrays for positions and velocity of primary and secondary bodies
    and masses, calculates the circular frequency in the reduced two body system.
    Usage note: Intended for binary system, but pass x2 = v2 = 0 to use with any
    location in the disk.

    omega = (L_z)/(R^2) which assumes spherical symmetry (ok assumption here)
    L = sqrt(G*M*a*(1-e^2) for ~Keplerian

    Deprecated (just use sqrt(G*M/a^3))...why did I make this?

    Parameters
    ----------
    Assumed as pynbody SimArrays in simulation units (AU, scaled velocity, etc)
    
    x1,x2 : arrays
        Primary and secondary position arrays (in AU)
    v1, v2 : arrays
        Primary and secondary velocity arrays (km/s)
    m1, m2 : floats
        Primary and secondary masses (Msol)
    Flag : Whether or not to internally convert to cgs units

    Returns
    -------
    omega: float
        Circular frequency in 1/days
    """
    e = calcEcc(x1, x2, v1, v2, m1, m2, flag=True)
    a = calcSemi(x1, x2, v1, v2, m1, m2, flag=True) * AUCM
    
    if flag:
        # Remove units since input is pynbody SimArray
        x1 = np.asarray(strip_units(x1)) * AUCM
        x2 = np.asarray(strip_units(x2)) * AUCM
        v1 = np.asarray(strip_units(v1)) * 1000 * 100 * VEL_UNIT
        v2 = np.asarray(strip_units(v2)) * 1000 * 100 * VEL_UNIT
        m1 = np.asarray(strip_units(m1)) * Msol
        m2 = np.asarray(strip_units(m2)) * Msol

    length, ax = computeLenAx(x1)

    # Calculate angular momentum assuming all arrays are nx3
    r = x1 - x2
    rMag = np.sqrt(dotProduct(r, r))
    #e = ...    
    #a = calcSemi(x1, x2, v1, v2, m1, m2, flag=False) * AUCM
    L = np.sqrt(BigG * (m1 + m2) * a * (1 - e * e))

    # Convert from 1/s to 1/day, return
    return L * DAYSEC / (rMag * rMag)
コード例 #16
0
def calcCircularFrequency(x1, x2, v1, v2, m1, m2, flag=True):
    """
    Given pynbody arrays for positions and velocity of primary and secondary bodies
    and masses, calculates the circular frequency in the reduced two body system.
    Usage note: Intended for binary system, but pass x2 = v2 = 0 to use with any
    location in the disk.

    omega = (L_z)/(R^2) which assumes spherical symmetry (ok assumption here)
    L = sqrt(G*M*a*(1-e^2) for ~Keplerian

    Deprecated (just use sqrt(G*M/a^3))...why did I make this?

    Parameters
    ----------
    Assumed as pynbody SimArrays in simulation units (AU, scaled velocity, etc)
    
    x1,x2 : arrays
        Primary and secondary position arrays (in AU)
    v1, v2 : arrays
        Primary and secondary velocity arrays (km/s)
    m1, m2 : floats
        Primary and secondary masses (Msol)
    Flag : Whether or not to internally convert to cgs units

    Returns
    -------
    omega: float
        Circular frequency in 1/days
    """
    e = calcEcc(x1, x2, v1, v2, m1, m2, flag=True)
    a = calcSemi(x1, x2, v1, v2, m1, m2, flag=True) * AUCM

    if flag:
        # Remove units since input is pynbody SimArray
        x1 = np.asarray(strip_units(x1)) * AUCM
        x2 = np.asarray(strip_units(x2)) * AUCM
        v1 = np.asarray(strip_units(v1)) * 1000 * 100 * VEL_UNIT
        v2 = np.asarray(strip_units(v2)) * 1000 * 100 * VEL_UNIT
        m1 = np.asarray(strip_units(m1)) * Msol
        m2 = np.asarray(strip_units(m2)) * Msol

    length, ax = computeLenAx(x1)

    # Calculate angular momentum assuming all arrays are nx3
    r = x1 - x2
    rMag = np.sqrt(dotProduct(r, r))
    #e = ...
    #a = calcSemi(x1, x2, v1, v2, m1, m2, flag=False) * AUCM
    L = np.sqrt(BigG * (m1 + m2) * a * (1 - e * e))

    # Convert from 1/s to 1/day, return
    return L * DAYSEC / (rMag * rMag)
コード例 #17
0
def binaryPrecession(s, r_in, r_out):
    """
    Computes the period of the binary precession due to an axisymmetric disk
    given by Rafikov 2013.

    Parameters
    ----------
    s : Tipsy snapshot
    r_in, r_out : float
        inner and outer radii of the circumbinary disk [AU]
        
    Returns
    -------
    T : SimArray
        Period of binary argument of periastron precession in yr
    """
    x1 = s.stars[0]['pos'].in_units('cm')
    x2 = s.stars[1]['pos'].in_units('cm')
    v1 = s.stars[0]['vel'].in_units('cm s**-1')
    v2 = s.stars[1]['vel'].in_units('cm s**-1')
    m1 = s.stars[0]['mass'].in_units('g')
    m2 = s.stars[1]['mass'].in_units('g')

    # Define required parameters in cgs
    M_bin = m1 + m2
    M_disk = np.sum(s.gas['mass']).in_units('g')
    a = SimArray(calcSemi(x1, x2, v1, v2, m1, m2, flag=False),
                 'au').in_units('cm')  #semimajor axis in cm
    n = calcMeanMotion(x1, x2, v1, v2, m1, m2, flag=False)  #mean motion in 1/s
    r_in = SimArray(r_in, 'au').in_units('cm')
    r_out = SimArray(r_out, 'au').in_units('cm')

    T = 8.0 * np.pi * (M_bin /
                       M_disk) * (np.power(r_out, 0.5) * np.power(r_in, 2.5) /
                                  (np.power(a, 3) * 0.5 * n))
    return strip_units(T) / YEARSEC
コード例 #18
0
def snapshot_gen(ICobj):
    """
    Generates a tipsy snapshot from the initial conditions object ICobj.
    
    Returns snapshot, param
    
        snapshot: tipsy snapshot
        param: dictionary containing info for a .param file
    Note: Code has been edited (dflemin3) such that now it returns a snapshot for a circumbinary disk
    where initial conditions generated assuming star at origin of mass M.  After gas initialized, replaced
    star at origin with binary system who's center of mass lies at the origin and who's mass m1 +m2 = M
    """

    print 'Generating snapshot...'
    # Constants
    G = SimArray(1.0, 'G')
    # ------------------------------------
    # Load in things from ICobj
    # ------------------------------------
    print 'Accessing data from ICs'
    settings = ICobj.settings

    # snapshot file name
    snapshotName = settings.filenames.snapshotName
    paramName = settings.filenames.paramName

    #Load user supplied snapshot (assumed to be in cwd)
    path = "/astro/store/scratch/tmp/dflemin3/nbodyshare/9au-Q1.05-129K/"
    snapshot = pynbody.load(path + snapshotName)

    # particle positions
    r = snapshot.gas['r']
    xyz = snapshot.gas['pos']

    # Number of particles
    nParticles = len(snapshot.gas)

    # molecular mass
    m = settings.physical.m

    #Pull star mass from user-supplied snapshot
    ICobj.settings.physical.M = snapshot.star[
        'mass']  #Total stellar mass in solar masses
    m_star = ICobj.settings.physical.M

    # disk mass
    m_disk = np.sum(snapshot.gas['mass'])
    m_disk = match_units(m_disk, m_star)[0]

    # mass of the gas particles
    m_particles = m_disk / float(nParticles)

    # re-scale the particles (allows making of low-mass disk)
    m_particles *= settings.snapshot.mScale

    # -------------------------------------------------
    # Assign output
    # -------------------------------------------------
    print 'Assigning data to snapshot'
    # Get units all set up
    m_unit = m_star.units
    pos_unit = r.units

    if xyz.units != r.units:

        xyz.convert_units(pos_unit)

    # time units are sqrt(L^3/GM)
    t_unit = np.sqrt((pos_unit**3) * np.power((G * m_unit), -1)).units
    # velocity units are L/t
    v_unit = (pos_unit / t_unit).ratio('km s**-1')
    # Make it a unit, save value for future conversion
    v_unit_vel = v_unit
    #Ensure v_unit_vel is the same as what I assume it is.
    assert (np.fabs(AddBinary.VEL_UNIT - v_unit_vel) <
            AddBinary.SMALL), "VEL_UNIT not equal to ChaNGa unit! Why??"

    v_unit = pynbody.units.Unit('{0} km s**-1'.format(v_unit))

    # Other settings
    metals = settings.snapshot.metals
    star_metals = metals

    # Estimate the star's softening length as the closest particle distance
    eps = r.min()

    # Make param file
    param = make_param(snapshot, snapshotName)
    param['dMeanMolWeight'] = m

    gc.collect()

    # CALCULATE VELOCITY USING calc_velocity.py.  This also estimates the
    # gravitational softening length eps

    preset = settings.changa_run.preset

    # -------------------------------------------------
    # Estimate time step for changa to use
    # -------------------------------------------------
    # Save param file
    configsave(param, paramName, 'param')
    # Save snapshot
    snapshot.write(filename=snapshotName, fmt=pynbody.tipsy.TipsySnap)
    # est dDelta
    dDelta = ICgen_utils.est_time_step(paramName, preset)
    param['dDelta'] = dDelta

    # -------------------------------------------------
    # Create director file
    # -------------------------------------------------
    # largest radius to plot
    r_director = float(0.9 * r.max())
    # Maximum surface density
    sigma_min = float(ICobj.sigma(r_director))
    # surface density at largest radius
    sigma_max = float(ICobj.sigma.input_dict['sigma'].max())
    # Create director dict
    director = make_director(sigma_min,
                             sigma_max,
                             r_director,
                             filename=param['achOutName'])
    ## Save .director file
    #configsave(director, directorName, 'director')
    """
    Now that the gas disk is initializes around the primary (M=m1), add in the
    second star as specified by the user.
    """

    #Now that velocities and everything are all initialized for gas particles, create new snapshot to return in which
    #single star particle is replaced by 2, same units as above
    snapshotBinary = pynbody.new(star=2, gas=nParticles)
    snapshotBinary['eps'] = 0.01 * SimArray(
        np.ones(nParticles + 2, dtype=np.float32), pos_unit)
    snapshotBinary['metals'] = SimArray(
        np.zeros(nParticles + 2, dtype=np.float32))
    snapshotBinary['vel'].units = v_unit
    snapshotBinary['pos'].units = pos_unit
    snapshotBinary['mass'].units = snapshot['mass'].units
    snapshotBinary['rho'] = SimArray(np.zeros(nParticles + 2,
                                              dtype=np.float32))

    #Assign gas particles with calculated/given values from above
    snapshotBinary.gas['pos'] = snapshot.gas['pos']
    snapshotBinary.gas['vel'] = snapshot.gas['vel']
    snapshotBinary.gas['temp'] = snapshot.gas['temp']
    snapshotBinary.gas['rho'] = snapshot.gas['rho']
    snapshotBinary.gas['eps'] = snapshot.gas['eps']
    snapshotBinary.gas['mass'] = snapshot.gas['mass']
    snapshotBinary.gas['metals'] = snapshot.gas['metals']

    #Load Binary system obj to initialize system
    binsys = ICobj.settings.physical.binsys
    m_disk = strip_units(np.sum(snapshotBinary.gas['mass']))
    binsys.m1 = strip_units(m_star)
    binsys.m1 = binsys.m1 + m_disk
    #Recompute cartesian coords considering primary as m1+m_disk
    binsys.computeCartesian()

    x1, x2, v1, v2 = binsys.generateICs()

    #Assign position, velocity assuming CCW orbit
    snapshotBinary.star[0]['pos'] = SimArray(x1, pos_unit)
    snapshotBinary.star[0]['vel'] = SimArray(v1, v_unit)
    snapshotBinary.star[1]['pos'] = SimArray(x2, pos_unit)
    snapshotBinary.star[1]['vel'] = SimArray(v2, v_unit)
    """
    We have the binary positions about their center of mass, (0,0,0), so 
    shift the position, velocity of the gas disk to be around the primary.
    """
    snapshotBinary.gas['pos'] += snapshotBinary.star[0]['pos']
    snapshotBinary.gas['vel'] += snapshotBinary.star[0]['vel']

    #Set stellar masses: Create simArray for mass, convert units to simulation mass units
    snapshotBinary.star[0]['mass'] = SimArray(binsys.m1 - m_disk, m_unit)
    snapshotBinary.star[1]['mass'] = SimArray(binsys.m2, m_unit)
    snapshotBinary.star['metals'] = SimArray(star_metals)

    print 'Wrapping up'
    # Now set the star particle's tform to a negative number.  This allows
    # UW ChaNGa treat it as a sink particle.
    snapshotBinary.star['tform'] = -1.0

    #Set sink radius, stellar smoothing length as fraction of distance
    #from primary to inner edge of the disk
    r_sink = eps
    snapshotBinary.star[0]['eps'] = SimArray(r_sink / 2.0, pos_unit)
    snapshotBinary.star[1]['eps'] = SimArray(r_sink / 2.0, pos_unit)
    param['dSinkBoundOrbitRadius'] = r_sink
    param['dSinkRadius'] = r_sink
    param['dSinkMassMin'] = 0.9 * binsys.m2
    param['bDoSinks'] = 1

    return snapshotBinary, param, director
コード例 #19
0
def snapshot_gen(ICobj):
    """
    Generates a tipsy snapshot from the initial conditions object ICobj.
    
    Returns snapshot, param
    
        snapshot: tipsy snapshot
        param: dictionary containing info for a .param file
    Note: Code has been edited (dflemin3) such that now it returns a snapshot for a circumbinary disk
    where initial conditions generated assuming star at origin of mass M.  After gas initialized, replaced
    star at origin with binary system who's center of mass lies at the origin and who's mass m1 +m2 = M
    """

    print "Generating snapshot..."
    # Constants
    G = SimArray(1.0, "G")
    # ------------------------------------
    # Load in things from ICobj
    # ------------------------------------
    print "Accessing data from ICs"
    settings = ICobj.settings

    # snapshot file name
    snapshotName = settings.filenames.snapshotName
    paramName = settings.filenames.paramName

    # Load user supplied snapshot (assumed to be in cwd)
    path = "/astro/store/scratch/tmp/dflemin3/nbodyshare/9au-Q1.05-129K/"
    snapshot = pynbody.load(path + snapshotName)

    # particle positions
    r = snapshot.gas["r"]
    xyz = snapshot.gas["pos"]

    # Number of particles
    nParticles = len(snapshot.gas)

    # molecular mass
    m = settings.physical.m

    # Pull star mass from user-supplied snapshot
    ICobj.settings.physical.M = snapshot.star["mass"]  # Total stellar mass in solar masses
    m_star = ICobj.settings.physical.M

    # disk mass
    m_disk = np.sum(snapshot.gas["mass"])
    m_disk = match_units(m_disk, m_star)[0]

    # mass of the gas particles
    m_particles = m_disk / float(nParticles)

    # re-scale the particles (allows making of low-mass disk)
    m_particles *= settings.snapshot.mScale

    # -------------------------------------------------
    # Assign output
    # -------------------------------------------------
    print "Assigning data to snapshot"
    # Get units all set up
    m_unit = m_star.units
    pos_unit = r.units

    if xyz.units != r.units:

        xyz.convert_units(pos_unit)

    # time units are sqrt(L^3/GM)
    t_unit = np.sqrt((pos_unit ** 3) * np.power((G * m_unit), -1)).units
    # velocity units are L/t
    v_unit = (pos_unit / t_unit).ratio("km s**-1")
    # Make it a unit, save value for future conversion
    v_unit_vel = v_unit
    # Ensure v_unit_vel is the same as what I assume it is.
    assert np.fabs(AddBinary.VEL_UNIT - v_unit_vel) < AddBinary.SMALL, "VEL_UNIT not equal to ChaNGa unit! Why??"

    v_unit = pynbody.units.Unit("{0} km s**-1".format(v_unit))

    # Other settings
    metals = settings.snapshot.metals
    star_metals = metals

    # Estimate the star's softening length as the closest particle distance
    eps = r.min()

    # Make param file
    param = make_param(snapshot, snapshotName)
    param["dMeanMolWeight"] = m

    gc.collect()

    # CALCULATE VELOCITY USING calc_velocity.py.  This also estimates the
    # gravitational softening length eps

    preset = settings.changa_run.preset

    # -------------------------------------------------
    # Estimate time step for changa to use
    # -------------------------------------------------
    # Save param file
    configsave(param, paramName, "param")
    # Save snapshot
    snapshot.write(filename=snapshotName, fmt=pynbody.tipsy.TipsySnap)
    # est dDelta
    dDelta = ICgen_utils.est_time_step(paramName, preset)
    param["dDelta"] = dDelta

    # -------------------------------------------------
    # Create director file
    # -------------------------------------------------
    # largest radius to plot
    r_director = float(0.9 * r.max())
    # Maximum surface density
    sigma_min = float(ICobj.sigma(r_director))
    # surface density at largest radius
    sigma_max = float(ICobj.sigma.input_dict["sigma"].max())
    # Create director dict
    director = make_director(sigma_min, sigma_max, r_director, filename=param["achOutName"])
    ## Save .director file
    # configsave(director, directorName, 'director')

    """
    Now that the gas disk is initializes around the primary (M=m1), add in the
    second star as specified by the user.
    """

    # Now that velocities and everything are all initialized for gas particles, create new snapshot to return in which
    # single star particle is replaced by 2, same units as above
    snapshotBinary = pynbody.new(star=2, gas=nParticles)
    snapshotBinary["eps"] = 0.01 * SimArray(np.ones(nParticles + 2, dtype=np.float32), pos_unit)
    snapshotBinary["metals"] = SimArray(np.zeros(nParticles + 2, dtype=np.float32))
    snapshotBinary["vel"].units = v_unit
    snapshotBinary["pos"].units = pos_unit
    snapshotBinary["mass"].units = snapshot["mass"].units
    snapshotBinary["rho"] = SimArray(np.zeros(nParticles + 2, dtype=np.float32))

    # Assign gas particles with calculated/given values from above
    snapshotBinary.gas["pos"] = snapshot.gas["pos"]
    snapshotBinary.gas["vel"] = snapshot.gas["vel"]
    snapshotBinary.gas["temp"] = snapshot.gas["temp"]
    snapshotBinary.gas["rho"] = snapshot.gas["rho"]
    snapshotBinary.gas["eps"] = snapshot.gas["eps"]
    snapshotBinary.gas["mass"] = snapshot.gas["mass"]
    snapshotBinary.gas["metals"] = snapshot.gas["metals"]

    # Load Binary system obj to initialize system
    binsys = ICobj.settings.physical.binsys
    m_disk = strip_units(np.sum(snapshotBinary.gas["mass"]))
    binsys.m1 = strip_units(m_star)
    binsys.m1 = binsys.m1 + m_disk
    # Recompute cartesian coords considering primary as m1+m_disk
    binsys.computeCartesian()

    x1, x2, v1, v2 = binsys.generateICs()

    # Assign position, velocity assuming CCW orbit
    snapshotBinary.star[0]["pos"] = SimArray(x1, pos_unit)
    snapshotBinary.star[0]["vel"] = SimArray(v1, v_unit)
    snapshotBinary.star[1]["pos"] = SimArray(x2, pos_unit)
    snapshotBinary.star[1]["vel"] = SimArray(v2, v_unit)

    """
    We have the binary positions about their center of mass, (0,0,0), so 
    shift the position, velocity of the gas disk to be around the primary.
    """
    snapshotBinary.gas["pos"] += snapshotBinary.star[0]["pos"]
    snapshotBinary.gas["vel"] += snapshotBinary.star[0]["vel"]

    # Set stellar masses: Create simArray for mass, convert units to simulation mass units
    snapshotBinary.star[0]["mass"] = SimArray(binsys.m1 - m_disk, m_unit)
    snapshotBinary.star[1]["mass"] = SimArray(binsys.m2, m_unit)
    snapshotBinary.star["metals"] = SimArray(star_metals)

    print "Wrapping up"
    # Now set the star particle's tform to a negative number.  This allows
    # UW ChaNGa treat it as a sink particle.
    snapshotBinary.star["tform"] = -1.0

    # Set sink radius, stellar smoothing length as fraction of distance
    # from primary to inner edge of the disk
    r_sink = eps
    snapshotBinary.star[0]["eps"] = SimArray(r_sink / 2.0, pos_unit)
    snapshotBinary.star[1]["eps"] = SimArray(r_sink / 2.0, pos_unit)
    param["dSinkBoundOrbitRadius"] = r_sink
    param["dSinkRadius"] = r_sink
    param["dSinkMassMin"] = 0.9 * binsys.m2
    param["bDoSinks"] = 1

    return snapshotBinary, param, director
コード例 #20
0
ファイル: _param.py プロジェクト: dflemin3/diskpy
def make_director(sigma_min, sigma_max, r, resolution=1200, filename='snapshot'):
    """
    Makes a director dictionary for ChaNGa runs based on the min/max surface
    density, maximum image radius, and image resolution for a gaseous
    protoplanetary disk.  The created dictionary can be saved with
    diskpy.utils.configsave

    The method is to use an example director file (saved as default.director)
    which works for one simulation and scale the various parameters accordingly.
    default.director should have a commented line in it which reads:
        #sigma_max float
    where float is the maximum surface density of the simulation in simulation
    units.

    **ARGUMENTS**

    sigma_min : float
        The surface density that corresponds to 0 density on the image (ie the
        minimum threshold).  Required for setting the dynamic range
    sigma_max : float
        Maximum surface density in the simulation
    r : float
        Maximum radius to plot out to
    resolution : int or float
        Number of pixels in image.  The image is shape (resolution, resolution)
    filename : str
        prefix to use for saving the images.  Example: if filename='snapshot',
        then the outputs will be of form 'snapshot.000000000.ppm'

    **RETURNS**

    director : dict
        A .director dictionary.  Can be saved with diskpy.utils.configsave
    """
    # -----------------------------------------------------------
    # Parse defaults to get scale factor for c
    # -----------------------------------------------------------
    sigma_min, sigma_max, r = strip_units([sigma_min, sigma_max, r])
    defaults = configparser(_directordefault)
    if '#sigma_max' not in defaults:

        raise KeyError,'Default .director file should have a line e.g. << #sigma_max 0.01 >>'

    sigma_max0 = defaults['#sigma_max']
    c0 = defaults['colgas'][3]
    n0 = defaults['size'][0]
    r0 = defaults['eye'][2]
    A = (c0 * float(n0)**2)/(sigma_max0 * r0**2)

    # -----------------------------------------------------------
    # Create new director dictionary
    # -----------------------------------------------------------
    director = copy.deepcopy(defaults)
    director.pop('#sigma_max', None)

    logscale_min = sigma_min/sigma_max

    if pynbody.units.has_units(logscale_min):

        logscale_min = float(logscale_min.in_units('1'))

    c = A * float(sigma_max * r**2 /float(resolution)**2)

    director['colgas'][3] = c
    director['size'] = [resolution, resolution]
    director['eye'][2] = r
    director['file'] = filename

    return director
コード例 #21
0
ファイル: make_snapshot.py プロジェクト: ibackus/diskpy
def make_binary(IC, snapshot):
    """
    Turns a snapshot for a single star into a snapshot of a binary system
    
    Parameters
    ----------
    IC : IC object
    snapshot : SimSnap
        Single star system to turn into a binary
    
    Returns
    -------
    snapshotBinary : SimSnap
        A binary version of the simulation snapshot
    """
    # Initialize snapshot
    snapshotBinary = pynbody.new(star=2, gas=len(snapshot.g))
    # Copy gas particles over
    for key in snapshot.gas.keys():
        
        snapshotBinary.gas[key] = snapshot.gas[key]
        
    # Load Binary system obj to initialize system
    starMode = IC.settings.physical.starMode.lower()
    binsys = IC.settings.physical.binsys
    
    if starMode == 'stype':
        
        # Treate the primary as a star of mass mStar + mDisk
        m_disk = strip_units(np.sum(snapshotBinary.gas['mass']))
        binsys.m1 += m_disk
        binsys.computeCartesian()
        
    x1,x2,v1,v2 = binsys.generateICs()
    
    #Assign star parameters assuming CCW orbit
    snapshotBinary.star[0]['pos'] = x1
    snapshotBinary.star[0]['vel'] = v1
    snapshotBinary.star[1]['pos'] = x2
    snapshotBinary.star[1]['vel'] = v2
    
    #Set stellar masses
    priMass = binsys.m1
    secMass = binsys.m2    
    snapshotBinary.star[0]['mass'] = priMass
    snapshotBinary.star[1]['mass'] = secMass    
    snapshotBinary.star['metals'] = snapshot.s['metals']
    
    if starMode == 'stype':
        # We have the binary positions about their center of mass, (0,0,0), so 
        # shift the position, velocity of the gas disk to be around the primary.
        snapshotBinary.gas['pos'] += snapshotBinary.star[0]['pos']
        snapshotBinary.gas['vel'] += snapshotBinary.star[0]['vel']  
        # Remove disk mass from the effective star mass
        snapshotBinary[0]['mass'] -= m_disk
        binsys.m1 -= m_disk
        # Star smoothing
        snapshotBinary.star['eps'] = snapshot.star['eps']

        
    elif starMode == 'binary':
        
        # Estimate stars' softening length as fraction of distance to COM
        d = np.sqrt(AddBinary.dotProduct(x1-x2,x1-x2))
        pos_unit = snapshotBinary['pos'].units
        snapshotBinary.star['eps'] = SimArray(abs(d)/4.0,pos_unit)
        
    return snapshotBinary
コード例 #22
0
ファイル: clumpfinding.py プロジェクト: philchang/diskpy
def find_clumps(f,
                n_smooth=32,
                param=None,
                arg_string=None,
                seed=None,
                verbose=True):
    """
    Uses skid (https://github.com/N-BodyShop/skid) to find clumps in a gaseous
    protoplanetary disk.  
    
    The linking length used is equal to the gravitational softening length of
    the gas particles.
    
    The density cut-off comes from the criterion that there are n_smooth particles
    within the Hill sphere of a particle.  This is formulated mathematically as:
    
        rho_min = 3*n_smooth*Mstar/R^3
        
    where R is the distance from the star.  The trick used here is to multiply
    all particle masses by R^3 before running skid so the density cut-off is:
    
        rho_min = 3*n_smooth*Mstar
        
    **ARGUMENTS**
    
    *f* : TipsySnap, or str
        A tipsy snapshot loaded/created by pynbody -OR- a filename pointing to a
        snapshot.
    
    *n_smooth* : int (optional)
        Number of particles used in SPH calculations.  Should be the same as used
        in the simulation.  Default = 32
    
    *param* : str (optional)
        filename for a .param file for the simulation
    
    *arg_string* : str (optional)
        Additional arguments to be passed to skid.  Cannot use -tau, -d, -m, -s, -o
    
    *seed* : int
        An integer used to seed the random filename generation for temporary
        files.  Necessary for multiprocessing and should be unique for each
        thread.
        
    *verbose* : bool
        Verbosity flag.  Default is True
    
    **RETURNS**
    
    *clumps* : array, int-like
        Array containing the group number each particle belongs to, with star
        particles coming after gas particles.  A zero means the particle belongs
        to no groups
    """
    # Parse areguments
    if isinstance(f, str):

        f = pynbody.load(f, paramfile=param)

    if seed is not None:

        np.random.seed(seed)

    # Estimate the linking length as the gravitational softening length
    tau = f.g['eps'][0]

    # Calculate minimum density
    rho_min = 3 * n_smooth * f.s['mass'][0]

    # Center on star.  This is done because R used in hill-sphere calculations
    # is relative to the star
    star_pos = f.s['pos'].copy()
    f['pos'] -= star_pos

    # Scale mass by R^3
    R = utils.strip_units(f['rxy'])
    m0 = f['mass'].copy()
    f['mass'] *= (R + tau)**3

    # Save temporary snapshot
    f_prefix = str(np.random.randint(np.iinfo(int).max))
    f_name = f_prefix + '.std'

    # Save temporary .param file
    if param is not None:

        param_name = f_prefix + '.param'
        param_dict = utils.configparser(param, 'param')
        utils.configsave(param_dict, param_name)

    f.write(filename=f_name, fmt=pynbody.tipsy.TipsySnap)

    f['pos'] += star_pos
    f['mass'] = m0

    command = 'totipnat < {} | skid -tau {:.2e} -d {:.2e} -m {:d} -s {:d} -o {}'\
    .format(f_name, tau, rho_min, n_smooth, n_smooth, f_prefix)
    p = subprocess.Popen(command,
                         shell=True,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)

    if verbose:

        for line in iter(p.stdout.readline, ''):
            print line,

    p.wait()

    # Load clumps
    clumps = loadhalos(f_prefix + '.grp')

    # Cleanup
    for name in glob.glob(f_prefix + '*'):

        os.remove(name)

    return clumps
コード例 #23
0
ファイル: binaryUtils.py プロジェクト: dflemin3/diskpy
def findCBResonances(s,r,r_min,r_max,m_max=4,l_max=4,bins=50):
    """
    Given Tipsy snapshot, computes the resonances of disk on binary as a function of orbital angular frequency omega.
    Disk radius, in au, is convered to angular frequency which will then be used to compute corotation 
    and inner/outer Lindblad resonances.
   
   Note: r given MUST correspond to r over which de/dt was calculated.  Otherwise, scale gets all messed up
   
   !!! NOTE: This function is awful and deprecated --- do NOT use it.  Instead, use calc_LB_resonance !!!
 
     Parameters
     ----------
     s: Tipsy-format snapshot
     r: array
         radius array over which de/dt was calculated
     r_min,r_max: floats
         min/maximum disk radius for calculations (au)
     bins: int
         number of radial bins to calculate over
     m_max,l_max: ints
         maximum orders of (m,l) LR

    Returns
    -------
    Orbital frequency: numpy array
        for corotation and inner/outer resonances and radii as float and numpy arrays
    """
    stars = s.stars
    gas = s.gas

    m_min = 1 #m >=1 for LRs, CRs
    l_min = 1 #l >=1 for LRs, CRs

    #Compute binary angular frequency
    x1 = stars[0]['pos']
    x2 = stars[1]['pos']
    v1 = stars[0]['vel']
    v2 = stars[1]['vel']
    m1 = stars[0]['mass']
    m2 = stars[1]['mass']
     
    a = strip_units(AddBinary.calcSemi(x1, x2, v1, v2, m1, m2))
    omega_b = 2.0*np.pi/AddBinary.aToP(a,m1+m2) #In units 1/day

    #Make r steps smaller for higher accuracy
    r_arr = np.linspace(r.min(),r.max(),len(r)*10)

    #Compute mass of disk interior to given r
    mask = np.zeros((len(gas),len(r_arr)),dtype=bool)
    m_disk = np.zeros(len(r_arr))
    for i in range(0,len(r_arr)):
        mask[:,i] = gas['rxy'] < r_arr[i]
        m_disk[i] = np.sum(gas['mass'][mask[:,i]])

    #Compute omega_disk in units 1/day (like omega_binary)
    omega_d = 2.0*np.pi/AddBinary.aToP(r_arr,m1+m2+m_disk)
        
    #Compute kappa (radial epicycle frequency = sqrt(r * d(omega^2)/dr + 4*(omega^2))
    o2 = omega_d*omega_d
    dr = r_arr[1] - r_arr[0]
    #dr = (r.max()-r.min())/float(bins) #Assuming r has evenly spaced bins!
    drdo2 = np.gradient(o2,dr) #I mean d/dr(omega^2)
    kappa = np.sqrt(r_arr*drdo2 + 4.0*o2)
   
    #Allocate arrays for output 
    omega_Lo = np.zeros((m_max,l_max))
    omega_Li = np.zeros((m_max,l_max))
    o_c = np.zeros(l_max)   
 
    #Find resonance angular frequency
    for m in range(m_min,m_max+1):
        for l in range(l_min,l_max+1):
            outer = omega_d + (float(l)/m)*kappa
            inner = omega_d - (float(l)/m)*kappa
            omega_Lo[m-m_min,l-l_min] = omega_d[np.argmin(np.fabs(omega_b-outer))]
            omega_Li[m-m_min,l-l_min] = omega_d[np.argmin(np.fabs(omega_b-inner))]

            #Find corotation resonance where omega_d ~ omega_b
            o_c[l-l_min] = omega_d[np.argmin(np.fabs(omega_d-omega_b/float(l)))]

    #Rescale omega_d, kappa to be of length bins again
    omega_d = np.linspace(omega_d.min(),omega_d.max(),bins)
    kappa = np.linspace(kappa.min(),kappa.max(),bins)
    return omega_Li, omega_Lo, o_c, omega_d, kappa
コード例 #24
0
ファイル: _math.py プロジェクト: philchang/diskpy
def meshinterp(xedges,
               y,
               z,
               kind='linear',
               bounds_error=False,
               fill_value=0,
               assume_sorted=True):
    """
    Generates a 2D interpolating function for z defined on a non-uniform mesh
    Handles units
    
    Parameters
    ----------
    
    xedges : array
        1D array defining the x bin edges, monotonically increasing
    y : array
        2D array defining y values.  shape (nx, ny), where nx is the number
        of xedges and ny is the number of y-points at each x-bin
        So, y[i, :] are the monotonically increasing y values at xedges[i]
    z : array
        2D array of z(x,y).  shape (nx, ny) = y.shape
    kind : str
        (optional) Sets the kind of interpolation to perform
        [see scipy.interpolate.interp1d]
    bounds_error : bool
        (optional) Flag to raise error if values outside of y are called
        [see scipy.interpolate.interp1d]
    fill_value : float
        (optional) Sets the value to fill with if bounds_error = True
        [see scipy.interpolate.interp1d]
    assume_sorted : bool
        [see scipy.interpolate.interp1d]
    
    Returns
    -------
    
    meshspline(x, y): callable interpolation function
        Function which can be called on x, y pairs to give the interpolated
        value of z.  Values outside of the range of y are set to fill_value.
        x values outside the range of xedges are set to the boundary of xedges
    """
    # Check shapes

    if z.shape != y.shape:

        raise ValueError, 'y and z must have same shape'

    if len(xedges) != len(y):

        raise ValueError, 'x and y must have same len'

    # Handle units
    pos = [xedges, y, z]
    units = []
    for a in pos:

        if pb.units.has_units(a):

            units.append(a.units)

        else:

            units.append(None)

    xedges, y, z = strip_units(pos)
    # Setup bin information
    binsize = xedges[1:] - xedges[0:-1]
    xmin = xedges[0]
    xmax = xedges[-1]
    nbins = len(xedges) - 1

    # set up spliness
    splines = []

    for i in range(nbins + 1):

        # perform interpolation to make spline
        splines.append(interp1d(y[i], z[i], kind=kind, \
        bounds_error=bounds_error, fill_value=fill_value))

        # Assume_sorted doesn't work in older scipy versions


#        # perform interpolation to make spline
#        splines.append(interp1d(y[i], z[i], kind=kind, \
#        bounds_error=bounds_error, fill_value=fill_value, \
#        assume_sorted=assume_sorted))

# Define the callable interplation function to return

    def meshspline(x1, y1):
        """
        Callable interpolation function, interoplates the value of z at
        points (x1, y1)
        
        Parameters
        ----------
        
        x1, y1 : array
            x and y points to evaluate z at.  Must be the same shape.  ie,
            x1[i], y1[i] define a point (x, y).
            If @x1 or @y1 have no units, they are assumed to have the units of
            the nodes used to make the interpolator.  Otherwise they are
            converted to the proper units
            
        Returns
        -------
        
        z(x1, y1) : array
            z evaluated at @x1, @y1
        """
        # Handle units
        x1 = strip_units(match_units(x1, units[0])[0])
        y1 = strip_units(match_units(y1, units[1])[0])

        # Setup x and y points to estimate z at
        x1 = np.asarray(x1).copy()
        y1 = np.asarray(y1)

        if len(x1.shape) < 1:

            x1 = x1[None]

        if len(y1.shape) < 1:

            y1 = y1[None]

        # Flatten arrays
        shape = x1.shape
        nElements = np.prod(shape)
        x1 = np.reshape(x1, [nElements])
        y1 = np.reshape(y1, [nElements])

        # Deal with xs outside of boundaries
        x1[x1 < xmin] = xmin
        x1[x1 > xmax] = xmax
        # Find bin indices
        ind = np.digitize(x1, xedges) - 1
        ind[ind < 0] = 0
        ind[ind > nbins - 1] = nbins - 1

        # Get bin info for every point
        xlo = xedges[ind]
        xhi = xedges[ind + 1]
        dx = binsize[ind]

        # Get weights for bins (distance from bin edges)
        wlo = (xhi - x1) / dx
        whi = (x1 - xlo) / dx

        # Get function values at left and right xedges
        flo = np.zeros(x1.shape)
        fhi = np.zeros(x1.shape)

        for i in range(nbins):

            # Select everything in bin i
            mask = (ind == i)

            if np.any(mask):

                # Retrieve function values
                flo[mask] = splines[i](y1[mask])
                fhi[mask] = splines[i + 1](y1[mask])

        # Take a weighted average of the function values at left and right
        # bin edges
        fout = wlo * flo + whi * fhi

        # Unflatten fout:
        fout = np.reshape(fout, shape)

        return SimArray(fout, units[2])

    return meshspline
コード例 #25
0
ファイル: _math.py プロジェクト: dflemin3/diskpy
def binned_mean(x, y, bins=10, nbins=None, binedges=None, weights=None, weighted_bins=False, ret_bin_edges=False):
    """
    Bins y according to x and takes the average for each bin.

    bins can either be an integer (the number of bins to use) or an array of
    binedges.  bins will be overridden by nbins or binedges

    Optionally (for compatibility reasons) if binedges is specified, the
    x-bins are defined by binedges.  Otherwise the x-bins are determined by
    nbins

    If weights = None, equal weights are assumed for the average, otherwise
    weights for each data point should be specified

    y_err (error in y) is calculated as the standard deviation in y for each
    bin, divided by sqrt(N), where N is the number of counts in each bin

    IF weighted_bins is True, the bin centers are calculated as a center of
    mass

    NaNs are ignored for the input.  Empty bins are returned with nans

    RETURNS a tuple of (bin_centers, y_mean, y_err) if ret_bin_edges=False
    else, Returns (bin_edges, y_mean, y_err)
    """
    if (isinstance(bins, int)) and (nbins is None):

        nbins = bins

    elif (hasattr(bins, "__iter__")) and (binedges is None):

        binedges = bins

    if binedges is not None:

        nbins = len(binedges) - 1

    else:

        binedges = np.linspace(x.min(), (1 + np.spacing(2)) * x.max(), nbins + 1)

    if weights is None:

        weights = np.ones(x.shape)

    weights = strip_units(weights)

    # Pre-factor for weighted STD:
    A = 1 / (1 - (weights ** 2).sum())

    # Initialize
    y_mean = np.zeros(nbins)
    y_std = np.zeros(nbins)
    # Find the index bins for each data point
    ind = np.digitize(x, binedges) - 1
    # Ignore nans
    nan_ind = np.isnan(y)
    N = np.histogram(x, binedges)[0]

    # Initialize bin_centers (try to retain units)
    bin_centers = 0.0 * binedges[1:]

    for i in range(nbins):

        # Indices to use
        mask = (ind == i) & (~nan_ind)
        # Set up the weighting
        w = weights[mask].copy()
        w /= w.sum()
        A = 1 / (1 - (w ** 2).sum())
        # y_mean[i] = np.nanmean(y[mask])
        y_mean[i] = (w * y[mask]).sum()
        var = A * (w * (y[mask] - y_mean[i]) ** 2).sum()
        y_std[i] = np.sqrt(var)
        # y_std[i] = np.std(y[use_ind])

        if weighted_bins:
            # Center of mass of x positions
            bin_centers[i] = (w * x[mask]).sum()

    y_mean = match_units(y_mean, y)[0]
    y_err = y_std / np.sqrt(N)
    y_err = match_units(y_err, y)[0]

    y_mean[N == 0] = np.nan
    y_err[N == 0] = np.nan

    if not weighted_bins:

        bin_centers = (binedges[0:-1] + binedges[1:]) / 2.0
        binedges = match_units(binedges, x)[0]
        bin_centers = match_units(bin_centers, x)[0]

    else:

        bin_centers[N == 0] = np.nan

    if ret_bin_edges:

        return binedges, y_mean, y_err

    else:

        return bin_centers, y_mean, y_err
コード例 #26
0
ファイル: _math.py プロジェクト: dflemin3/diskpy
def meshinterp(xedges, y, z, kind="linear", bounds_error=False, fill_value=0, assume_sorted=True):
    """
    Generates a 2D interpolating function for z defined on a non-uniform mesh
    Handles units
    
    Parameters
    ----------
    
    xedges : array
        1D array defining the x bin edges, monotonically increasing
    y : array
        2D array defining y values.  shape (nx, ny), where nx is the number
        of xedges and ny is the number of y-points at each x-bin
        So, y[i, :] are the monotonically increasing y values at xedges[i]
    z : array
        2D array of z(x,y).  shape (nx, ny) = y.shape
    kind : str
        (optional) Sets the kind of interpolation to perform
        [see scipy.interpolate.interp1d]
    bounds_error : bool
        (optional) Flag to raise error if values outside of y are called
        [see scipy.interpolate.interp1d]
    fill_value : float
        (optional) Sets the value to fill with if bounds_error = True
        [see scipy.interpolate.interp1d]
    assume_sorted : bool
        [see scipy.interpolate.interp1d]
    
    Returns
    -------
    
    meshspline(x, y): callable interpolation function
        Function which can be called on x, y pairs to give the interpolated
        value of z.  Values outside of the range of y are set to fill_value.
        x values outside the range of xedges are set to the boundary of xedges
    """
    # Check shapes

    if z.shape != y.shape:

        raise ValueError, "y and z must have same shape"

    if len(xedges) != len(y):

        raise ValueError, "x and y must have same len"

    # Handle units
    pos = [xedges, y, z]
    units = []
    for a in pos:

        if pb.units.has_units(a):

            units.append(a.units)

        else:

            units.append(None)

    xedges, y, z = strip_units(pos)
    # Setup bin information
    binsize = xedges[1:] - xedges[0:-1]
    xmin = xedges[0]
    xmax = xedges[-1]
    nbins = len(xedges) - 1

    # set up spliness
    splines = []

    for i in range(nbins + 1):

        # perform interpolation to make spline
        splines.append(
            interp1d(
                y[i], z[i], kind=kind, bounds_error=bounds_error, fill_value=fill_value, assume_sorted=assume_sorted
            )
        )

    # Define the callable interplation function to return
    def meshspline(x1, y1):
        """
        Callable interpolation function, interoplates the value of z at
        points (x1, y1)
        
        Parameters
        ----------
        
        x1, y1 : array
            x and y points to evaluate z at.  Must be the same shape.  ie,
            x1[i], y1[i] define a point (x, y).
            If @x1 or @y1 have no units, they are assumed to have the units of
            the nodes used to make the interpolator.  Otherwise they are
            converted to the proper units
            
        Returns
        -------
        
        z(x1, y1) : array
            z evaluated at @x1, @y1
        """
        # Handle units
        x1 = strip_units(match_units(x1, units[0])[0])
        y1 = strip_units(match_units(y1, units[1])[0])

        # Setup x and y points to estimate z at
        x1 = np.asarray(x1).copy()
        y1 = np.asarray(y1)

        if len(x1.shape) < 1:

            x1 = x1[None]

        if len(y1.shape) < 1:

            y1 = y1[None]

        # Flatten arrays
        shape = x1.shape
        nElements = np.prod(shape)
        x1 = np.reshape(x1, [nElements])
        y1 = np.reshape(y1, [nElements])

        # Deal with xs outside of boundaries
        x1[x1 < xmin] = xmin
        x1[x1 > xmax] = xmax
        # Find bin indices
        ind = np.digitize(x1, xedges) - 1
        ind[ind < 0] = 0
        ind[ind > nbins - 1] = nbins - 1

        # Get bin info for every point
        xlo = xedges[ind]
        xhi = xedges[ind + 1]
        dx = binsize[ind]

        # Get weights for bins (distance from bin edges)
        wlo = (xhi - x1) / dx
        whi = (x1 - xlo) / dx

        # Get function values at left and right xedges
        flo = np.zeros(x1.shape)
        fhi = np.zeros(x1.shape)

        for i in range(nbins):

            # Select everything in bin i
            mask = ind == i

            if np.any(mask):

                # Retrieve function values
                flo[mask] = splines[i](y1[mask])
                fhi[mask] = splines[i + 1](y1[mask])

        # Take a weighted average of the function values at left and right
        # bin edges
        fout = wlo * flo + whi * fhi

        # Unflatten fout:
        fout = np.reshape(fout, shape)

        return SimArray(fout, units[2])

    return meshspline
コード例 #27
0
ファイル: _math.py プロジェクト: philchang/diskpy
    def meshspline(x1, y1):
        """
        Callable interpolation function, interoplates the value of z at
        points (x1, y1)
        
        Parameters
        ----------
        
        x1, y1 : array
            x and y points to evaluate z at.  Must be the same shape.  ie,
            x1[i], y1[i] define a point (x, y).
            If @x1 or @y1 have no units, they are assumed to have the units of
            the nodes used to make the interpolator.  Otherwise they are
            converted to the proper units
            
        Returns
        -------
        
        z(x1, y1) : array
            z evaluated at @x1, @y1
        """
        # Handle units
        x1 = strip_units(match_units(x1, units[0])[0])
        y1 = strip_units(match_units(y1, units[1])[0])

        # Setup x and y points to estimate z at
        x1 = np.asarray(x1).copy()
        y1 = np.asarray(y1)

        if len(x1.shape) < 1:

            x1 = x1[None]

        if len(y1.shape) < 1:

            y1 = y1[None]

        # Flatten arrays
        shape = x1.shape
        nElements = np.prod(shape)
        x1 = np.reshape(x1, [nElements])
        y1 = np.reshape(y1, [nElements])

        # Deal with xs outside of boundaries
        x1[x1 < xmin] = xmin
        x1[x1 > xmax] = xmax
        # Find bin indices
        ind = np.digitize(x1, xedges) - 1
        ind[ind < 0] = 0
        ind[ind > nbins - 1] = nbins - 1

        # Get bin info for every point
        xlo = xedges[ind]
        xhi = xedges[ind + 1]
        dx = binsize[ind]

        # Get weights for bins (distance from bin edges)
        wlo = (xhi - x1) / dx
        whi = (x1 - xlo) / dx

        # Get function values at left and right xedges
        flo = np.zeros(x1.shape)
        fhi = np.zeros(x1.shape)

        for i in range(nbins):

            # Select everything in bin i
            mask = (ind == i)

            if np.any(mask):

                # Retrieve function values
                flo[mask] = splines[i](y1[mask])
                fhi[mask] = splines[i + 1](y1[mask])

        # Take a weighted average of the function values at left and right
        # bin edges
        fout = wlo * flo + whi * fhi

        # Unflatten fout:
        fout = np.reshape(fout, shape)

        return SimArray(fout, units[2])
コード例 #28
0
ファイル: _clumpfinding.py プロジェクト: ibackus/diskpy
def find_clumps(f, n_smooth=32, param=None, arg_string=None, seed=None, verbose=True):
    """
    Uses skid (https://github.com/N-BodyShop/skid) to find clumps in a gaseous
    protoplanetary disk.  
    Also requires tipsy tools (https://github.com/N-BodyShop/tipsy_tools),
    specifically totipnat
    
    The linking length used is equal to the gravitational softening length of
    the gas particles.
    
    The density cut-off comes from the criterion that there are n_smooth particles
    within the Hill sphere of a particle.  This is formulated mathematically as:
    
        rho_min = 3*n_smooth*Mstar/R^3
        
    where R is the distance from the star.  The trick used here is to multiply
    all particle masses by R^3 before running skid so the density cut-off is:
    
        rho_min = 3*n_smooth*Mstar
        
    **ARGUMENTS**
    
    *f* : TipsySnap, or str
        A tipsy snapshot loaded/created by pynbody -OR- a filename pointing to a
        snapshot.
    
    *n_smooth* : int (optional)
        Number of particles used in SPH calculations.  Should be the same as used
        in the simulation.  Default = 32
    
    *param* : str (optional)
        filename for a .param file for the simulation
    
    *arg_string* : str (optional)
        Additional arguments to be passed to skid.  Cannot use -tau, -d, -m, -s, -o
    
    *seed* : int
        An integer used to seed the random filename generation for temporary
        files.  Necessary for multiprocessing and should be unique for each
        thread.
        
    *verbose* : bool
        Verbosity flag.  Default is True
    
    **RETURNS**
    
    *clumps* : array, int-like
        Array containing the group number each particle belongs to, with star
        particles coming after gas particles.  A zero means the particle belongs
        to no groups
    """
    # Check for skid and totipnat
    err = []
    skid_path = utils.which('skid')
    
    if skid_path is None:
        
        err.append('<skid not found : https://github.com/N-BodyShop/skid>')
        
    totipnat_path = utils.which('totipnat')
    
    if totipnat_path is None:
        
        err.append('<totipnat (part of tipsy tools) not found : '
        'https://github.com/N-BodyShop/tipsy_tools>')
        
    if len(err) > 0:
        
        err = '\n'.join(err)
        raise RuntimeError, err
        
    # Parse areguments
    if isinstance(f, str):
        
        f = pynbody.load(f, paramfile=param)
        
    if seed is not None:
        
        np.random.seed(seed)
        
    # Estimate the linking length as the gravitational softening length
    tau = f.g['eps'][0]
    
    # Calculate minimum density
    rho_min = 3*n_smooth*f.s['mass'][0]
    
    # Center on star.  This is done because R used in hill-sphere calculations
    # is relative to the star
    star_pos = f.s['pos'].copy()
    f['pos'] -= star_pos
    
    # Scale mass by R^3
    R = utils.strip_units(f['rxy'])
    m0 = f['mass'].copy()
    f['mass'] *= (R+tau)**3
    
    # Save temporary snapshot
    f_prefix = str(np.random.randint(np.iinfo(int).max))
    f_name = f_prefix + '.std'
    
    # Save temporary .param file
    if param is not None:
        
        param_name = f_prefix + '.param'
        param_dict = utils.configparser(param, 'param')
        utils.configsave(param_dict, param_name)
        
    f.write(filename=f_name, fmt=pynbody.tipsy.TipsySnap)
        
    f['pos'] += star_pos
    f['mass'] = m0
    
    command = 'totipnat < {} | skid -tau {:.2e} -d {:.2e} -m {:d} -s {:d} -o {}'\
    .format(f_name, tau, rho_min, n_smooth, n_smooth, f_prefix)
    p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    
    if verbose:
        
        for line in iter(p.stdout.readline, ''):
            print line,
            
    p.wait()
    
    # Load clumps
    clumps = loadhalos(f_prefix + '.grp')
    
    # Cleanup
    for name in glob.glob(f_prefix + '*'):
        
        os.remove(name)
        
    return clumps
コード例 #29
0
ファイル: make_snapshot.py プロジェクト: philchang/diskpy
def make_binary(IC, snapshot):
    """
    Turns a snapshot for a single star into a snapshot of a binary system
    
    Parameters
    ----------
    IC : IC object
    snapshot : SimSnap
        Single star system to turn into a binary
    
    Returns
    -------
    snapshotBinary : SimSnap
        A binary version of the simulation snapshot
    """
    # Initialize snapshot
    snapshotBinary = pynbody.new(star=2, gas=len(snapshot.g))
    # Copy gas particles over
    for key in snapshot.gas.keys():
        
        snapshotBinary.gas[key] = snapshot.gas[key]
        
    # Load Binary system obj to initialize system
    starMode = IC.settings.physical.starMode.lower()
    binsys = IC.settings.physical.binsys
    
    if starMode == 'stype':
        
        # Treate the primary as a star of mass mStar + mDisk
        m_disk = strip_units(np.sum(snapshotBinary.gas['mass']))
        binsys.m1 += m_disk
        binsys.computeCartesian()
        
    x1,x2,v1,v2 = binsys.generateICs()
    
    #Assign star parameters assuming CCW orbit
    snapshotBinary.star[0]['pos'] = x1
    snapshotBinary.star[0]['vel'] = v1
    snapshotBinary.star[1]['pos'] = x2
    snapshotBinary.star[1]['vel'] = v2
    
    #Set stellar masses
    priMass = binsys.m1
    secMass = binsys.m2    
    snapshotBinary.star[0]['mass'] = priMass
    snapshotBinary.star[1]['mass'] = secMass    
    snapshotBinary.star['metals'] = snapshot.s['metals']
    
    if starMode == 'stype':
        # We have the binary positions about their center of mass, (0,0,0), so 
        # shift the position, velocity of the gas disk to be around the primary.
        snapshotBinary.gas['pos'] += snapshotBinary.star[0]['pos']
        snapshotBinary.gas['vel'] += snapshotBinary.star[0]['vel']  
        # Remove disk mass from the effective star mass
        snapshotBinary[0]['mass'] -= m_disk
        binsys.m1 -= m_disk
        # Star smoothing
        snapshotBinary.star['eps'] = snapshot.star['eps']

        
    elif starMode == 'binary':
        
        # Estimate stars' softening length as fraction of distance to COM
        d = np.sqrt(AddBinary.dotProduct(x1-x2,x1-x2))
        pos_unit = snapshotBinary['pos'].units
        snapshotBinary.star['eps'] = SimArray(abs(d)/4.0,pos_unit)
        
    return snapshotBinary
コード例 #30
0
ファイル: make_snapshot.py プロジェクト: dflemin3/diskpy
def snapshot_gen(ICobj):
    """
    Generates a tipsy snapshot from the initial conditions object ICobj.
    
    Returns snapshot, param
    
        snapshot: tipsy snapshot
        param: dictionary containing info for a .param file
    """
    
    print 'Generating snapshot...'
    # Constants
    G = SimArray(1.0,'G')
    # ------------------------------------
    # Load in things from ICobj
    # ------------------------------------
    print 'Accessing data from ICs'
    settings = ICobj.settings
    # filenames
    snapshotName = settings.filenames.snapshotName
    paramName = settings.filenames.paramName
        
    # particle positions
    r = ICobj.pos.r
    xyz = ICobj.pos.xyz
    # Number of particles
    nParticles = ICobj.pos.nParticles
    # molecular mass
    m = settings.physical.m
    # star mass
    m_star = settings.physical.M.copy()
    # disk mass
    m_disk = ICobj.sigma.m_disk.copy()
    m_disk = match_units(m_disk, m_star)[0]
    # mass of the gas particles
    m_particles = m_disk / float(nParticles)
    # re-scale the particles (allows making of lo-mass disk)
    m_particles *= settings.snapshot.mScale
    
    # -------------------------------------------------
    # Assign output
    # -------------------------------------------------
    print 'Assigning data to snapshot'
    # Get units all set up
    m_unit = m_star.units
    pos_unit = r.units
    
    if xyz.units != r.units:
        
        xyz.convert_units(pos_unit)
        
    # time units are sqrt(L^3/GM)
    t_unit = np.sqrt((pos_unit**3)*np.power((G*m_unit), -1)).units
    # velocity units are L/t
    v_unit = (pos_unit/t_unit).ratio('km s**-1')
    # Make it a unit
    v_unit = pynbody.units.Unit('{0} km s**-1'.format(v_unit))
    
    # Other settings
    metals = settings.snapshot.metals
    star_metals = metals
    
    # -------------------------------------------------
    # Initialize snapshot
    # -------------------------------------------------
    # Note that empty pos, vel, and mass arrays are created in the snapshot
    snapshot = pynbody.new(star=1,gas=nParticles)
    snapshot['vel'].units = v_unit
    snapshot['eps'] = 0.01*SimArray(np.ones(nParticles+1, dtype=np.float32), pos_unit)
    snapshot['metals'] = SimArray(np.zeros(nParticles+1, dtype=np.float32))
    snapshot['rho'] = SimArray(np.zeros(nParticles+1, dtype=np.float32))
    
    snapshot.gas['pos'] = xyz
    snapshot.gas['temp'] = ICobj.T(r)
    snapshot.gas['mass'] = m_particles
    snapshot.gas['metals'] = metals
    
    snapshot.star['pos'] = SimArray([[ 0.,  0.,  0.]],pos_unit)
    snapshot.star['vel'] = SimArray([[ 0.,  0.,  0.]], v_unit)
    snapshot.star['mass'] = m_star
    snapshot.star['metals'] = SimArray(star_metals)
    # Estimate the star's softening length as the closest particle distance
    snapshot.star['eps'] = r.min()
    
    # Make param file
    param = make_param(snapshot, snapshotName)
    param['dMeanMolWeight'] = m
    eos = (settings.physical.eos).lower()
    
    if eos == 'adiabatic':
        
        param['bGasAdiabatic'] = 1
        param['bGasIsothermal'] = 0
        
    param['dConstGamma']
       
    gc.collect()
    
    # -------------------------------------------------
    # CALCULATE VELOCITY USING calc_velocity.py.  This also estimates the 
    # gravitational softening length eps
    # -------------------------------------------------
    print 'Calculating circular velocity'
    preset = settings.changa_run.preset
    max_particles = global_settings['misc']['max_particles']
    calc_velocity.v_xy(snapshot, param, changa_preset=preset, max_particles=max_particles)
    
    gc.collect()
    
    # -------------------------------------------------
    # Estimate time step for changa to use
    # -------------------------------------------------
    # Save param file
    configsave(param, paramName, 'param')
    # Save snapshot
    snapshot.write(filename=snapshotName, fmt=pynbody.tipsy.TipsySnap)
    # est dDelta
    dDelta = ICgen_utils.est_time_step(paramName, preset)
    param['dDelta'] = dDelta
    
    # -------------------------------------------------
    # Create director file
    # -------------------------------------------------
    # largest radius to plot
    r_director = float(0.9 * r.max())
    # Maximum surface density
    sigma_min = float(ICobj.sigma(r_director))
    # surface density at largest radius
    sigma_max = float(ICobj.sigma.input_dict['sigma'].max())
    # Create director dict
    director = make_director(sigma_min, sigma_max, r_director, filename=param['achOutName'])
    ## Save .director file
    #configsave(director, directorName, 'director')
    
    # -------------------------------------------------
    # Wrap up
    # -------------------------------------------------
    print 'Wrapping up'
    # Now set the star particle's tform to a negative number.  This allows
    # UW ChaNGa treat it as a sink particle.
    snapshot.star['tform'] = -1.0
    
    # Update params
    r_sink = strip_units(r.min())
    param['dSinkBoundOrbitRadius'] = r_sink
    param['dSinkRadius'] = r_sink
    param['dSinkMassMin'] = 0.9 * strip_units(m_star)
    param['bDoSinks'] = 1
    
    return snapshot, param, director
コード例 #31
0
ファイル: binaryUtils.py プロジェクト: philchang/diskpy
def findCBResonances(s, r, r_min, r_max, m_max=4, l_max=4, bins=50):
    """
    Given Tipsy snapshot, computes the resonances of disk on binary as a function of orbital angular frequency omega.
    Disk radius, in au, is convered to angular frequency which will then be used to compute corotation 
    and inner/outer Lindblad resonances.
   
   Note: r given MUST correspond to r over which de/dt was calculated.  Otherwise, scale gets all messed up
   
   !!! NOTE: This function is awful and deprecated --- do NOT use it.  Instead, use calc_LB_resonance !!!
 
     Parameters
     ----------
     s: Tipsy-format snapshot
     r: array
         radius array over which de/dt was calculated
     r_min,r_max: floats
         min/maximum disk radius for calculations (au)
     bins: int
         number of radial bins to calculate over
     m_max,l_max: ints
         maximum orders of (m,l) LR

    Returns
    -------
    Orbital frequency: numpy array
        for corotation and inner/outer resonances and radii as float and numpy arrays
    """
    stars = s.stars
    gas = s.gas

    m_min = 1  #m >=1 for LRs, CRs
    l_min = 1  #l >=1 for LRs, CRs

    #Compute binary angular frequency
    x1 = stars[0]['pos']
    x2 = stars[1]['pos']
    v1 = stars[0]['vel']
    v2 = stars[1]['vel']
    m1 = stars[0]['mass']
    m2 = stars[1]['mass']

    a = strip_units(AddBinary.calcSemi(x1, x2, v1, v2, m1, m2))
    omega_b = 2.0 * np.pi / AddBinary.aToP(a, m1 + m2)  #In units 1/day

    #Make r steps smaller for higher accuracy
    r_arr = np.linspace(r.min(), r.max(), len(r) * 10)

    #Compute mass of disk interior to given r
    mask = np.zeros((len(gas), len(r_arr)), dtype=bool)
    m_disk = np.zeros(len(r_arr))
    for i in range(0, len(r_arr)):
        mask[:, i] = gas['rxy'] < r_arr[i]
        m_disk[i] = np.sum(gas['mass'][mask[:, i]])

    #Compute omega_disk in units 1/day (like omega_binary)
    omega_d = 2.0 * np.pi / AddBinary.aToP(r_arr, m1 + m2 + m_disk)

    #Compute kappa (radial epicycle frequency = sqrt(r * d(omega^2)/dr + 4*(omega^2))
    o2 = omega_d * omega_d
    dr = r_arr[1] - r_arr[0]
    #dr = (r.max()-r.min())/float(bins) #Assuming r has evenly spaced bins!
    drdo2 = np.gradient(o2, dr)  #I mean d/dr(omega^2)
    kappa = np.sqrt(r_arr * drdo2 + 4.0 * o2)

    #Allocate arrays for output
    omega_Lo = np.zeros((m_max, l_max))
    omega_Li = np.zeros((m_max, l_max))
    o_c = np.zeros(l_max)

    #Find resonance angular frequency
    for m in range(m_min, m_max + 1):
        for l in range(l_min, l_max + 1):
            outer = omega_d + (float(l) / m) * kappa
            inner = omega_d - (float(l) / m) * kappa
            omega_Lo[m - m_min,
                     l - l_min] = omega_d[np.argmin(np.fabs(omega_b - outer))]
            omega_Li[m - m_min,
                     l - l_min] = omega_d[np.argmin(np.fabs(omega_b - inner))]

            #Find corotation resonance where omega_d ~ omega_b
            o_c[l - l_min] = omega_d[np.argmin(
                np.fabs(omega_d - omega_b / float(l)))]

    #Rescale omega_d, kappa to be of length bins again
    omega_d = np.linspace(omega_d.min(), omega_d.max(), bins)
    kappa = np.linspace(kappa.min(), kappa.max(), bins)
    return omega_Li, omega_Lo, o_c, omega_d, kappa
コード例 #32
0
ファイル: binaryUtils.py プロジェクト: dflemin3/diskpy
def linearMomentumEffects(x1, x2, v1, v2, m1, m2, accretion):
	"""
	Given initial binary system parameters and an array tracking the accretion events, calculate the effects of accretion
	on the semimajor axis and eccentricity of the binary system.

	Inputs: Assume all input arrays are in simulation units
	Masses of primary and secondary (m1, m2 in Msol)
	Position arrays of primary and secondary x1, x2 (in AU)
	Velocity arrays of primary and secondary v1, v2 (in km/s)
	Numpy array of accretion events of the form [m vx vy vz ...] for each accreted gas particle at time of accretion

	Output:
	Semimajor axis, eccentricity of binary system after accretion events
	"""
	#Extract masses and velocities of accreted gas particles from array of known format
	m_g = np.zeros(len(accretion))	
	v = np.zeros(shape=(len(accretion),3))

	for i in range(len(accretion)):
		m_g[i] = accretion[i,0]	
		for j in range(1,4):
			v[i,j-1] = accretion[i,j]

	#Strip units from all inputs, convert all into CGS
	r1 = np.asarray(strip_units(x1))*AddBinary.AUCM
	r2 = np.asarray(strip_units(x2))*AddBinary.AUCM
	v1 = np.asarray(strip_units(v1))*AddBinary.VEL_UNIT*100*1000
	v2 = np.asarray(strip_units(v2))*AddBinary.VEL_UNIT*100*1000
	m1 = np.asarray(strip_units(m1))*AddBinary.Msol
	m2 = np.asarray(strip_units(m2))*AddBinary.Msol
	m_g = m_g*AddBinary.Msol
	v = v * AddBinary.VEL_UNIT*100*1000

	#Compute relative binary system quantities
	vBin = v1 - v2
	rBin = r1 - r2
	mBin = m1 + m2

	#Loop over accretion events, apply conservation of linear momentum at each step
	for i in range(len(accretion)):
		vBin = (1.0/(mBin+m_g[i]))*(mBin*vBin + m_g[i]*v[i])
		mBin = mBin + m_g[i]	

	#Compute final semimajor axis, eccentricity
	
	#Compute r, v, standard gravitational parameter
	magR = np.linalg.norm(rBin)
	mu = AddBinary.BigG*(mBin)
	magV = np.linalg.norm(vBin)

	#Compute specific orbital energy, angular momentum
	eps = (magV*magV/2.0) - (mu/magR)
	h = np.cross(rBin,vBin)
	magH = np.linalg.norm(h)
	
	#Compute semimajor axis	in AU
	a = -mu/(2.0*eps)/(AddBinary.AUCM)

	#Compute eccentricity
	e = np.sqrt(1 + ((2*eps*magH*magH)/(mu*mu)))

	return a,e
コード例 #33
0
ファイル: binaryUtils.py プロジェクト: philchang/diskpy
def linearMomentumEffects(x1, x2, v1, v2, m1, m2, accretion):
    """
	Given initial binary system parameters and an array tracking the accretion events, calculate the effects of accretion
	on the semimajor axis and eccentricity of the binary system.

	Inputs: Assume all input arrays are in simulation units
	Masses of primary and secondary (m1, m2 in Msol)
	Position arrays of primary and secondary x1, x2 (in AU)
	Velocity arrays of primary and secondary v1, v2 (in km/s)
	Numpy array of accretion events of the form [m vx vy vz ...] for each accreted gas particle at time of accretion

	Output:
	Semimajor axis, eccentricity of binary system after accretion events
	"""
    #Extract masses and velocities of accreted gas particles from array of known format
    m_g = np.zeros(len(accretion))
    v = np.zeros(shape=(len(accretion), 3))

    for i in range(len(accretion)):
        m_g[i] = accretion[i, 0]
        for j in range(1, 4):
            v[i, j - 1] = accretion[i, j]

    #Strip units from all inputs, convert all into CGS
    r1 = np.asarray(strip_units(x1)) * AddBinary.AUCM
    r2 = np.asarray(strip_units(x2)) * AddBinary.AUCM
    v1 = np.asarray(strip_units(v1)) * AddBinary.VEL_UNIT * 100 * 1000
    v2 = np.asarray(strip_units(v2)) * AddBinary.VEL_UNIT * 100 * 1000
    m1 = np.asarray(strip_units(m1)) * AddBinary.Msol
    m2 = np.asarray(strip_units(m2)) * AddBinary.Msol
    m_g = m_g * AddBinary.Msol
    v = v * AddBinary.VEL_UNIT * 100 * 1000

    #Compute relative binary system quantities
    vBin = v1 - v2
    rBin = r1 - r2
    mBin = m1 + m2

    #Loop over accretion events, apply conservation of linear momentum at each step
    for i in range(len(accretion)):
        vBin = (1.0 / (mBin + m_g[i])) * (mBin * vBin + m_g[i] * v[i])
        mBin = mBin + m_g[i]

    #Compute final semimajor axis, eccentricity

    #Compute r, v, standard gravitational parameter
    magR = np.linalg.norm(rBin)
    mu = AddBinary.BigG * (mBin)
    magV = np.linalg.norm(vBin)

    #Compute specific orbital energy, angular momentum
    eps = (magV * magV / 2.0) - (mu / magR)
    h = np.cross(rBin, vBin)
    magH = np.linalg.norm(h)

    #Compute semimajor axis	in AU
    a = -mu / (2.0 * eps) / (AddBinary.AUCM)

    #Compute eccentricity
    e = np.sqrt(1 + ((2 * eps * magH * magH) / (mu * mu)))

    return a, e
コード例 #34
0
 def _est_r_adiabatic(self):
     """
     Estimates the radius at which the temperature profile should be made
     adiabatic (for adiabatic disks only!).  This is defined the be the
     first radius at which the entropy gradient switches from negative
     to positive
     
     Returns
     -------
     
     r_adiabatic : SimArray
         radius
     
     Notes
     -----
     
     Entropy gradients are estimated assuming:
     
     * Star gravity dominates disk self-gravity
     
     * Disk is thin
     
     * No vertical temperature gradient
     
     """
     ICobj = self._parent
     
     if not hasattr(ICobj, 'sigma'):
         
         raise RuntimeError, 'Sigma not found in initial conditions object'
         
     gamma = ICobj.settings.physical.gamma
     p = (gamma - 1.)/(gamma + 1.)
     a = 1/p        
     r = ICobj.sigma.r_bins
     temp = strip_units(self.T_nocut(r))
     sigma = strip_units(ICobj.sigma(r))
     r1 = strip_units(r)
     # Entropy/mass (up to a multiplicative and an additive constant)
     s = 0.5*a*np.log(temp) + 1.5*np.log(r1) - np.log(sigma)
     # Entropy gradient (up to a multiplicative constant)
     ds = np.gradient(s)
     # Find all negative to positive zero crossings
     neg = ds < 0
     ind = np.where(neg[0:-1] & ~neg[1:])[0] + 1
     
     if len(ind) > 1:
         
         print 'WARNING: Multiple r_adiabatics found.  Selecting the lowest'
         r_adiabatic = r[[ind[0]]]
         
     elif len(ind) < 1:
         
         print 'WARNING: could not find r_adiabatic'
         r_adiabatic = SimArray([0.],'au')
         
     else:
         
         r_adiabatic = r[ind]
         
     return r_adiabatic
コード例 #35
0
ファイル: _math.py プロジェクト: philchang/diskpy
def binned_mean(x, y, bins=10, nbins=None, binedges = None, weights=None,\
weighted_bins=False, ret_bin_edges=False, binind=None):
    """
    Bins y according to x and takes the average for each bin.

    RETURNS a tuple of (bin_centers, y_mean, y_err) if ret_bin_edges=False
    else, Returns (bin_edges, y_mean, y_err)
    
    Parameters
    ----------
    x, y : array-like
        Bin and average y according to x
    bins : int or arraylike
        Either number of bins or an array of binedges
    nbins : int
        (optional) For backward compatibility, prefer using bins
    binedges : array-like
        (optional) For backward compatibility, prefer using bins
    weights : array-like
        Weights to use for data points.  Assume weights=1 (uniform)
    weighted_bins : bool
        If true, the bin centers will be calculated as weighted centers
    ret_bin_edges : bool
        Return bin centers instead of edges.  Default = False
    binind : list of arrays
        An optional list of arrays which specify which indices of x, y belong
        to which bin.  This can be used for speed.  when using a pynbody profile,
        pynbody will generate such a list:
            >>> p = pynbody.analysis.profile.Profile(f)
            >>> p.binind # binind
        For the returned bins to be consistent, the user should supply the used
        binedges.
    
    """
    x = np.asanyarray(x)
    y = np.asanyarray(y)
    if (isinstance(bins, int)) and (nbins is None):

        nbins = bins

    elif (hasattr(bins, '__iter__')) and (binedges is None):

        binedges = bins

    if binedges is not None:

        nbins = len(binedges) - 1

    else:

        binedges = np.linspace(x.min(), (1 + np.spacing(2)) * x.max(),
                               nbins + 1)

    if weights is None:

        weights = np.ones(x.shape)

    weights = strip_units(weights)

    # Pre-factor for weighted STD:
    A = 1 / (1 - (weights**2).sum())

    # Initialize
    y_mean = np.zeros(nbins)
    y_std = np.zeros(nbins)
    if binind is None:
        # Find the index bins for each data point
        ind = np.digitize(x, binedges) - 1
        N = np.histogram(x, binedges)[0]
    else:
        N = np.array([ind.sum() for ind in binind])
    # Ignore nans
    nan_ind = np.isnan(y)
    # Initialize bin_centers (try to retain units)
    bin_centers = 0.0 * binedges[1:]

    for i in range(nbins):

        if binind is None:
            #Indices to use
            mask = (ind == i) & (~nan_ind)
            # Set up the weighting
            w = weights[mask].copy()
            yvals = y[mask]
            xvals = x[mask]
        else:
            select_ind = binind[i]
            w = weights[select_ind]
            yvals = y[select_ind]
            xvals = x[select_ind]

        w /= w.sum()
        A = 1 / (1 - (w**2).sum())
        y_mean[i] = (w * yvals).sum()
        var = A * (w * (yvals - y_mean[i])**2).sum()
        y_std[i] = np.sqrt(var)

        if weighted_bins:
            # Center of mass of x positions
            bin_centers[i] = (w * xvals).sum()

    y_mean = match_units(y_mean, y)[0]
    y_err = y_std / np.sqrt(N)
    y_err = match_units(y_err, y)[0]

    y_mean[N == 0] = np.nan
    y_err[N == 0] = np.nan

    if not weighted_bins:

        bin_centers = (binedges[0:-1] + binedges[1:]) / 2.0
        binedges = match_units(binedges, x)[0]
        bin_centers = match_units(bin_centers, x)[0]

    else:

        bin_centers[N == 0] = np.nan

    if ret_bin_edges:

        return binedges, y_mean, y_err

    else:

        return bin_centers, y_mean, y_err
コード例 #36
0
ファイル: _math.py プロジェクト: dflemin3/diskpy
    def meshspline(x1, y1):
        """
        Callable interpolation function, interoplates the value of z at
        points (x1, y1)
        
        Parameters
        ----------
        
        x1, y1 : array
            x and y points to evaluate z at.  Must be the same shape.  ie,
            x1[i], y1[i] define a point (x, y).
            If @x1 or @y1 have no units, they are assumed to have the units of
            the nodes used to make the interpolator.  Otherwise they are
            converted to the proper units
            
        Returns
        -------
        
        z(x1, y1) : array
            z evaluated at @x1, @y1
        """
        # Handle units
        x1 = strip_units(match_units(x1, units[0])[0])
        y1 = strip_units(match_units(y1, units[1])[0])

        # Setup x and y points to estimate z at
        x1 = np.asarray(x1).copy()
        y1 = np.asarray(y1)

        if len(x1.shape) < 1:

            x1 = x1[None]

        if len(y1.shape) < 1:

            y1 = y1[None]

        # Flatten arrays
        shape = x1.shape
        nElements = np.prod(shape)
        x1 = np.reshape(x1, [nElements])
        y1 = np.reshape(y1, [nElements])

        # Deal with xs outside of boundaries
        x1[x1 < xmin] = xmin
        x1[x1 > xmax] = xmax
        # Find bin indices
        ind = np.digitize(x1, xedges) - 1
        ind[ind < 0] = 0
        ind[ind > nbins - 1] = nbins - 1

        # Get bin info for every point
        xlo = xedges[ind]
        xhi = xedges[ind + 1]
        dx = binsize[ind]

        # Get weights for bins (distance from bin edges)
        wlo = (xhi - x1) / dx
        whi = (x1 - xlo) / dx

        # Get function values at left and right xedges
        flo = np.zeros(x1.shape)
        fhi = np.zeros(x1.shape)

        for i in range(nbins):

            # Select everything in bin i
            mask = ind == i

            if np.any(mask):

                # Retrieve function values
                flo[mask] = splines[i](y1[mask])
                fhi[mask] = splines[i + 1](y1[mask])

        # Take a weighted average of the function values at left and right
        # bin edges
        fout = wlo * flo + whi * fhi

        # Unflatten fout:
        fout = np.reshape(fout, shape)

        return SimArray(fout, units[2])
コード例 #37
0
def snapshot_gen(ICobj):
    """
    Generates a tipsy snapshot from the initial conditions object ICobj.
    
    Returns snapshot, param
    
        snapshot: tipsy snapshot
        param: dictionary containing info for a .param file
    Note: Code has been edited (dflemin3) such that now it returns a snapshot for a circumbinary disk
    where initial conditions generated assuming star at origin of mass M.  After gas initialized, replaced
    star at origin with binary system who's center of mass lies at the origin and who's mass m1 +m2 = M
    """
    
    print 'Generating snapshot...'
    # Constants
    G = SimArray(1.0,'G')
    # ------------------------------------
    # Load in things from ICobj
    # ------------------------------------
    print 'Accessing data from ICs'
    settings = ICobj.settings
    
    # snapshot file name
    snapshotName = settings.filenames.snapshotName
    paramName = settings.filenames.paramName   
 
    # particle positions
    r = ICobj.pos.r
    xyz = ICobj.pos.xyz
    
    # Number of particles
    nParticles = ICobj.pos.nParticles
    
    # molecular mass
    m = settings.physical.m
    
    # star mass
    m_star = settings.physical.M.copy()
    
    # disk mass
    m_disk = ICobj.sigma.m_disk.copy()
    m_disk = match_units(m_disk, m_star)[0]
    
    # mass of the gas particles
    m_particles = m_disk / float(nParticles)
    
    # re-scale the particles (allows making of low-mass disk)
    m_particles *= settings.snapshot.mScale
    
    # -------------------------------------------------
    # Assign output
    # -------------------------------------------------
    print 'Assigning data to snapshot'
    # Get units all set up
    m_unit = m_star.units
    pos_unit = r.units
    
    if xyz.units != r.units:
        
        xyz.convert_units(pos_unit)
        
    # time units are sqrt(L^3/GM)
    t_unit = np.sqrt((pos_unit**3)*np.power((G*m_unit), -1)).units
    # velocity units are L/t
    v_unit = (pos_unit/t_unit).ratio('km s**-1')
    # Make it a unit, save value for future conversion
    v_unit_vel = v_unit
    #Ensure v_unit_vel is the same as what I assume it is.
    assert(np.fabs(AddBinary.VEL_UNIT-v_unit_vel)<AddBinary.SMALL),"VEL_UNIT not equal to ChaNGa unit! Why??"			
	
    v_unit = pynbody.units.Unit('{0} km s**-1'.format(v_unit))
    
    # Other settings
    metals = settings.snapshot.metals
    star_metals = metals
    
    # Generate snapshot
    # Note that empty pos, vel, and mass arrays are created in the snapshot
    snapshot = pynbody.new(star=1,gas=nParticles)
    snapshot['vel'].units = v_unit
    snapshot['eps'] = 0.01*SimArray(np.ones(nParticles+1, dtype=np.float32), pos_unit)
    snapshot['metals'] = SimArray(np.zeros(nParticles+1, dtype=np.float32))
    snapshot['rho'] = SimArray(np.zeros(nParticles+1, dtype=np.float32))
    
    snapshot.gas['pos'] = xyz
    snapshot.gas['temp'] = ICobj.T(r)
    snapshot.gas['mass'] = m_particles
    snapshot.gas['metals'] = metals
    
    snapshot.star['pos'] = SimArray([[ 0.,  0.,  0.]],pos_unit)
    snapshot.star['vel'] = SimArray([[ 0.,  0.,  0.]], v_unit)
    snapshot.star['mass'] = m_star
    snapshot.star['metals'] = SimArray(star_metals)
    # Estimate the star's softening length as the closest particle distance
    #snapshot.star['eps'] = r.min()
    
    # Make param file
    param = make_param(snapshot, snapshotName)
    param['dMeanMolWeight'] = m
       
    gc.collect()
    
    # CALCULATE VELOCITY USING calc_velocity.py.  This also estimates the 
    # gravitational softening length eps
    print 'Calculating circular velocity'
    preset = settings.changa_run.preset
    max_particles = global_settings['misc']['max_particles']
    calc_velocity.v_xy(snapshot, param, changa_preset=preset, max_particles=max_particles)
    
    gc.collect()
  
	# -------------------------------------------------
    # Estimate time step for changa to use
    # -------------------------------------------------
    # Save param file
    configsave(param, paramName, 'param')
    # Save snapshot
    snapshot.write(filename=snapshotName, fmt=pynbody.tipsy.TipsySnap)
    # est dDelta
    dDelta = ICgen_utils.est_time_step(paramName, preset)
    param['dDelta'] = dDelta
 
	# -------------------------------------------------
    # Create director file
    # -------------------------------------------------
    # largest radius to plot
    r_director = float(0.9 * r.max())
    # Maximum surface density
    sigma_min = float(ICobj.sigma(r_director))
    # surface density at largest radius
    sigma_max = float(ICobj.sigma.input_dict['sigma'].max())
    # Create director dict
    director = make_director(sigma_min, sigma_max, r_director, filename=param['achOutName'])
    ## Save .director file
    #configsave(director, directorName, 'director')

    #Now that velocities and everything are all initialized for gas particles, create new snapshot to return in which
    #single star particle is replaced by 2, same units as above
    snapshotBinary = pynbody.new(star=2,gas=nParticles)
    snapshotBinary['eps'] = 0.01*SimArray(np.ones(nParticles+2, dtype=np.float32), pos_unit)
    snapshotBinary['metals'] = SimArray(np.zeros(nParticles+2, dtype=np.float32))
    snapshotBinary['vel'].units = v_unit
    snapshotBinary['pos'].units = pos_unit
    snapshotBinary['mass'].units = snapshot['mass'].units
    snapshotBinary['rho'] = SimArray(np.zeros(nParticles+2, dtype=np.float32))

    #Assign gas particles with calculated/given values from above
    snapshotBinary.gas['pos'] = snapshot.gas['pos']
    snapshotBinary.gas['vel'] = snapshot.gas['vel']
    snapshotBinary.gas['temp'] = snapshot.gas['temp']
    snapshotBinary.gas['rho'] = snapshot.gas['rho']
    snapshotBinary.gas['eps'] = snapshot.gas['eps']
    snapshotBinary.gas['mass'] = snapshot.gas['mass']
    snapshotBinary.gas['metals'] = snapshot.gas['metals']

    #Load Binary system obj to initialize system
    binsys = ICobj.settings.physical.binsys
    
    x1,x2,v1,v2 = binsys.generateICs()

    #Put velocity in sim units
    #!!! Note: v_unit_vel will always be 29.785598165 km/s when m_unit = Msol and r_unit = 1 AU in kpc!!!
    #conv = v_unit_vel #km/s in sim units
    #v1 /= conv
    #v2 /= conv

    #Assign position, velocity assuming CCW orbit

    snapshotBinary.star[0]['pos'] = SimArray(x1,pos_unit)
    snapshotBinary.star[0]['vel'] = SimArray(v1,v_unit)
    snapshotBinary.star[1]['pos'] = SimArray(x2,pos_unit)
    snapshotBinary.star[1]['vel'] = SimArray(v2,v_unit)

    #Set stellar masses
    #Set Mass units
    #Create simArray for mass, convert units to simulation mass units
    priMass = SimArray(binsys.m1,m_unit)
    secMass = SimArray(binsys.m2,m_unit)

    snapshotBinary.star[0]['mass'] = priMass
    snapshotBinary.star[1]['mass'] = secMass
    snapshotBinary.star['metals'] = SimArray(star_metals)

    #Estimate stars' softening length as fraction of distance to COM
    d = np.sqrt(AddBinary.dotProduct(x1-x2,x1-x2))

    snapshotBinary.star[0]['eps'] = SimArray(math.fabs(d)/4.0,pos_unit)
    snapshotBinary.star[1]['eps'] = SimArray(math.fabs(d)/4.0,pos_unit)
 
    print 'Wrapping up'
    # Now set the star particle's tform to a negative number.  This allows
    # UW ChaNGa treat it as a sink particle.
    snapshotBinary.star['tform'] = -1.0
    
    #Set Sink Radius to be mass-weighted average of Roche lobes of two stars
    r1 = AddBinary.calcRocheLobe(binsys.m1/binsys.m2,binsys.a) 
    r2 = AddBinary.calcRocheLobe(binsys.m2/binsys.m1,binsys.a)
    p = strip_units(binsys.m1/(binsys.m1 + binsys.m2))

    r_sink = (r1*p) + (r2*(1.0-p))
    param['dSinkBoundOrbitRadius'] = r_sink
    param['dSinkRadius'] = r_sink
    param['dSinkMassMin'] = 0.9 * strip_units(secMass)
    param['bDoSinks'] = 1
    
    return snapshotBinary, param, director
コード例 #38
0
def make_director(sigma_min,
                  sigma_max,
                  r,
                  resolution=1200,
                  filename='snapshot'):
    """
    Makes a director dictionary for ChaNGa runs based on the min/max surface
    density, maximum image radius, and image resolution for a gaseous
    protoplanetary disk.  The created dictionary can be saved with
    diskpy.utils.configsave

    The method is to use an example director file (saved as default.director)
    which works for one simulation and scale the various parameters accordingly.
    default.director should have a commented line in it which reads:
        #sigma_max float
    where float is the maximum surface density of the simulation in simulation
    units.

    **ARGUMENTS**

    sigma_min : float
        The surface density that corresponds to 0 density on the image (ie the
        minimum threshold).  Required for setting the dynamic range
    sigma_max : float
        Maximum surface density in the simulation
    r : float
        Maximum radius to plot out to
    resolution : int or float
        Number of pixels in image.  The image is shape (resolution, resolution)
    filename : str
        prefix to use for saving the images.  Example: if filename='snapshot',
        then the outputs will be of form 'snapshot.000000000.ppm'

    **RETURNS**

    director : dict
        A .director dictionary.  Can be saved with diskpy.utils.configsave
    """
    # -----------------------------------------------------------
    # Parse defaults to get scale factor for c
    # -----------------------------------------------------------
    sigma_min, sigma_max, r = strip_units([sigma_min, sigma_max, r])
    defaults = _directordefault
    if '#sigma_max' not in defaults:

        raise KeyError, 'Default .director file should have a line e.g. << #sigma_max 0.01 >>'

    sigma_max0 = defaults['#sigma_max']
    c0 = defaults['colgas'][3]
    n0 = defaults['size'][0]
    r0 = defaults['eye'][2]
    A = (c0 * float(n0)**2) / (sigma_max0 * r0**2)

    # -----------------------------------------------------------
    # Create new director dictionary
    # -----------------------------------------------------------
    director = copy.deepcopy(defaults)
    director.pop('#sigma_max', None)

    logscale_min = sigma_min / sigma_max

    if pynbody.units.has_units(logscale_min):

        logscale_min = float(logscale_min.in_units('1'))

    c = A * float(sigma_max * r**2 / float(resolution)**2)

    director['colgas'][3] = c
    director['size'] = [resolution, resolution]
    director['eye'][2] = r
    director['file'] = filename

    return director
コード例 #39
0
def snapshot_gen(ICobj):
    """
    Generates a tipsy snapshot from the initial conditions object ICobj.
    
    Returns snapshot, param
    
        snapshot: tipsy snapshot
        param: dictionary containing info for a .param file
    Note: Code has been edited (dflemin3) such that now it returns a snapshot for a circumbinary disk
    where initial conditions generated assuming star at origin of mass M.  After gas initialized, replaced
    star at origin with binary system who's center of mass lies at the origin and who's mass m1 +m2 = M
    """
    
    print 'Generating snapshot...'
    # Constants
    G = SimArray(1.0,'G')
    # ------------------------------------
    # Load in things from ICobj
    # ------------------------------------
    print 'Accessing data from ICs'
    settings = ICobj.settings
    
    # snapshot file name
    snapshotName = settings.filenames.snapshotName
    paramName = settings.filenames.paramName   
 
    # particle positions
    r = ICobj.pos.r
    xyz = ICobj.pos.xyz
    
    # Number of particles
    nParticles = ICobj.pos.nParticles
    
    # molecular mass
    m = settings.physical.m
    
    # star mass
    m_star = settings.physical.M.copy()
    
    # disk mass
    m_disk = ICobj.sigma.m_disk.copy()
    m_disk = match_units(m_disk, m_star)[0]
    
    # mass of the gas particles
    m_particles = m_disk / float(nParticles)
    
    # re-scale the particles (allows making of low-mass disk)
    m_particles *= settings.snapshot.mScale
    
    # -------------------------------------------------
    # Assign output
    # -------------------------------------------------
    print 'Assigning data to snapshot'
    # Get units all set up
    m_unit = m_star.units
    pos_unit = r.units
    
    if xyz.units != r.units:
        
        xyz.convert_units(pos_unit)
        
    # time units are sqrt(L^3/GM)
    t_unit = np.sqrt((pos_unit**3)*np.power((G*m_unit), -1)).units
    # velocity units are L/t
    v_unit = (pos_unit/t_unit).ratio('km s**-1')
    # Make it a unit, save value for future conversion
    v_unit_vel = v_unit
    #Ensure v_unit_vel is the same as what I assume it is.
    assert(np.fabs(AddBinary.VEL_UNIT-v_unit_vel)<AddBinary.SMALL),"VEL_UNIT not equal to ChaNGa unit! Why??"			
	
    v_unit = pynbody.units.Unit('{0} km s**-1'.format(v_unit))
    
    # Other settings
    metals = settings.snapshot.metals
    star_metals = metals
    
    # Generate snapshot
    # Note that empty pos, vel, and mass arrays are created in the snapshot
    snapshot = pynbody.new(star=1,gas=nParticles)
    snapshot['vel'].units = v_unit
    snapshot['eps'] = 0.01*SimArray(np.ones(nParticles+1, dtype=np.float32), pos_unit)
    snapshot['metals'] = SimArray(np.zeros(nParticles+1, dtype=np.float32))
    snapshot['rho'] = SimArray(np.zeros(nParticles+1, dtype=np.float32))
    
    snapshot.gas['pos'] = xyz
    snapshot.gas['temp'] = ICobj.T(r)
    snapshot.gas['mass'] = m_particles
    snapshot.gas['metals'] = metals
    
    snapshot.star['pos'] = SimArray([[ 0.,  0.,  0.]],pos_unit)
    snapshot.star['vel'] = SimArray([[ 0.,  0.,  0.]], v_unit)
    snapshot.star['mass'] = m_star
    snapshot.star['metals'] = SimArray(star_metals)
    # Estimate the star's softening length as the closest particle distance
    #snapshot.star['eps'] = r.min()
    
    # Make param file
    param = make_param(snapshot, snapshotName)
    param['dMeanMolWeight'] = m
       
    gc.collect()
    
    # CALCULATE VELOCITY USING calc_velocity.py.  This also estimates the 
    # gravitational softening length eps
    print 'Calculating circular velocity'
    preset = settings.changa_run.preset
    max_particles = global_settings['misc']['max_particles']
    calc_velocity.v_xy(snapshot, param, changa_preset=preset, max_particles=max_particles)
    
    gc.collect()
  
	# -------------------------------------------------
    # Estimate time step for changa to use
    # -------------------------------------------------
    # Save param file
    configsave(param, paramName, 'param')
    # Save snapshot
    snapshot.write(filename=snapshotName, fmt=pynbody.tipsy.TipsySnap)
    # est dDelta
    dDelta = ICgen_utils.est_time_step(paramName, preset)
    param['dDelta'] = dDelta
 
	# -------------------------------------------------
    # Create director file
    # -------------------------------------------------
    # largest radius to plot
    r_director = float(0.9 * r.max())
    # Maximum surface density
    sigma_min = float(ICobj.sigma(r_director))
    # surface density at largest radius
    sigma_max = float(ICobj.sigma.input_dict['sigma'].max())
    # Create director dict
    director = make_director(sigma_min, sigma_max, r_director, filename=param['achOutName'])
    ## Save .director file
    #configsave(director, directorName, 'director')

    #Now that velocities and everything are all initialized for gas particles, create new snapshot to return in which
    #single star particle is replaced by 2, same units as above
    snapshotBinary = pynbody.new(star=2,gas=nParticles)
    snapshotBinary['eps'] = 0.01*SimArray(np.ones(nParticles+2, dtype=np.float32), pos_unit)
    snapshotBinary['metals'] = SimArray(np.zeros(nParticles+2, dtype=np.float32))
    snapshotBinary['vel'].units = v_unit
    snapshotBinary['pos'].units = pos_unit
    snapshotBinary['mass'].units = snapshot['mass'].units
    snapshotBinary['rho'] = SimArray(np.zeros(nParticles+2, dtype=np.float32))

    #Assign gas particles with calculated/given values from above
    snapshotBinary.gas['pos'] = snapshot.gas['pos']
    snapshotBinary.gas['vel'] = snapshot.gas['vel']
    snapshotBinary.gas['temp'] = snapshot.gas['temp']
    snapshotBinary.gas['rho'] = snapshot.gas['rho']
    snapshotBinary.gas['eps'] = snapshot.gas['eps']
    snapshotBinary.gas['mass'] = snapshot.gas['mass']
    snapshotBinary.gas['metals'] = snapshot.gas['metals']

    #Load Binary system obj to initialize system
    binsys = ICobj.settings.physical.binsys
    
    x1,x2,v1,v2 = binsys.generateICs()

    #Put velocity in sim units
    #!!! Note: v_unit_vel will always be 29.785598165 km/s when m_unit = Msol and r_unit = 1 AU in kpc!!!
    #conv = v_unit_vel #km/s in sim units
    #v1 /= conv
    #v2 /= conv

    #Assign position, velocity assuming CCW orbit

    snapshotBinary.star[0]['pos'] = SimArray(x1,pos_unit)
    snapshotBinary.star[0]['vel'] = SimArray(v1,v_unit)
    snapshotBinary.star[1]['pos'] = SimArray(x2,pos_unit)
    snapshotBinary.star[1]['vel'] = SimArray(v2,v_unit)

    #Set stellar masses
    #Set Mass units
    #Create simArray for mass, convert units to simulation mass units
    priMass = SimArray(binsys.m1,m_unit)
    secMass = SimArray(binsys.m2,m_unit)

    snapshotBinary.star[0]['mass'] = priMass
    snapshotBinary.star[1]['mass'] = secMass
    snapshotBinary.star['metals'] = SimArray(star_metals)

    #Estimate stars' softening length as fraction of distance to COM
    d = np.sqrt(AddBinary.dotProduct(x1-x2,x1-x2))

    snapshotBinary.star[0]['eps'] = SimArray(math.fabs(d)/4.0,pos_unit)
    snapshotBinary.star[1]['eps'] = SimArray(math.fabs(d)/4.0,pos_unit)
 
    print 'Wrapping up'
    # Now set the star particle's tform to a negative number.  This allows
    # UW ChaNGa treat it as a sink particle.
    snapshotBinary.star['tform'] = -1.0
    
    #Set Sink Radius to be mass-weighted average of Roche lobes of two stars
    r1 = AddBinary.calcRocheLobe(binsys.m1/binsys.m2,binsys.a) 
    r2 = AddBinary.calcRocheLobe(binsys.m2/binsys.m1,binsys.a)
    p = strip_units(binsys.m1/(binsys.m1 + binsys.m2))

    r_sink = (r1*p) + (r2*(1.0-p))
    param['dSinkBoundOrbitRadius'] = r_sink
    param['dSinkRadius'] = r_sink
    param['dSinkMassMin'] = 0.9 * strip_units(secMass)
    param['bDoSinks'] = 1
    
    return snapshotBinary, param, director