def calc_rungdist(param_name, dDelta):
    """
    Calls ChaNGa to calculate the rung distribution
    """
        
    changa_args = '+n 1 -dt {}'.format(dDelta)
    command = ICgen_utils.changa_command(param_name, changa_args=changa_args, preset='isaac')
    p = ICgen_utils.changa_run(command, verbose=False)
    
    return read_rungdist(p)
Example #2
0
def calc_rungdist(param_name, dDelta):
    """
    Calls ChaNGa to calculate the rung distribution
    """

    changa_args = '+n 1 -dt {}'.format(dDelta)
    command = ICgen_utils.changa_command(param_name,
                                         changa_args=changa_args,
                                         preset='isaac')
    p = ICgen_utils.changa_run(command, verbose=False)

    return read_rungdist(p)
Example #3
0
def v_xy(f, param, changbin=None, nr=50, min_per_bin=100, changa_preset=None, \
max_particles=None, est_eps=True):
    """
    Attempts to calculate the circular velocities for particles in a thin
    (not flat) keplerian disk.  Also estimates gravitational softening (eps)
    for the gas particles
    
    Requires ChaNGa
    
    Note that this will change the velocities IN f
    
    **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.
    changa_preset : str
        Which ChaNGa execution preset to use (ie 'mpi', 'local', ...).  See
        ICgen_utils.changa_command
    max_particles : int or None
        Specifies the maximum number of particles to use for calculating
        accelerations and velocities.  Setting a smaller number can speed up
        computation and save on memory but can yield noisier results.
        If None, max is unlimited.
    est_eps : bool
        Estimate eps (gravitational softening length).  Default is True.
        If False, it is assumed eps has already been estimated
        
    **RETURNS**
    
    Nothing.  Velocities are updated within f as is eps
    """
    # If the snapshot has too many particles, randomly select gas particles
    # To use for calculating velocity and make a view of the snapshot
    n_gas = len(f) - 1
    subview = (n_gas > max_particles) and (max_particles is not None)
    if subview:
        
        max_particles = int(max_particles)
        mask = np.zeros(n_gas + 1, dtype=bool)
        mask[-1] = True # Use the star particle always
        # randomly select particles to use
        m = np.random.rand(n_gas)
        ind = m.argsort()[0:max_particles]
        mask[ind] = True
        # Make a subview and create a reference to the complete snapshot
        complete_snapshot = f
        f = complete_snapshot[mask]
        # Scale gas mass
        m_scale = float(n_gas)/float(max_particles)
        f.g['mass'] *= m_scale
        
        if not est_eps:
            
            f.g['eps'] *= m_scale**(1.0/3)
        
    # Load stuff from the snapshot
    r = f.g['rxy'].astype(np.float32)
        
    cosine = (f.g['x']/r).in_units('1').astype(np.float32)
    sine = (f.g['y']/r).in_units('1').astype(np.float32)
    z = f.g['z']
    vel = f.g['vel']
    a = None # arbitrary initialization
    
    # 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
    p_temp['dDelta'] = 1e-10
    if 'dDumpFrameTime' in p_temp: p_temp.pop('dDumpFrameTime')
    if 'dDumpFrameStep' in p_temp: p_temp.pop('dDumpFrameStep')
    
    # --------------------------------------------
    # Estimate velocity from gravity only
    # --------------------------------------------
    for iGrav in range(2):
        # Save files
        f.write(filename=f_name, fmt = pynbody.tipsy.TipsySnap)
        isaac.configsave(p_temp, p_name, ftype='param')
        
        if iGrav == 0:
            # Run ChaNGa calculating all forces (for initial run)
            command = ICgen_utils.changa_command(p_name, changa_preset, changbin, '+gas +n 0')
        else:
            # Run ChaNGa, only calculating gravity (on second run)
            command = ICgen_utils.changa_command(p_name, changa_preset, changbin, '-gas +n 0')
            
        print command
        p = ICgen_utils.changa_run(command)
        p.wait()
        
        if (iGrav == 0) and est_eps:
            # Estimate the gravitational softening length on the first iteration
            smoothlength_file = f_prefix + '.000000.smoothlength'
            eps = ICgen_utils.est_eps(smoothlength_file)
            f.g['eps'] = eps
    
        # Load accelerations
        acc_name = f_prefix + '.000000.acc2'
        del a
        gc.collect()
        a = isaac.load_acc(acc_name, low_mem=True)
        gc.collect()
        
        # Clean-up
        for fname in glob.glob(f_prefix + '*'): os.remove(fname)
        
        # Calculate cos(theta) where theta is angle above x-y plane
        cos = (r/np.sqrt(r**2 + z**2)).in_units('1').astype(np.float32)
        # Calculate radial acceleration times r^2
        ar2 = (a[:,0]*cosine + a[:,1]*sine)*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)
        
        gc.collect()
        
        # 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 = SimArray(m_spline(r)*cos + b_spline(r), ar2.units)
        gc.collect()
        v_calc = (np.sqrt(abs(ar2)/r)).in_units(vel.units)
        gc.collect()
        vel[:,0] = -v_calc*sine
        vel[:,1] = v_calc*cosine
        del v_calc
        gc.collect()
        
    # --------------------------------------------
    # Estimate pressure/gas dynamics accelerations
    # --------------------------------------------
    
    # Save files
    f.write(filename=f_name, fmt = pynbody.tipsy.TipsySnap)
    isaac.configsave(p_temp, p_name, ftype='param')
    
    # Run ChaNGa, including SPH
    command = ICgen_utils.changa_command(p_name, changa_preset, changbin, '+gas -n 0')
    p = ICgen_utils.changa_run(command)
    p.wait()
        
    # Load accelerations
    acc_name = f_prefix + '.000000.acc2'
    a_total = isaac.load_acc(acc_name, low_mem=True)
    gc.collect()
    
    # 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
    del a_total, a
    gc.collect()
    ar2_gas = (a_gas[:,0]*cosine + a_gas[:,1]*sine)*r**2
    del a_gas
    gc.collect()
    
    logr_bins, ratio, err = isaac.binned_mean(np.log(r), ar2_gas/ar2, nbins=nr,\
    weighted_bins=True)
    r_bins = np.exp(logr_bins)
    del ar2_gas
    gc.collect()
    ratio_spline = isaac.extrap1d(r_bins, ratio)
    
    # If not all the particles were used for calculating velocity,
    # Make sure to use them now
    if subview:
        
        # Re-scale mass back to normal
        f.g['mass'] /= m_scale
        # Scale eps appropriately
        f.g['eps'] /= m_scale**(1.0/3)
        complete_snapshot.g['eps'] = f.g['eps'][[0]]
        
        # Rename complete snapshot
        f = complete_snapshot
        # Calculate stuff for all particles
        r = f.g['rxy']
        z = f.g['z']
        cos = (r/np.sqrt(r**2 + z**2)).in_units('1').astype(np.float32)
        ar2 = SimArray(m_spline(r)*cos + b_spline(r), ar2.units)
        cosine = (f.g['x']/r).in_units('1').astype(np.float32)
        sine = (f.g['y']/r).in_units('1').astype(np.float32)
        vel = f.g['vel']
        
    
    ar2_calc = ar2*(1 + ratio_spline(r))
    del ar2
    gc.collect()
    
    # Calculate velocity
    v = (np.sqrt(abs(ar2_calc)/r)).in_units(f.g['vel'].units)
    del ar2_calc
    gc.collect()
    
    vel[:,0] = -v*sine
    vel[:,1] = v*cosine
    
    return
