コード例 #1
0
ファイル: make_sigma.py プロジェクト: trquinn/ICgen
    def _make_sigma(self, settings, sigma_input=None):
        """
        Generates the surface density as a function of r, a callable object 
        sigma(r) and assigns it to self.sigma
        
        The method used is determined by kind = settings.sigma.kind
        
        kind = 'file':
            Generates a spline interpolation of sigma vs r from the file
            defined by settings.filenames.sigmaFileName.  Returns sigma vs r as
            an cubic spline interpolation object
            (see scipy.interpolation.interp1d)
            
            sigma_input should be a pickled dictionary with the entries:
            'sigma': <sigma evaluated at r>
            'r':     <r for the bins>
            
            If the input sigma has units, sigma vs r will be returned in units
            of Msol/au^2
        """
        kind = settings.sigma.kind
        self.kind = kind

        if kind == "file":

            inDict = sigma_input.copy()
            # Save the input dictionary in self
            self.input_dict = inDict

            sigmaBinned = inDict["sigma"]
            r_bins = inDict["r"]

            # Convert to default units of Msol/au^2.  If no units, assign default
            sigmaBinned = isaac.match_units(sigmaBinned, "Msol au**-2")[0]
            # Convert r_bins to default units of 'au'
            r_bins = isaac.match_units(r_bins, "au")[0]
            # Calculate spline interpolation
            print "Calculating spline interpolation (slow for many data points)"
            sigspline = interp1d(r_bins, sigmaBinned, kind="cubic", fill_value=0.0, bounds_error=False)

            def sigout(r):
                """
                Linear spline interpolation of sigma(r).  
                
                ARGUMENTS:
                
                r - can be scalar, numpy array, or sim array
                
                RETURNS: 
                
                sigma (surface density) evaluated at r
                """

                # Try to convert r to the units used to make sigspline ('au')
                r = isaac.match_units(r, "au")[0]

                return SimArray(sigspline(r), "Msol au**-2")

            self.sigma = sigout
            self.r_bins = r_bins
コード例 #2
0
ファイル: ICgen.py プロジェクト: trquinn/ICgen
def Qest(ICobj, r=None):
    """
    Estimate Toomre Q at r (optional) for ICs, assuming omega=epicyclic
    frequency.  Ignores disk self-gravity
    """
    if not hasattr(ICobj, 'sigma'):

        raise ValueError, 'Could not find surface density profile (sigma)'

    G = SimArray(1.0, 'G')
    kB = SimArray(1.0, 'k')

    if r is None:

        r = ICobj.sigma.r_bins

    sigma = ICobj.sigma(r)
    T = ICobj.T(r)
    M = ICobj.settings.physical.M
    m = ICobj.settings.physical.m
    M = isaac.match_units(M, 'Msol')[0]
    m = isaac.match_units(m, 'm_p')[0]

    Q = np.sqrt(M * kB * T / (G * m * r**3)) / (np.pi * sigma)
    Q.convert_units('1')

    return Q
コード例 #3
0
ファイル: ICgen.py プロジェクト: trquinn/ICgen
def Qest(ICobj, r=None):
    """
    Estimate Toomre Q at r (optional) for ICs, assuming omega=epicyclic
    frequency.  Ignores disk self-gravity
    """
    if not hasattr(ICobj, 'sigma'):
        
        raise ValueError, 'Could not find surface density profile (sigma)'
        
    G = SimArray(1.0, 'G')
    kB = SimArray(1.0, 'k')
    
    if r is None:
        
        r = ICobj.sigma.r_bins
        
    sigma = ICobj.sigma(r)
    T = ICobj.T(r)
    M = ICobj.settings.physical.M
    m = ICobj.settings.physical.m
    M = isaac.match_units(M, 'Msol')[0]
    m = isaac.match_units(m, 'm_p')[0]
    
    Q = np.sqrt(M*kB*T/(G*m*r**3))/(np.pi*sigma)
    Q.convert_units('1')
    
    return Q
コード例 #4
0
 def rho(self,z,r):
     """
     A Callable method that works like a spline but handles units.
     
     returns rho(z,r), an N-D array evaluated over the N-D arrays z, r
     """
     
     # Fix up units
     zunit = self.z_bins.units
     runit = self.r_bins.units
     rho_unit = self.rho_binned.units
     
     z = isaac.match_units(z, zunit)[0]
     r = isaac.match_units(r, runit)[0]
     
     if not hasattr(z, '__iter__'):
         
         rho_out = SimArray(self._rho_spline(z,r), rho_unit)
         
     else:
         
         rho_out = np.zeros(z.shape)
         iterator = np.nditer([z,r], flags=['multi_index'])
         
         while not iterator.finished:
             
             z_val, r_val = iterator.value
             ind = iterator.multi_index
             rho_out[ind] = self._rho_spline(z_val, r_val)
             iterator.iternext()
             
         rho_out = SimArray(rho_out, rho_unit)                
                     
     return rho_out
コード例 #5
0
ファイル: calc_temp.py プロジェクト: dflemin3/ICgen
 def __call__(self, r):
     
     # Load settings
     params = self._parent.settings.physical
     T0 = params.T0
     Tpower = params.Tpower
     r0 = params.r0
     Tmin = params.Tmin
     # Calculate T(r)
     r = isaac.match_units(r, r0)[0]
     a = (r/r0)
     a = isaac.match_units(a, '1')[0]
     Tout = T0 * np.power(a, Tpower)
     Tout[Tout < Tmin] = Tmin
     
     return Tout
コード例 #6
0
ファイル: make_sigma.py プロジェクト: dflemin3/ICgen
 def _make_sigma(self, r_bins, sigmaBinned):
     """
     Generates the surface density as a function of r, a callable object 
     sigma(r) and assigns it to self.sigma
     
     Generates a spline interpolation of sigma vs r from the file
     defined by settings.filenames.sigmaFileName.  Returns sigma vs r as
     an cubic spline interpolation object
     (see scipy.interpolation.interp1d)
     
     sigma_input should be a pickled dictionary with the entries:
     'sigma': <sigma evaluated at r>
     'r':     <r for the bins>
     
     If the input sigma has units, sigma vs r will be returned in units
     of Msol/au^2
     """       
     # Convert to default units of Msol/au^2.  If no units, assign default
     sigmaBinned = isaac.match_units(sigmaBinned, 'Msol au**-2')[0]
     # Convert r_bins to default units of 'au'
     r_bins = isaac.match_units(r_bins, 'au')[0]
     # Calculate spline interpolation
     print 'Calculating spline interpolation (slow for many data points)'
     sigspline = interp1d(r_bins,sigmaBinned,kind='cubic',fill_value=0.0,\
     bounds_error=False)
     
     def sigout(r):
         """
         Linear spline interpolation of sigma(r).  
         
         ARGUMENTS:
         
         r - can be scalar, numpy array, or sim array
         
         RETURNS: 
         
         sigma (surface density) evaluated at r
         """
         
         # Try to convert r to the units used to make sigspline ('au')
         r = isaac.match_units(r, 'au')[0]
         
         return SimArray(sigspline(r), 'Msol au**-2')
     
     self.sigma = sigout
     self.r_bins = r_bins
コード例 #7
0
    def _make_sigma(self, r_bins, sigmaBinned):
        """
        Generates the surface density as a function of r, a callable object 
        sigma(r) and assigns it to self.sigma
        
        Generates a spline interpolation of sigma vs r from the file
        defined by settings.filenames.sigmaFileName.  Returns sigma vs r as
        an cubic spline interpolation object
        (see scipy.interpolation.interp1d)
        
        sigma_input should be a pickled dictionary with the entries:
        'sigma': <sigma evaluated at r>
        'r':     <r for the bins>
        
        If the input sigma has units, sigma vs r will be returned in units
        of Msol/au^2
        """
        # Convert to default units of Msol/au^2.  If no units, assign default
        sigmaBinned = isaac.match_units(sigmaBinned, 'Msol au**-2')[0]
        # Convert r_bins to default units of 'au'
        r_bins = isaac.match_units(r_bins, 'au')[0]
        # Calculate spline interpolation
        print 'Calculating spline interpolation (slow for many data points)'
        sigspline = interp1d(r_bins,sigmaBinned,kind='cubic',fill_value=0.0,\
        bounds_error=False)

        def sigout(r):
            """
            Linear spline interpolation of sigma(r).  
            
            ARGUMENTS:
            
            r - can be scalar, numpy array, or sim array
            
            RETURNS: 
            
            sigma (surface density) evaluated at r
            """

            # Try to convert r to the units used to make sigspline ('au')
            r = isaac.match_units(r, 'au')[0]

            return SimArray(sigspline(r), 'Msol au**-2')

        self.sigma = sigout
        self.r_bins = r_bins
コード例 #8
0
ファイル: calc_temp.py プロジェクト: trquinn/ICgen
    def __call__(self, r):

        # Load settings
        params = self._parent.settings.physical

        if not hasattr(params, 'kind'):
            # Add this check for backwards compatibility.  Previous versions
            # only had one kind of temperature profile
            params.kind = 'powerlaw'

        T0 = params.T0
        Tmin = params.Tmin
        r0 = params.r0
        kind = params.kind

        # Calculate T(r)
        r = isaac.match_units(r, r0)[0]
        a = (r / r0)
        a = isaac.match_units(a, '1')[0]

        # Powerlaw temperature (default)
        if kind == 'powerlaw':

            Tpower = params.Tpower
            Tout = T0 * np.power(a, Tpower)
            Tout[Tout < Tmin] = Tmin

        # MQWS temperature profile
        elif (kind == 'mqws') | (kind == 'MQWS'):

            # NOTE: I'm not sure how exactly they generate the temperature
            # profile.  The quoted equation doesn't match their figures
            Tout = T0 * np.exp(-3 * a / 2) + Tmin

        else:

            raise TypeError, 'Could not find temperature kind {0}'.format(kind)

        if hasattr(params, 'Tmax'):
            Tmax = params.Tmax
            Tout[Tout > Tmax] = Tmax

        return Tout
コード例 #9
0
ファイル: calc_temp.py プロジェクト: trquinn/ICgen
    def __call__(self, r):

        # Load settings
        params = self._parent.settings.physical

        if not hasattr(params, "kind"):
            # Add this check for backwards compatibility.  Previous versions
            # only had one kind of temperature profile
            params.kind = "powerlaw"

        T0 = params.T0
        Tmin = params.Tmin
        r0 = params.r0
        kind = params.kind

        # Calculate T(r)
        r = isaac.match_units(r, r0)[0]
        a = r / r0
        a = isaac.match_units(a, "1")[0]

        # Powerlaw temperature (default)
        if kind == "powerlaw":

            Tpower = params.Tpower
            Tout = T0 * np.power(a, Tpower)
            Tout[Tout < Tmin] = Tmin

        # MQWS temperature profile
        elif (kind == "mqws") | (kind == "MQWS"):

            # NOTE: I'm not sure how exactly they generate the temperature
            # profile.  The quoted equation doesn't match their figures
            Tout = T0 * np.exp(-3 * a / 2) + Tmin

        else:

            raise TypeError, "Could not find temperature kind {0}".format(kind)

        if hasattr(params, "Tmax"):
            Tmax = params.Tmax
            Tout[Tout > Tmax] = Tmax

        return Tout
コード例 #10
0
    def cdf_inv(self, m, r):
        """
        A callable interface for the inverse CDF.
        
        cdf_inv(m,r) returns z at a given r for 0 < m <1
        
        IF m and r are the same length, the CDF_inv is calculated over the
        pairs m(i), r(i).
        
        IF one argument is a single point and the other is an array, the value
        of the single point is used for every evaluation.  eg:
            r = SimArray(np.linspace(0, 20, 100), 'au')
            m = 0.5
            
            cdf_vals = cdf_inv(m, r) # Returns z at cdf = 0.5 for all r
            
        """

        # Make them iterable if they are floats/0D arrays
        if not hasattr(m, '__iter__'): m = np.array(m).reshape(1)
        if not hasattr(r, '__iter__'): r = np.array(r).reshape(1)
        # Check to see if one of the arrays is longer than the other.  IF so,
        # assume that one is length one
        if np.prod(m.shape) > np.prod(r.shape):

            r = r * np.ones(m.shape)

        elif np.prod(m.shape) < np.prod(r.shape):

            m = m * np.ones(r.shape)

        # Check units
        runit = self.r_bins.units
        zunit = self.z_bins.units
        r = isaac.match_units(r, runit)[0]

        # Initialize
        n_pts = len(r)
        z_out = SimArray(np.zeros([len(r)]), zunit)
        dr = self.r_bins[[1]] - self.r_bins[[0]]
        r_indices = np.digitize(r, self.r_bins)
        # Ignore values outside of the r range
        mask = (r >= self.r_bins.min()) & (r < self.r_bins.max())
        z_ind = np.arange(n_pts)

        # Now calculate the values of z_out
        for i, j in zip(z_ind[mask], r_indices[mask]):

            z_lo = self._cdf_inv[j - 1](m[i])
            z_hi = self._cdf_inv[j](m[i])
            z_out[i] = z_lo + (
                (z_hi - z_lo) / dr) * (r[[i]] - self.r_bins[[j - 1]])

        return z_out
コード例 #11
0
 def drho_dr(self, z, r):
     """
     Radial derivative of rho.  A callable method that works like a spline
     but handles units.
     
     USAGE:
     
     drho_dr(z,r) returns the radial derivative of rho at z, r
     """
     
     # Set-up units
     zunit = self.z_bins.units
     runit = self.r_bins.units
     rho_unit = self.rho_binned.units
     drho_unit = rho_unit/runit
     
     # Put z, r in the correct units
     z = isaac.match_units(z, zunit)[0]
     r = isaac.match_units(r, runit)[0]
     
     # Iterate over drho        
     if not hasattr(z, '__iter__'):
         
         drho = self._drho_dr(z,r)
         
     else:
         
         drho = np.zeros(z.shape)
         iterator = np.nditer([z,r], flags=['multi_index'])
         
         while not iterator.finished:
             
             z_val, r_val = iterator.value
             ind = iterator.multi_index
             drho[ind] = self._drho_dr(z_val, r_val)
             iterator.iternext()
                     
     # Fix up units
     drho = isaac.match_units(drho, drho_unit)[0]
     
     return drho
コード例 #12
0
ファイル: calc_temp.py プロジェクト: trquinn/ICgen
 def __call__(self, r):
     
     # Load settings
     params = self._parent.settings.physical
     T0 = params.T0
     Tpower = params.Tpower
     r0 = params.r0
     Tmin = params.Tmin
     
     if hasattr(params, 'Tmax'):
         Tmax = params.Tmax
     # Calculate T(r)
     r = isaac.match_units(r, r0)[0]
     a = (r/r0)
     a = isaac.match_units(a, '1')[0]
     Tout = T0 * np.power(a, Tpower)
     Tout[Tout < Tmin] = Tmin
     if hasattr(params, 'Tmax'):
         Tout[Tout > Tmax] = Tmax
     
     return Tout
コード例 #13
0
ファイル: make_sigma.py プロジェクト: trquinn/ICgen
            def pdf_fcn(r_in):
                """
                Normalized cubic spline interpolation of the PDF(r) from sigma(r).
                The PDF is just calculated as 2*pi*r*sigma(r).
                
                ARGUMENTS:
                
                r_in - radii at which to calculate the PDF
                
                RETURNS:
                
                probability density function from sigma(r) evaluated at r_in
                """
                # Put r_in into the units used in generating the pdf
                r_in = isaac.match_units(r_in, self.r_bins)[0]
                # Evaluate the pdf at r_in
                pdf_vals = pdfSpline(r_in)
                # Put the pdf into units of r_in.units**-1
                pdf_vals = isaac.match_units(pdf_vals, 1 / r_in)[0]

                return pdf_vals
コード例 #14
0
ファイル: make_sigma.py プロジェクト: trquinn/ICgen
            def pdf_fcn(r_in):
                """
                Normalized cubic spline interpolation of the PDF(r) from sigma(r).
                The PDF is just calculated as 2*pi*r*sigma(r).
                
                ARGUMENTS:
                
                r_in - radii at which to calculate the PDF
                
                RETURNS:
                
                probability density function from sigma(r) evaluated at r_in
                """
                # Put r_in into the units used in generating the pdf
                r_in = isaac.match_units(r_in, self.r_bins)[0]
                # Evaluate the pdf at r_in
                pdf_vals = pdfSpline(r_in)
                # Put the pdf into units of r_in.units**-1
                pdf_vals = isaac.match_units(pdf_vals, 1 / r_in)[0]

                return pdf_vals