Example #4
0
def v_xy(f, param, changbin=None, nr=50, min_per_bin=100, changa_preset=None, \
max_particles=None, est_eps=True):
    """
    Attempts to calculate the circular velocities for particles in a thin
    (not flat) keplerian disk.  Also estimates gravitational softening (eps)
    for the gas particles
    
    Requires ChaNGa
    
    Note that this will change the velocities IN f
    
    **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.
    changa_preset : str
        Which ChaNGa execution preset to use (ie 'mpi', 'local', ...).  See
        ICgen_utils.changa_command
    max_particles : int or None
        Specifies the maximum number of particles to use for calculating
        accelerations and velocities.  Setting a smaller number can speed up
        computation and save on memory but can yield noisier results.
        If None, max is unlimited.
    est_eps : bool
        Estimate eps (gravitational softening length).  Default is True.
        If False, it is assumed eps has already been estimated
        
    **RETURNS**
    
    Nothing.  Velocities are updated within f as is eps
    """
    # If the snapshot has too many particles, randomly select gas particles
    # To use for calculating velocity and make a view of the snapshot
    n_gas = len(f) - 1
    subview = (n_gas > max_particles) and (max_particles is not None)
    if subview:

        max_particles = int(max_particles)
        mask = np.zeros(n_gas + 1, dtype=bool)
        mask[-1] = True  # Use the star particle always
        # randomly select particles to use
        m = np.random.rand(n_gas)
        ind = m.argsort()[0:max_particles]
        mask[ind] = True
        # Make a subview and create a reference to the complete snapshot
        complete_snapshot = f
        f = complete_snapshot[mask]
        # Scale gas mass
        m_scale = float(n_gas) / float(max_particles)
        f.g['mass'] *= m_scale

        if not est_eps:

            f.g['eps'] *= m_scale**(1.0 / 3)

    # Load stuff from the snapshot
    r = f.g['rxy'].astype(np.float32)

    cosine = (f.g['x'] / r).in_units('1').astype(np.float32)
    sine = (f.g['y'] / r).in_units('1').astype(np.float32)
    z = f.g['z']
    vel = f.g['vel']
    a = None  # arbitrary initialization

    # 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
    p_temp['dDelta'] = 1e-10
    if 'dDumpFrameTime' in p_temp: p_temp.pop('dDumpFrameTime')
    if 'dDumpFrameStep' in p_temp: p_temp.pop('dDumpFrameStep')

    # --------------------------------------------
    # Estimate velocity from gravity only
    # --------------------------------------------
    for iGrav in range(2):
        # Save files
        f.write(filename=f_name, fmt=pynbody.tipsy.TipsySnap)
        isaac.configsave(p_temp, p_name, ftype='param')

        if iGrav == 0:
            # Run ChaNGa calculating all forces (for initial run)
            command = ICgen_utils.changa_command(p_name, changa_preset,
                                                 changbin, '+gas +n 0')
        else:
            # Run ChaNGa, only calculating gravity (on second run)
            command = ICgen_utils.changa_command(p_name, changa_preset,
                                                 changbin, '-gas +n 0')

        print command
        p = ICgen_utils.changa_run(command)
        p.wait()

        if (iGrav == 0) and est_eps:
            # Estimate the gravitational softening length on the first iteration
            smoothlength_file = f_prefix + '.000000.smoothlength'
            eps = ICgen_utils.est_eps(smoothlength_file)
            f.g['eps'] = eps

        # Load accelerations
        acc_name = f_prefix + '.000000.acc2'
        del a
        gc.collect()
        a = isaac.load_acc(acc_name, low_mem=True)
        gc.collect()

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

        # Calculate cos(theta) where theta is angle above x-y plane
        cos = (r / np.sqrt(r**2 + z**2)).in_units('1').astype(np.float32)
        # Calculate radial acceleration times r^2
        ar2 = (a[:, 0] * cosine + a[:, 1] * sine) * 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)

        gc.collect()

        # 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 = SimArray(m_spline(r) * cos + b_spline(r), ar2.units)
        gc.collect()
        v_calc = (np.sqrt(abs(ar2) / r)).in_units(vel.units)
        gc.collect()
        vel[:, 0] = -v_calc * sine
        vel[:, 1] = v_calc * cosine
        del v_calc
        gc.collect()

    # --------------------------------------------
    # Estimate pressure/gas dynamics accelerations
    # --------------------------------------------

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

    # Run ChaNGa, including SPH
    command = ICgen_utils.changa_command(p_name, changa_preset, changbin,
                                         '+gas -n 0')
    p = ICgen_utils.changa_run(command)
    p.wait()

    # Load accelerations
    acc_name = f_prefix + '.000000.acc2'
    a_total = isaac.load_acc(acc_name, low_mem=True)
    gc.collect()

    # 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
    del a_total, a
    gc.collect()
    ar2_gas = (a_gas[:, 0] * cosine + a_gas[:, 1] * sine) * r**2
    del a_gas
    gc.collect()

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

    # If not all the particles were used for calculating velocity,
    # Make sure to use them now
    if subview:

        # Re-scale mass back to normal
        f.g['mass'] /= m_scale
        # Scale eps appropriately
        f.g['eps'] /= m_scale**(1.0 / 3)
        complete_snapshot.g['eps'] = f.g['eps'][[0]]

        # Rename complete snapshot
        f = complete_snapshot
        # Calculate stuff for all particles
        r = f.g['rxy']
        z = f.g['z']
        cos = (r / np.sqrt(r**2 + z**2)).in_units('1').astype(np.float32)
        ar2 = SimArray(m_spline(r) * cos + b_spline(r), ar2.units)
        cosine = (f.g['x'] / r).in_units('1').astype(np.float32)
        sine = (f.g['y'] / r).in_units('1').astype(np.float32)
        vel = f.g['vel']

    ar2_calc = ar2 * (1 + ratio_spline(r))
    del ar2
    gc.collect()

    # Calculate velocity
    v = (np.sqrt(abs(ar2_calc) / r)).in_units(f.g['vel'].units)
    del ar2_calc
    gc.collect()

    vel[:, 0] = -v * sine
    vel[:, 1] = v * cosine

    return