コード例 #15
0
ファイル: pos_class.py プロジェクト: trquinn/ICgen
 def _cartesian_pos(self):
     """
     Generate x,y
     """
     
     r = self.r
     z = self.z
     theta = self.theta
     x = r*np.cos(theta)
     y = r*np.sin(theta)
     
     xyz = np.zeros([self.nParticles, 3])
     xyz = isaac.match_units(xyz, r)[0]
     
     xyz[:,0] = x
     xyz[:,1] = y
     xyz[:,2] = isaac.match_units(z, r)[0]
     
     self.x = x
     self.y = y
     self.xyz = xyz
コード例 #16
0
ファイル: calc_rho_zr.py プロジェクト: dflemin3/ICgen
 def cdf_inv(self,m,r):
     """
     A callable interface for the inverse CDF.
     
     cdf_inv(m,r) returns z at a given r for 0 < m <1
     
     IF m and r are the same length, the CDF_inv is calculated over the
     pairs m(i), r(i).
     
     IF one argument is a single point and the other is an array, the value
     of the single point is used for every evaluation.  eg:
         r = SimArray(np.linspace(0, 20, 100), 'au')
         m = 0.5
         
         cdf_vals = cdf_inv(m, r) # Returns z at cdf = 0.5 for all r
         
     """
     
     # Make them iterable if they are floats/0D arrays
     if not hasattr(m, '__iter__'): m = np.array(m).reshape(1)
     if not hasattr(r, '__iter__'): r = np.array(r).reshape(1)
     # Check to see if one of the arrays is longer than the other.  IF so,
     # assume that one is length one
     if np.prod(m.shape) > np.prod(r.shape):
         
         r = r*np.ones(m.shape)
         
     elif np.prod(m.shape) < np.prod(r.shape):
         
         m = m*np.ones(r.shape)
     
     # Check units
     runit = self.r_bins.units
     zunit = self.z_bins.units
     r = isaac.match_units(r, runit)[0]
         
     # Initialize
     n_pts = len(r)
     z_out = SimArray(np.zeros([len(r)]), zunit)
     dr = self.r_bins[[1]] - self.r_bins[[0]]
     r_indices = np.digitize(r, self.r_bins)
     # Ignore values outside of the r range
     mask = (r >= self.r_bins.min()) & (r < self.r_bins.max())
     z_ind = np.arange(n_pts)
     
     # Now calculate the values of z_out
     for i,j in zip(z_ind[mask], r_indices[mask]):
         
         z_lo = self._cdf_inv[j-1](m[i])
         z_hi = self._cdf_inv[j](m[i])
         z_out[i] = z_lo + ((z_hi-z_lo)/dr)*(r[[i]] - self.r_bins[[j-1]])
         
     return z_out
コード例 #17
0
    def _disk_mass(self):
        """
        Calculate the total disk mass by integrating sigma
        """
        # Assign variables
        r = self.r_bins
        sig = self.sigma(r)
        # Now integrate
        m_disk = simps(2 * np.pi * r * sig, r)
        m_units = sig.units * (r.units)**2
        m_disk = isaac.match_units(m_disk, m_units)[0]

        self.m_disk = m_disk
コード例 #18
0
ファイル: make_sigma.py プロジェクト: dflemin3/ICgen
 def _disk_mass(self):
     """
     Calculate the total disk mass by integrating sigma
     """
     # Assign variables
     r = self.r_bins
     sig = self.sigma(r)
     # Now integrate
     m_disk = simps(2*np.pi*r*sig, r)
     m_units = sig.units * (r.units)**2
     m_disk = isaac.match_units(m_disk, m_units)[0]
     
     self.m_disk = m_disk
コード例 #19
0
ファイル: make_sigma.py プロジェクト: trquinn/ICgen
            def sigout(r):
                """
                Linear spline interpolation of sigma(r).  
                
                ARGUMENTS:
                
                r - can be scalar, numpy array, or sim array
                
                RETURNS: 
                
                sigma (surface density) evaluated at r
                """

                # Try to convert r to the units used to make sigspline ('au')
                r = isaac.match_units(r, 'au')[0]

                return SimArray(sigspline(r), 'Msol au**-2')
コード例 #20
0
ファイル: make_sigma.py プロジェクト: trquinn/ICgen
            def sigout(r):
                """
                Linear spline interpolation of sigma(r).  
                
                ARGUMENTS:
                
                r - can be scalar, numpy array, or sim array
                
                RETURNS: 
                
                sigma (surface density) evaluated at r
                """

                # Try to convert r to the units used to make sigspline ('au')
                r = isaac.match_units(r, "au")[0]

                return SimArray(sigspline(r), "Msol au**-2")
コード例 #21
0
ファイル: make_sigma.py プロジェクト: trquinn/ICgen
            def finv_fcn(m_in):
                """
                The inverse CDF for sigma(r).
                
                input:
                
                0 <= m_in < 1
                
                returns:
                
                r (radius), the inverse CDF evaluated at m_in
                
                Uses a linear spline interpolation.
                """

                r_out = finv(m_in)
                r_out = isaac.match_units(r_out, r)[0]
                return r_out
コード例 #22
0
ファイル: make_sigma.py プロジェクト: trquinn/ICgen
            def finv_fcn(m_in):
                """
                The inverse CDF for sigma(r).
                
                input:
                
                0 <= m_in < 1
                
                returns:
                
                r (radius), the inverse CDF evaluated at m_in
                
                Uses a linear spline interpolation.
                """

                r_out = finv(m_in)
                r_out = isaac.match_units(r_out, r)[0]
                return r_out
コード例 #23
0
ファイル: make_snapshot.py プロジェクト: trquinn/ICgen
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 = isaac.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 = isaac.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
    isaac.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 = isaac.make_director(sigma_min, sigma_max, r_director, filename=param['achOutName'])
    ## Save .director file
    #isaac.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 = isaac.strip_units(r.min())
    param['dSinkBoundOrbitRadius'] = r_sink
    param['dSinkRadius'] = r_sink
    param['dSinkMassMin'] = 0.9 * isaac.strip_units(m_star)
    param['bDoSinks'] = 1
    
    return snapshot, param, director
コード例 #24
0
ファイル: calc_velocity.py プロジェクト: dflemin3/ICgen
def v_xy(snapshot, param, changbin=None):
    """
    Attempts to calculate the circular velocities for particles in a thin
    (not flat) keplerian disk.  Requires ChaNGa
    
    ARGUMENTS:
    
    snapshot:   a tipsy snapshot for a gaseous disk
    param:      a dictionary containing params for changa.
                (see isaac.configparser)
    changbin:   (OPTIONAL)  If set, should be the full path to the ChaNGa
                executable.  If None, an attempt to find ChaNGa is made
    """
    
    if changbin is None:
        # Try to find the ChaNGa binary full path
        changbin = os.popen('which ChaNGa').read().strip()
    # --------------------------------------------
    # Initialize
    # --------------------------------------------
    # Load things from snapshot
    x = snapshot.g['x']
    y = snapshot.g['y']
    z = snapshot.g['z']
    r = snapshot.g['rxy']
    v_initial = snapshot.g['vel'].copy()
    
    # Temporary filenames for running ChaNGa
    f_prefix = str(np.random.randint(0, 2**32))
    f_name = f_prefix + '.std'
    p_name = f_prefix + '.param'
    
    # Update parameters
    p_temp = param.copy()
    p_temp['achInFile'] = f_name
    p_temp['achOutName'] = f_prefix
    if 'dDumpFrameTime' in p_temp: p_temp.pop('dDumpFrameTime')
    if 'dDumpFrameStep' in p_temp: p_temp.pop('dDumpFrameStep')
    
    # --------------------------------------------
    # Estimate velocity from gravity only
    # --------------------------------------------
    # Save files
    snapshot.write(filename=f_name, fmt = pynbody.tipsy.TipsySnap)
    isaac.configsave(p_temp, p_name, ftype='param')
    
    # Run ChaNGa, only calculating gravity
    command = 'charmrun ++local ' + changbin + ' -gas -n 0 ' + p_name
    
    p = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
    
    while p.poll() is None:
        
        time.sleep(0.1)
        
    # Load accelerations
    acc_name = f_prefix + '.000000.acc2'
    a = isaac.load_acc(acc_name)
    
    # Calculate radial acceleration
    a_r = a[:,0]*x/r + a[:,1]*y/r
    
    # circular velocity
    v = np.sqrt(abs(r*a_r))
    
    # Assign
    snapshot.g['vel'][:,0] = -v*y/r
    snapshot.g['vel'][:,1] = v*x/r
    
    # --------------------------------------------
    # Estimate velocity from gravity & sph (assuming bDoGas=1 in param)
    # --------------------------------------------
    # Write file
    snapshot.write(filename=f_name, fmt = pynbody.tipsy.TipsySnap)
    
    # Run ChaNGa, only calculating gravity
    changbin = os.popen('which ChaNGa').read().strip()
    #command = 'charmrun ++local ' + changbin + ' +gas -n 0 ' + p_name
    command = 'charmrun ++local ' + changbin + ' -n 0 ' + p_name
    
    p = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
    
    while p.poll() is None:
        
        time.sleep(0.1)
        
    # Load accelerations
    acc_name = f_prefix + '.000000.acc2'
    a = isaac.load_acc(acc_name)
    
    # Calculate radial acceleration
    a_r = a[:,0]*x/r + a[:,1]*y/r
    
    # circular velocity
    v = np.sqrt(abs(r*a_r))
    
    logv = np.log(v)
    logr = np.log(r)
    
    logr_bins, logv_mean, err = isaac.binned_mean(logr, logv, 50, \
    weighted_bins=True)
    
    logv_spline = isaac.extrap1d(logr_bins, logv_mean)
    
    v_calc = np.exp(logv_spline(logr))
    v_calc = isaac.match_units(v_calc, v_initial.units)[0]
    v_out = v_initial * 0.0
    v_out[:,0] = -v_calc * y/r
    v_out[:,1] = v_calc * x/r
    
    # Clean-up
    for fname in glob.glob(f_prefix + '*'): os.remove(fname)
    
    # Re-assign velocity to snapshot
    snapshot.g['vel'] = v_initial
    
    return v_out
コード例 #25
0
ファイル: make_snapshotBinary.py プロジェクト: ibackus/ICgen
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 = isaac.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 = isaac.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
    isaac.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 = isaac.make_director(sigma_min,
                                   sigma_max,
                                   r_director,
                                   filename=param['achOutName'])
    ## Save .director file
    #isaac.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 = isaac.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 * isaac.strip_units(secMass)
    param['bDoSinks'] = 1

    return snapshotBinary, param, director
コード例 #26
0
 def cdf_inv(self,m,r):
     """
     A callable interface for the inverse CDF.
     
     cdf_inv(m,r) returns z at a given r for 0 < m <1
     
     IF m and r are the same length, the CDF_inv is calculated over the
     pairs m(i), r(i).
     
     IF one argument is a single point and the other is an array, the value
     of the single point is used for every evaluation.  eg:
         r = SimArray(np.linspace(0, 20, 100), 'au')
         m = 0.5
         
         cdf_vals = cdf_inv(m, r) # Returns z at cdf = 0.5 for all r
         
     """
     
     # Make them iterable if they are floats/0D arrays
     if not hasattr(m, '__iter__'): m = np.array(m).reshape(1)
     if not hasattr(r, '__iter__'): r = np.array(r).reshape(1)
     # Check to see if one of the arrays is longer than the other.  IF so,
     # assume that one is length one
     if np.prod(m.shape) > np.prod(r.shape):
         
         r = r*np.ones(m.shape)
         
     elif np.prod(m.shape) < np.prod(r.shape):
         
         m = m*np.ones(r.shape)
     
     # Check units
     runit = self.r_bins.units
     zunit = self.z_bins.units
     r = isaac.match_units(r, runit)[0]
         
     # Initialize
     n_pts = len(r)
     z_out = SimArray(np.zeros([len(r)]), zunit)
     dr = self.r_bins[[1]] - self.r_bins[[0]]
     r_indices = np.digitize(r, self.r_bins)
     # Ignore values outside of the r range
     mask = (r >= self.r_bins.min()) & (r < self.r_bins.max())
     z = z_out[mask]
     r = r[mask]
     r_indices = r_indices[mask]
     m = m[mask]
     
     # Loop through all used radial bins
     used_indices = set(r_indices)        
     for i in used_indices:
         
         # Look at all particles in radial bin i
         mask2 = (r_indices == i)
         # Calculate z at the bin edges
         z_lo = self._cdf_inv[i-1](m[mask2])
         z_hi = self._cdf_inv[i](m[mask2])
         # Linearly interpolate z from bin edges
         z[mask2] = z_lo + ((z_hi-z_lo)/dr) * (r[mask2] - self.r_bins[[i-1]])
         
     # Assign z for all particles within the bin range
     z_out[mask] = z
                 
     return z_out
コード例 #27
0
ファイル: make_snapshot.py プロジェクト: trquinn/ICgen
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
    """

    # Constants
    G = SimArray(1.0, 'G')
    kB = SimArray(1.0, 'k')
    # ------------------------------------
    # Load in things from ICobj
    # ------------------------------------
    # snapshot file name
    snapshotName = ICobj.settings.filenames.snapshotName
    # particle positions
    theta = ICobj.pos.theta
    r = ICobj.pos.r
    x = ICobj.pos.x
    y = ICobj.pos.y
    z = ICobj.pos.z
    # Number of particles
    nParticles = ICobj.pos.nParticles
    # Temperature power law (used for pressure gradient)
    Tpower = ICobj.settings.physical.Tpower
    # molecular mass
    m = ICobj.settings.physical.m
    # star mass
    m_star = ICobj.settings.physical.M.copy()
    # disk mass
    m_disk = ICobj.sigma.m_disk.copy()
    m_disk = isaac.match_units(m_disk, m_star)[0]
    # mass of the gas particles
    m_particles = np.ones(nParticles) * m_disk / float(nParticles)
    # re-scale the particles (allows making of lo-mass disk)
    m_particles *= ICobj.settings.snapshot.mScale

    # ------------------------------------
    # Initial calculations
    # ------------------------------------
    # Find total mass interior to every particle
    N_interior = np.array(r.argsort().argsort())
    m_int = m_particles[[0]] * N_interior + m_star
    # Retrieve rho (density) at each position
    rho = ICobj.rho(z, r)
    # Retrieve radial derivative at each position
    drho_dr = ICobj.rho.drho_dr(z, r)
    # Get temperature at each position
    T = ICobj.T(r)

    # ------------------------------------
    # Calculate particle velocities
    # ------------------------------------
    # Find keperlerian velocity squared due to gravity
    v2grav = G * m_int / r
    # Find contribution from density gradient
    v2dens = (kB * T / m) * (r * drho_dr / rho)
    #       ignore nans and infs
    v2dens[(np.isnan(v2dens)) | (np.isinf(v2dens))] = 0.0
    # Find contribution from temperature gradient
    v2temp = (kB * T / m) * Tpower
    # Now find velocity from all contributions
    v = np.sqrt(v2grav + v2dens + v2temp)
    # Sometimes, at large r, the velocities due to the pressure and temp
    # Gradients become negative.  If this is the case, set them to 0
    nanind = np.isnan(v)
    v[nanind] = 0.0

    # -------------------------------------------------
    # Assign output
    # -------------------------------------------------
    # Get units all set up
    m_unit = m_star.units
    pos_unit = r.units
    # 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('{} km s**-1'.format(v_unit))
    x.convert_units(pos_unit)
    y.convert_units(pos_unit)
    z.convert_units(pos_unit)

    # 3-D velocity
    vel = SimArray(np.zeros([nParticles, 3]), v_unit)
    vel[:, 0] = -np.sin(theta) * v
    vel[:, 1] = np.cos(theta) * v

    # Generate positions
    xyz = SimArray(np.zeros([nParticles, 3]), pos_unit)
    xyz[:, 0] = x
    xyz[:, 1] = y
    xyz[:, 2] = z

    # Other settings
    eps = ICobj.settings.snapshot.eps
    star_eps = eps
    eps *= SimArray(np.ones(nParticles), pos_unit)
    metals = ICobj.settings.snapshot.metals
    star_metals = metals
    metals *= SimArray(np.ones(nParticles))

    # Generate snapshot
    snapshot = pynbody.new(star=1, gas=nParticles)
    snapshot.gas['vel'] = vel
    snapshot.gas['pos'] = xyz
    snapshot.gas['temp'] = T
    snapshot.gas['mass'] = m_particles
    snapshot.gas['metals'] = metals
    snapshot.gas['eps'] = eps
    snapshot.gas['mu'].derived = False
    snapshot.gas['mu'] = float(m.in_units('m_p'))

    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)
    snapshot.star['eps'] = SimArray(star_eps, pos_unit)

    param = isaac.make_param(snapshot, snapshotName)

    # CALCULATE VELOCITY USING calc_velocity.py
    vel = calc_velocity.v_xy(snapshot, param)
    snapshot.gas['vel'] = vel

    return snapshot, param
コード例 #28
0
ファイル: sigma_profile.py プロジェクト: trquinn/ICgen
def powerlaw(settings, T = None):
    """
    Generates a surface density profile according to a powerlaw sigma ~ 1/r
    with a smooth interior cutoff and smooth exterior exponential cutoff.
    
    **ARGUMENTS**
    
    settings : IC settings
        settings like those contained in an IC object (see ICgen_settings.py)
    T : callable function
        Function that returns temperature of the disk as a function of radius
        IF none, a powerlaw temperature is assumed
    
    **RETURNS**
    
    R : SimArray
        Radii at which sigma is calculated
    sigma : SimArray
        Surface density profile as a function of R
    """
    # Parse settings
    Rd = settings.sigma.Rd
    rin = settings.sigma.rin
    rmax = settings.sigma.rmax
    cutlength = settings.sigma.cutlength
    Mstar = settings.physical.M
    Qmin = settings.sigma.Qmin
    n_points = settings.sigma.n_points
    m = settings.physical.m

    if T is None:
        # If no callable object to calculate Temperature(R) is provided, 
        # default to a powerlaw T ~ R^-q
        
        T0 = SimArray([129.0],'K') # Temperature at 1 AU
        R0 = SimArray([1.0],'au')
        q = 0.59
        def T(x):
            
            return T0 * np.power((x/R0).in_units('1'),-q)
        
    Rd = isaac.match_units(pynbody.units.au, Rd)[1]
    Mstar = isaac.match_units(pynbody.units.Msol, Mstar)[1]
    # Molecular weight
    m = isaac.match_units(m, pynbody.units.m_p)[0]
    # Maximum R to calculate sigma at (needed for the exponential cutoff region)
    Rmax = rmax*Rd
    
    # Q calculation parameters:
    G = SimArray([1.0],'G')
    kB = SimArray([1.0],'k')
    
    # Initialize stuff
    A = SimArray(1.0,'Msol')/(2*np.pi*np.power(Rd,2))
    R = np.linspace(0,Rmax,n_points)
    r = np.array((R/Rd).in_units('1'))
    
    # Calculate sigma
    # Powerlaw
    sigma = A/r
    sigma[0] = 0.0
    # Interior cutoff
    sigma[r>1] *= np.exp(-(r[r>1] - 1)**2 / (2*cutlength**2))
    # Exterior cutoff
    sigma[r<rin] *= isaac.smoothstep(r[r<rin],degree=21,rescale=True)
    
    # Calculate Q
    Q = np.sqrt(Mstar*kB*T(R)/(G*m*R**3))/(np.pi*sigma)
    Q.convert_units('1')
    
    # Rescale sigma to meet the minimum Q requirement
    sigma *= Q.min()/Qmin
    
    # Calculate Q
    Q = np.sqrt(Mstar*kB*T(R)/(G*m*R**3))/(np.pi*sigma)
    Q.convert_units('1')
    
    return R, sigma
コード例 #29
0
ファイル: sigma_profile.py プロジェクト: trquinn/ICgen
def MQWS(settings, T):
    """
    Generates a surface density profile as the per method used in Mayer, Quinn,
    Wadsley, and Stadel 2004
    
    ** ARGUMENTS **
    NOTE: if units are not supplied, assumed units are AU, Msol
    
    settings : IC settings
        settings like those contained in an IC object (see ICgen_settings.py)
        
    T : callable
        A function to calculate temperature as a function of radius
        
    ** RETURNS **
    
    r : SimArray
        Radii at which sigma is calculated
    sigma : SimArray
        Surface density profile as a function of R
    """
    # Q calculation parameters:
    G = SimArray([1.0],'G')
    kB = SimArray([1.0],'k')
    
    # Load in settings
    n_points = settings.sigma.n_points
    rin = settings.sigma.rin
    rout = settings.sigma.rout
    rmax = settings.sigma.rmax
    Qmin = settings.sigma.Qmin
    m = settings.physical.m
    Mstar = settings.physical.M
    #m_disk = settings.sigma.m_disk
    
    rin = isaac.match_units(pynbody.units.au, rin)[1]
    rout = isaac.match_units(pynbody.units.au, rout)[1]
    #m_disk = isaac.match_units(pynbody.units.Msol, m_disk)[1]
    
    if rmax is None:
        
        rmax = 2.5 * rout
        
    else:
        
        rmax = isaac.match_units(pynbody.units.au, rmax)[1]
        
    r = np.linspace(0, rmax, n_points)
    
    #A = m_disk * np.exp(2 * (rin/rout).in_units('1'))/(rout * np.pi**1.5)
    
    a = (rin/r).in_units('1')
    b = (r/rout).in_units('1')
    #sigma = A * np.exp(-a**2 - b**2)/r
    sigma = (np.exp(-a**2 - b**2)/r) * Mstar.units/r.units
    
    # Calculate Q
    Q = np.sqrt(Mstar*kB*T(r)/(G*m*r**3))/(np.pi*sigma)
    Q.convert_units('1')

    sigma *= np.nanmin(Q)/Qmin
    
    # Remove all nans
    sigma[np.isnan(sigma)] = 0.0
    
    
    return r, sigma
コード例 #30
0
ファイル: calc_velocity.py プロジェクト: trquinn/ICgen
def v_xy(snapshot, param, changbin=None):
    """
    Attempts to calculate the circular velocities for particles in a thin
    (not flat) keplerian disk.  Requires ChaNGa
    
    ARGUMENTS:
    
    snapshot:   a tipsy snapshot for a gaseous disk
    param:      a dictionary containing params for changa.
                (see isaac.configparser)
    changbin:   (OPTIONAL)  If set, should be the full path to the ChaNGa
                executable.  If None, an attempt to find ChaNGa is made
    """

    if changbin is None:
        # Try to find the ChaNGa binary full path
        changbin = os.popen('which ChaNGa').read().strip()
    # --------------------------------------------
    # Initialize
    # --------------------------------------------
    # Load things from snapshot
    x = snapshot.g['x']
    y = snapshot.g['y']
    z = snapshot.g['z']
    r = snapshot.g['rxy']
    v_initial = snapshot.g['vel'].copy()

    # Temporary filenames for running ChaNGa
    f_prefix = str(np.random.randint(0, 2**32))
    f_name = f_prefix + '.std'
    p_name = f_prefix + '.param'

    # Update parameters
    p_temp = param.copy()
    p_temp['achInFile'] = f_name
    p_temp['achOutName'] = f_prefix
    if 'dDumpFrameTime' in p_temp: p_temp.pop('dDumpFrameTime')
    if 'dDumpFrameStep' in p_temp: p_temp.pop('dDumpFrameStep')

    # --------------------------------------------
    # Estimate velocity from gravity only
    # --------------------------------------------
    # Save files
    snapshot.write(filename=f_name, fmt=pynbody.tipsy.TipsySnap)
    isaac.configsave(p_temp, p_name, ftype='param')

    # Run ChaNGa, only calculating gravity
    command = 'charmrun ++local ' + changbin + ' -gas -n 0 ' + p_name

    p = subprocess.Popen(command.split(), stdout=subprocess.PIPE)

    while p.poll() is None:

        time.sleep(0.1)

    # Load accelerations
    acc_name = f_prefix + '.000000.acc2'
    a = isaac.load_acc(acc_name)

    # Calculate radial acceleration
    a_r = a[:, 0] * x / r + a[:, 1] * y / r

    # circular velocity
    v = np.sqrt(abs(r * a_r))

    # Assign
    snapshot.g['vel'][:, 0] = -v * y / r
    snapshot.g['vel'][:, 1] = v * x / r

    # --------------------------------------------
    # Estimate velocity from gravity & sph (assuming bDoGas=1 in param)
    # --------------------------------------------
    # Write file
    snapshot.write(filename=f_name, fmt=pynbody.tipsy.TipsySnap)

    # Run ChaNGa, only calculating gravity
    changbin = os.popen('which ChaNGa').read().strip()
    #command = 'charmrun ++local ' + changbin + ' +gas -n 0 ' + p_name
    command = 'charmrun ++local ' + changbin + ' -n 0 ' + p_name

    p = subprocess.Popen(command.split(), stdout=subprocess.PIPE)

    while p.poll() is None:

        time.sleep(0.1)

    # Load accelerations
    acc_name = f_prefix + '.000000.acc2'
    a = isaac.load_acc(acc_name)

    # Calculate radial acceleration
    a_r = a[:, 0] * x / r + a[:, 1] * y / r

    # circular velocity
    v = np.sqrt(abs(r * a_r))

    logv = np.log(v)
    logr = np.log(r)

    logr_bins, logv_mean, err = isaac.binned_mean(logr, logv, 50, \
    weighted_bins=True)

    logv_spline = isaac.extrap1d(logr_bins, logv_mean)

    v_calc = np.exp(logv_spline(logr))
    v_calc = isaac.match_units(v_calc, v_initial.units)[0]
    v_out = v_initial * 0.0
    v_out[:, 0] = -v_calc * y / r
    v_out[:, 1] = v_calc * x / r

    # Clean-up
    for fname in glob.glob(f_prefix + '*'):
        os.remove(fname)

    # Re-assign velocity to snapshot
    snapshot.g['vel'] = v_initial

    return v_out
コード例 #31
0
ファイル: sigma_profile.py プロジェクト: ibackus/ICgen
def MQWS(settings, T):
    """
    Generates a surface density profile as the per method used in Mayer, Quinn,
    Wadsley, and Stadel 2004
    
    ** ARGUMENTS **
    NOTE: if units are not supplied, assumed units are AU, Msol
    
    settings : IC settings
        settings like those contained in an IC object (see ICgen_settings.py)
        
    T : callable
        A function to calculate temperature as a function of radius
        
    ** RETURNS **
    
    r : SimArray
        Radii at which sigma is calculated
    sigma : SimArray
        Surface density profile as a function of R
    """
    # Q calculation parameters:
    G = SimArray([1.0], 'G')
    kB = SimArray([1.0], 'k')

    # Load in settings
    n_points = settings.sigma.n_points
    rin = settings.sigma.rin
    rout = settings.sigma.rout
    rmax = settings.sigma.rmax
    Qmin = settings.sigma.Qmin
    m = settings.physical.m
    Mstar = settings.physical.M
    #m_disk = settings.sigma.m_disk

    rin = isaac.match_units(pynbody.units.au, rin)[1]
    rout = isaac.match_units(pynbody.units.au, rout)[1]
    #m_disk = isaac.match_units(pynbody.units.Msol, m_disk)[1]

    if rmax is None:

        rmax = 2.5 * rout

    else:

        rmax = isaac.match_units(pynbody.units.au, rmax)[1]

    r = np.linspace(0, rmax, n_points)

    #A = m_disk * np.exp(2 * (rin/rout).in_units('1'))/(rout * np.pi**1.5)

    a = (rin / r).in_units('1')
    b = (r / rout).in_units('1')
    #sigma = A * np.exp(-a**2 - b**2)/r
    sigma = (np.exp(-a**2 - b**2) / r) * Mstar.units / r.units

    # Calculate Q
    Q = np.sqrt(Mstar * kB * T(r) / (G * m * r**3)) / (np.pi * sigma)
    Q.convert_units('1')

    sigma *= np.nanmin(Q) / Qmin

    # Remove all nans
    sigma[np.isnan(sigma)] = 0.0

    return r, sigma
コード例 #32
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 = isaac.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 = isaac.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
    isaac.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 = isaac.make_director(sigma_min,
                                   sigma_max,
                                   r_director,
                                   filename=param['achOutName'])
    ## Save .director file
    #isaac.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 = isaac.strip_units(np.sum(snapshotBinary.gas['mass']))
    binsys.m1 = isaac.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
コード例 #33
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
    """

    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 = isaac.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 = isaac.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
    isaac.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 = isaac.make_director(sigma_min,
                                   sigma_max,
                                   r_director,
                                   filename=param['achOutName'])
    ## Save .director file
    #isaac.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 = isaac.strip_units(r.min())
    param['dSinkBoundOrbitRadius'] = r_sink
    param['dSinkRadius'] = r_sink
    param['dSinkMassMin'] = 0.9 * isaac.strip_units(m_star)
    param['bDoSinks'] = 1

    return snapshot, param, director
コード例 #34
0
def v_xy(f, param, changbin=None, nr=50, min_per_bin=100):
    """
    Attempts to calculate the circular velocities for particles in a thin
    (not flat) keplerian disk.  Requires ChaNGa
    
    **ARGUMENTS**
    
    f : tipsy snapshot
        For a gaseous disk
    param : dict
        a dictionary containing params for changa. (see isaac.configparser)
    changbin : str  (OPTIONAL)  
        If set, should be the full path to the ChaNGa executable.  If None, 
        an attempt to find ChaNGa is made
    nr : int (optional)
        number of radial bins to use when averaging over accelerations
    min_per_bin : int (optional)
        The minimum number of particles to be in each bin.  If there are too
        few particles in a bin, it is merged with an adjacent bin.  Thus,
        actual number of radial bins may be less than nr.
        
    **RETURNS**
    
    vel : SimArray
        An N by 3 SimArray of gas particle velocities.
    """

    if changbin is None:
        # Try to find the ChaNGa binary full path
        changbin = os.popen('which ChaNGa').read().strip()

    # Load stuff from the snapshot
    x = f.g['x']
    y = f.g['y']
    z = f.g['z']
    r = f.g['rxy']
    vel0 = f.g['vel'].copy()

    # Remove units from all quantities
    r = isaac.strip_units(r)
    x = isaac.strip_units(x)
    y = isaac.strip_units(y)
    z = isaac.strip_units(z)

    # Temporary filenames for running ChaNGa
    f_prefix = str(np.random.randint(0, 2**32))
    f_name = f_prefix + '.std'
    p_name = f_prefix + '.param'

    # Update parameters
    p_temp = param.copy()
    p_temp['achInFile'] = f_name
    p_temp['achOutName'] = f_prefix
    if 'dDumpFrameTime' in p_temp: p_temp.pop('dDumpFrameTime')
    if 'dDumpFrameStep' in p_temp: p_temp.pop('dDumpFrameStep')

    # --------------------------------------------
    # Estimate velocity from gravity only
    # --------------------------------------------
    # Note, accelerations due to gravity are calculated twice to be extra careful
    # This is so that any velocity dependent effects are properly accounted for
    # (although, ideally, there should be none)
    # The second calculation uses the updated velocities from the first
    for iGrav in range(2):
        # Save files
        f.write(filename=f_name, fmt=pynbody.tipsy.TipsySnap)
        isaac.configsave(p_temp, p_name, ftype='param')

        # Run ChaNGa, only calculating gravity
        command = 'charmrun ++local ' + changbin + ' -gas -n 0 ' + p_name

        p = subprocess.Popen(command.split(), stdout=subprocess.PIPE)

        while p.poll() is None:

            time.sleep(0.1)

        # Load accelerations
        acc_name = f_prefix + '.000000.acc2'
        a = isaac.load_acc(acc_name)

        # Clean-up
        for fname in glob.glob(f_prefix + '*'):
            os.remove(fname)

        # If a is not a vector, calculate radial acceleration.  Otherwise, assume
        # a is the radial acceleration
        a_r = a[:, 0] * x / r + a[:, 1] * y / r

        # Make sure the units are correct then remove them
        a_r = isaac.match_units(a_r, a)[0]
        a_r = isaac.strip_units(a_r)

        # Calculate cos(theta) where theta is angle above x-y plane
        cos = r / np.sqrt(r**2 + z**2)
        ar2 = a_r * r**2

        # Bin the data
        r_edges = np.linspace(r.min(), (1 + np.spacing(2)) * r.max(), nr + 1)
        ind, r_edges = isaac.digitize_threshold(r, min_per_bin, r_edges)
        ind -= 1
        nr = len(r_edges) - 1

        r_bins, ar2_mean, err = isaac.binned_mean(r, ar2, binedges=r_edges, \
        weighted_bins=True)

        # Fit lines to ar2 vs cos for each radial bin
        m = np.zeros(nr)
        b = np.zeros(nr)

        for i in range(nr):

            mask = (ind == i)
            p = np.polyfit(cos[mask], ar2[mask], 1)
            m[i] = p[0]
            b[i] = p[1]

        # Interpolate the line fits
        m_spline = isaac.extrap1d(r_bins, m)
        b_spline = isaac.extrap1d(r_bins, b)

        # Calculate circular velocity
        ar2_calc = m_spline(r) * cos + b_spline(r)
        v_calc = np.sqrt(abs(ar2_calc) / r)
        vel = f.g['vel'].copy()
        v_calc = isaac.match_units(v_calc, vel)[0]
        vel[:, 0] = -v_calc * y / r
        vel[:, 1] = v_calc * x / r

        # Assign to f
        f.g['vel'] = vel

    # --------------------------------------------
    # Estimate pressure/gas dynamics accelerations
    # --------------------------------------------
    a_grav = a
    ar2_calc_grav = ar2_calc

    # Save files
    f.write(filename=f_name, fmt=pynbody.tipsy.TipsySnap)
    isaac.configsave(p_temp, p_name, ftype='param')

    # Run ChaNGa, including SPH
    command = 'charmrun ++local ' + changbin + ' +gas -n 0 ' + p_name

    p = subprocess.Popen(command.split(), stdout=subprocess.PIPE)

    while p.poll() is None:

        time.sleep(0.1)

    # Load accelerations
    acc_name = f_prefix + '.000000.acc2'
    a_total = isaac.load_acc(acc_name)

    # Clean-up
    for fname in glob.glob(f_prefix + '*'):
        os.remove(fname)

    # Estimate the accelerations due to pressure gradients/gas dynamics
    a_gas = a_total - a_grav
    ar_gas = a_gas[:, 0] * x / r + a_gas[:, 1] * y / r
    ar_gas = isaac.strip_units(ar_gas)
    ar2_gas = ar_gas * r**2

    logr_bins, ratio, err = isaac.binned_mean(np.log(r), ar2_gas/ar2_calc_grav, nbins=nr,\
    weighted_bins=True)
    r_bins = np.exp(logr_bins)
    ratio_spline = isaac.extrap1d(r_bins, ratio)

    ar2_calc = ar2_calc_grav * (1 + ratio_spline(r))
    a_calc = ar2_calc / r**2

    v = np.sqrt(r * abs(a_calc))
    v = isaac.match_units(v, vel0.units)[0]
    vel = vel0.copy()
    vel[:, 0] = -v * y / r
    vel[:, 1] = v * x / r

    # more cleanup
    f.g['vel'] = vel0

    return vel
コード例 #35
0
ファイル: make_snapshot.py プロジェクト: trquinn/ICgen
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
    """

    # Constants
    G = SimArray(1.0, "G")
    kB = SimArray(1.0, "k")
    # ------------------------------------
    # Load in things from ICobj
    # ------------------------------------
    # snapshot file name
    snapshotName = ICobj.settings.filenames.snapshotName
    # particle positions
    theta = ICobj.pos.theta
    r = ICobj.pos.r
    x = ICobj.pos.x
    y = ICobj.pos.y
    z = ICobj.pos.z
    # Number of particles
    nParticles = ICobj.pos.nParticles
    # Temperature power law (used for pressure gradient)
    Tpower = ICobj.settings.physical.Tpower
    # molecular mass
    m = ICobj.settings.physical.m
    # star mass
    m_star = ICobj.settings.physical.M.copy()
    # disk mass
    m_disk = ICobj.sigma.m_disk.copy()
    m_disk = isaac.match_units(m_disk, m_star)[0]
    # mass of the gas particles
    m_particles = np.ones(nParticles) * m_disk / float(nParticles)
    # re-scale the particles (allows making of lo-mass disk)
    m_particles *= ICobj.settings.snapshot.mScale

    # ------------------------------------
    # Initial calculations
    # ------------------------------------
    # Find total mass interior to every particle
    N_interior = np.array(r.argsort().argsort())
    m_int = m_particles[[0]] * N_interior + m_star
    # Retrieve rho (density) at each position
    rho = ICobj.rho(z, r)
    # Retrieve radial derivative at each position
    drho_dr = ICobj.rho.drho_dr(z, r)
    # Get temperature at each position
    T = ICobj.T(r)

    # ------------------------------------
    # Calculate particle velocities
    # ------------------------------------
    # Find keperlerian velocity squared due to gravity
    v2grav = G * m_int / r
    # Find contribution from density gradient
    v2dens = (kB * T / m) * (r * drho_dr / rho)
    #       ignore nans and infs
    v2dens[(np.isnan(v2dens)) | (np.isinf(v2dens))] = 0.0
    # Find contribution from temperature gradient
    v2temp = (kB * T / m) * Tpower
    # Now find velocity from all contributions
    v = np.sqrt(v2grav + v2dens + v2temp)
    # Sometimes, at large r, the velocities due to the pressure and temp
    # Gradients become negative.  If this is the case, set them to 0
    nanind = np.isnan(v)
    v[nanind] = 0.0

    # -------------------------------------------------
    # Assign output
    # -------------------------------------------------
    # Get units all set up
    m_unit = m_star.units
    pos_unit = r.units
    # 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("{} km s**-1".format(v_unit))
    x.convert_units(pos_unit)
    y.convert_units(pos_unit)
    z.convert_units(pos_unit)

    # 3-D velocity
    vel = SimArray(np.zeros([nParticles, 3]), v_unit)
    vel[:, 0] = -np.sin(theta) * v
    vel[:, 1] = np.cos(theta) * v

    # Generate positions
    xyz = SimArray(np.zeros([nParticles, 3]), pos_unit)
    xyz[:, 0] = x
    xyz[:, 1] = y
    xyz[:, 2] = z

    # Other settings
    eps = ICobj.settings.snapshot.eps
    star_eps = eps
    eps *= SimArray(np.ones(nParticles), pos_unit)
    metals = ICobj.settings.snapshot.metals
    star_metals = metals
    metals *= SimArray(np.ones(nParticles))

    # Generate snapshot
    snapshot = pynbody.new(star=1, gas=nParticles)
    snapshot.gas["vel"] = vel
    snapshot.gas["pos"] = xyz
    snapshot.gas["temp"] = T
    snapshot.gas["mass"] = m_particles
    snapshot.gas["metals"] = metals
    snapshot.gas["eps"] = eps
    snapshot.gas["mu"].derived = False
    snapshot.gas["mu"] = float(m.in_units("m_p"))

    snapshot.star["pos"] = SimArray([[0.0, 0.0, 0.0]], pos_unit)
    snapshot.star["vel"] = SimArray([[0.0, 0.0, 0.0]], v_unit)
    snapshot.star["mass"] = m_star
    snapshot.star["metals"] = SimArray(star_metals)
    snapshot.star["eps"] = SimArray(star_eps, pos_unit)

    param = isaac.make_param(snapshot, snapshotName)

    return snapshot, param
コード例 #36
0
ファイル: sigma_profile.py プロジェクト: ibackus/ICgen
def powerlaw(settings, T=None):
    """
    Generates a surface density profile according to a powerlaw sigma ~ 1/r
    with a smooth interior cutoff and smooth exterior exponential cutoff.
    
    **ARGUMENTS**
    
    settings : IC settings
        settings like those contained in an IC object (see ICgen_settings.py)
    T : callable function
        Function that returns temperature of the disk as a function of radius
        IF none, a powerlaw temperature is assumed
    
    **RETURNS**
    
    R : SimArray
        Radii at which sigma is calculated
    sigma : SimArray
        Surface density profile as a function of R
    """
    # Parse settings
    Rd = settings.sigma.Rd
    rin = settings.sigma.rin
    rmax = settings.sigma.rmax
    cutlength = settings.sigma.cutlength
    Mstar = settings.physical.M
    Qmin = settings.sigma.Qmin
    n_points = settings.sigma.n_points
    m = settings.physical.m
    power = settings.sigma.power

    if T is None:
        # If no callable object to calculate Temperature(R) is provided,
        # default to a powerlaw T ~ R^-q

        T0 = SimArray([129.0], 'K')  # Temperature at 1 AU
        R0 = SimArray([1.0], 'au')
        q = 0.59

        def T(x):

            return T0 * np.power((x / R0).in_units('1'), -q)

    Rd = isaac.match_units(pynbody.units.au, Rd)[1]
    Mstar = isaac.match_units(pynbody.units.Msol, Mstar)[1]
    # Molecular weight
    m = isaac.match_units(m, pynbody.units.m_p)[0]
    # Maximum R to calculate sigma at (needed for the exponential cutoff region)
    Rmax = rmax * Rd

    # Q calculation parameters:
    G = SimArray([1.0], 'G')
    kB = SimArray([1.0], 'k')

    # Initialize stuff
    A = SimArray(1.0, 'Msol') / (2 * np.pi * np.power(Rd, 2))
    R = np.linspace(0, Rmax, n_points)
    r = np.array((R / Rd).in_units('1'))

    # Calculate sigma
    # Powerlaw
    #sigma = A/r
    #dflemin3 edit 06/10/2015: Try powerlaw of the form sigma ~ r^power
    sigma = A * np.power(r, power)
    sigma[0] = 0.0
    # Exterior cutoff
    sigma[r > 1] *= np.exp(-(r[r > 1] - 1)**2 / (2 * cutlength**2))
    # Interior cutoff
    sigma[r < rin] *= isaac.smoothstep(r[r < rin], degree=21, rescale=True)

    # Calculate Q
    Q = np.sqrt(Mstar * kB * T(R) / (G * m * R**3)) / (np.pi * sigma)
    Q.convert_units('1')

    # Rescale sigma to meet the minimum Q requirement
    sigma *= Q.min() / Qmin

    # Calculate Q
    Q = np.sqrt(Mstar * kB * T(R) / (G * m * R**3)) / (np.pi * sigma)
    Q.convert_units('1')
    return R, sigma
コード例 #37
0
ファイル: calc_velocity_mpi.py プロジェクト: dflemin3/ICgen
def v_xy(f, param, changbin=None, nr=50, min_per_bin=100):
    """
    Attempts to calculate the circular velocities for particles in a thin
    (not flat) keplerian disk.  Requires ChaNGa
    
    **ARGUMENTS**
    
    f : tipsy snapshot
        For a gaseous disk
    param : dict
        a dictionary containing params for changa. (see isaac.configparser)
    changbin : str  (OPTIONAL)  
        If set, should be the full path to the ChaNGa executable.  If None, 
        an attempt to find ChaNGa is made
    nr : int (optional)
        number of radial bins to use when averaging over accelerations
    min_per_bin : int (optional)
        The minimum number of particles to be in each bin.  If there are too
        few particles in a bin, it is merged with an adjacent bin.  Thus,
        actual number of radial bins may be less than nr.
        
    **RETURNS**
    
    vel : SimArray
        An N by 3 SimArray of gas particle velocities.
    """
    
    if changbin is None:
        # Try to find the ChaNGa binary full path
        changbin = os.popen('which ChaNGa_uw_mpi').read().strip()
        
    # Load up mpi
    
    # Load stuff from the snapshot
    x = f.g['x']
    y = f.g['y']
    z = f.g['z']
    r = f.g['rxy']
    vel0 = f.g['vel'].copy()
    
    # Remove units from all quantities
    r = isaac.strip_units(r)
    x = isaac.strip_units(x)
    y = isaac.strip_units(y)
    z = isaac.strip_units(z)
    
    # Temporary filenames for running ChaNGa
    f_prefix = str(np.random.randint(0, 2**32))
    f_name = f_prefix + '.std'
    p_name = f_prefix + '.param'
    
    # Update parameters
    p_temp = param.copy()
    p_temp['achInFile'] = f_name
    p_temp['achOutName'] = f_prefix
    if 'dDumpFrameTime' in p_temp: p_temp.pop('dDumpFrameTime')
    if 'dDumpFrameStep' in p_temp: p_temp.pop('dDumpFrameStep')
    
    # --------------------------------------------
    # Estimate velocity from gravity only
    # --------------------------------------------
    # Note, accelerations due to gravity are calculated twice to be extra careful
    # This is so that any velocity dependent effects are properly accounted for
    # (although, ideally, there should be none)
    # The second calculation uses the updated velocities from the first
    for iGrav in range(2):
        # Save files
        f.write(filename=f_name, fmt = pynbody.tipsy.TipsySnap)
        isaac.configsave(p_temp, p_name, ftype='param')
        
        # Run ChaNGa, only calculating gravity
        command = 'mpirun --mca mtl mx --mca pml cm ' + changbin + ' -gas -n 0 ' + p_name
        #command = 'charmrun ++local ' + changbin + ' -gas -n 0 ' + p_name
        
        p = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
        
        while p.poll() is None:
            
            time.sleep(0.1)
            
    
        # Load accelerations
        acc_name = f_prefix + '.000000.acc2'
        a = isaac.load_acc(acc_name)
        
        # Clean-up
        for fname in glob.glob(f_prefix + '*'): os.remove(fname)
        
        # If a is not a vector, calculate radial acceleration.  Otherwise, assume
        # a is the radial acceleration                
        a_r = a[:,0]*x/r + a[:,1]*y/r
        
        # Make sure the units are correct then remove them
        a_r = isaac.match_units(a_r, a)[0]
        a_r = isaac.strip_units(a_r)
        
        # Calculate cos(theta) where theta is angle above x-y plane
        cos = r/np.sqrt(r**2 + z**2)
        ar2 = a_r*r**2
        
        # Bin the data
        r_edges = np.linspace(r.min(), (1+np.spacing(2))*r.max(), nr + 1)
        ind, r_edges = isaac.digitize_threshold(r, min_per_bin, r_edges)
        ind -= 1
        nr = len(r_edges) - 1
        
        r_bins, ar2_mean, err = isaac.binned_mean(r, ar2, binedges=r_edges, \
        weighted_bins=True)
        
        # Fit lines to ar2 vs cos for each radial bin
        m = np.zeros(nr)
        b = np.zeros(nr)    
        
        for i in range(nr):
            
            mask = (ind == i)
            p = np.polyfit(cos[mask], ar2[mask], 1)
            m[i] = p[0]
            b[i] = p[1]
            
        # Interpolate the line fits
        m_spline = isaac.extrap1d(r_bins, m)
        b_spline = isaac.extrap1d(r_bins, b)
        
        # Calculate circular velocity
        ar2_calc = m_spline(r)*cos + b_spline(r)
        v_calc = np.sqrt(abs(ar2_calc)/r)
        vel = f.g['vel'].copy()
        v_calc = isaac.match_units(v_calc,vel)[0]
        vel[:,0] = -v_calc*y/r
        vel[:,1] = v_calc*x/r
        
        # Assign to f
        f.g['vel'] = vel
        
    # --------------------------------------------
    # Estimate pressure/gas dynamics accelerations
    # --------------------------------------------
    a_grav = a
    ar2_calc_grav = ar2_calc
    
    # Save files
    f.write(filename=f_name, fmt = pynbody.tipsy.TipsySnap)
    isaac.configsave(p_temp, p_name, ftype='param')
    
    # Run ChaNGa, including SPH
    command = 'mpirun --mca mtl mx --mca pml cm ' + changbin + ' +gas -n 0 ' + p_name
    
    p = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
    
    while p.poll() is None:
        
        time.sleep(0.1)
        
    # Load accelerations
    acc_name = f_prefix + '.000000.acc2'
    a_total = isaac.load_acc(acc_name)
    
    # Clean-up
    for fname in glob.glob(f_prefix + '*'): os.remove(fname)
    
    # Estimate the accelerations due to pressure gradients/gas dynamics
    a_gas = a_total - a_grav
    ar_gas = a_gas[:,0]*x/r + a_gas[:,1]*y/r
    ar_gas = isaac.strip_units(ar_gas)
    ar2_gas = ar_gas*r**2
    
    logr_bins, ratio, err = isaac.binned_mean(np.log(r), ar2_gas/ar2_calc_grav, nbins=nr,\
    weighted_bins=True)
    r_bins = np.exp(logr_bins)
    ratio_spline = isaac.extrap1d(r_bins, ratio)
    
    ar2_calc = ar2_calc_grav*(1 + ratio_spline(r))
    a_calc = ar2_calc/r**2
    
    v = np.sqrt(r*abs(a_calc))
    v = isaac.match_units(v, vel0.units)[0]
    vel = vel0.copy()
    vel[:,0] = -v*y/r
    vel[:,1] = v*x/r
    
    # more cleanup
    f.g['vel'] = vel0
    
    return vel
コード例 #38
0
ファイル: make_snapshotSType.py プロジェクト: dflemin3/ICgen
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 = isaac.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
    eps = r.min()
    
    # Make param file
    param = isaac.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
    isaac.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 = isaac.make_director(sigma_min, sigma_max, r_director, filename=param['achOutName'])
    ## Save .director file
    #isaac.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 = isaac.strip_units(np.sum(snapshotBinary.gas['mass']))
    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)
 
    #Now that everything has masses and positions, adjust positions so the 
    #system center of mass corresponds to the origin
    """    
    com = binaryUtils.computeCOM(snapshotBinary.stars,snapshotBinary.gas)
    print com
    snapshotBinary.stars['pos'] -= com
    snapshotBinary.gas['pos'] -= com   
    """
 
    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