Пример #1
0
def COM(snap, quantity='x', type="default", unit="default"):
    ''' Computes the centre-of-mass value of a given vector component'''
    xunitinfo, x, xscaling_factor, xlabel = UserQuantity(quantity).fetch(type, snap, unit)
    m = UserQuantity('m').fetch(type, snap)[1]

    com = (x*m).sum()/m.sum()

    return xunitinfo, com, xscaling_factor, xlabel+'_COM'
Пример #2
0
def lagrangian_radii(snap, mfrac=0.5, type="default", unit="default"):
    '''Computes the Lagrangian radii from all particles in simulation'''
    runitinfo, r, rscaling_factor, rlabel = UserQuantity('r').fetch(type, snap, unit)
    m = UserQuantity('m').fetch(type, snap, unit)[1]

    # Find particle ids in order of increasing radial distance
    porder      = np.argsort(r)
    m_ordered   = m[porder]
    mcumulative = np.cumsum(m_ordered)
    mtotal      = mcumulative[-1]
    mlag        = mfrac*mtotal
    index       = np.searchsorted(mcumulative,mlag)
    lag_radius  = 0.5*(r[porder[index-1]] + r[porder[index]])
    return runitinfo, lag_radius, rscaling_factor, 'lag_radius_' + str(mfrac)
Пример #3
0
def energy_error(snap, etot0, type="default", unit="default"):
    '''Computes the energy error of all particles in the simulation'''
    vx   = UserQuantity('vx').fetch(type, snap, unit)[1]
    vy   = UserQuantity('vy').fetch(type, snap, unit)[1]
    vz   = UserQuantity('vz').fetch(type, snap, unit)[1]
    m    = UserQuantity('m').fetch(type, snap, unit)[1]
    gpot = UserQuantity('gpot').fetch(type, snap, unit)[1]
    N    = m.size

    # Loop over all particles and compute
    energy = 0.5*m*(vx*vx + vy*vy + vz*vz) - 0.5*m*gpot
    etot   = np.sum(energy)
    error  = abs((etot - etot0)/etot0)

    return error
Пример #4
0
def evaluateStack(s, type, snap):
    op = s.pop()
    if debug_flag:
        print op
    if op in "+-*/^":
        op2 = evaluateStack(s, type, snap)
        op1 = evaluateStack(s, type, snap)
        return opn[op](op1, op2)
    elif op == "pi":
        return np.pi
    elif op == "e":
        return np.e
    elif op in functions1arg:
        operand = evaluateStack(s, type, snap)
        return getattr(np, op)(operand)
    elif op in functions2arg:
        operand2 = evaluateStack(s, type, snap)
        operand1 = evaluateStack(s, type, snap)
        return getattr(np, op)(operand1, operand2)
    elif op in _KnownQuantities():
        return UserQuantity(op).fetch(type, snap, "default")[1]
    elif op in snap.sim.GetIntAndFloatParameterKeys():
        return float(snap.sim.GetParam(op))
    elif re.search('^[-+]?[0-9]+$', op):
        return int(op)
    elif re.search('[-+]?[0-9]+[.][0-9]*', op):
        return float(op)
    else:
        raise ParseException("Unable to parse string: " + op)
Пример #5
0
def density_pdf(snap, type="default", nbin=32, rhomin="auto", rhomax="auto"):
    '''Calculate the probability density function of the density field'''

    rho = UserQuantity("rho").fetch(type, snap)[1]

    if rhomin == "auto": rhomin = np.amin(rho)
    if rhomax == "auto": rhomax = np.amax(rho)
    n = rho.size
    rho = np.log10(rho)

    bins = np.linspace(log10(rhomin), log10(rhomax), nbin + 1)
    #rhopdf = np.zeros(nbin+2)

    rhopdf = np.histogram(rho, bins=bins)[0]
    #binpos = np.digitize(rho,bins,right=True)
    #for i in range(n):
    #    rhopdf[binpos[i]] += 1

    rhopdf = np.float32(rhopdf)

    # Normalise logarithmic bins
    for j in range(nbin):
        rhopdf[j] = rhopdf[j] / (10**bins[j + 1] - 10**bins[j])

    print bins
    print rhopdf

    return bins[0:nbin], rhopdf
Пример #6
0
    def get_array(self, axis, snap):
        '''Helper function to get the array of the quantity on the x, y or
        rendered axis.

        Inputs:
            axis
                String with the desidered axis ('x', 'y' or 'render')
            snap
                Snapshot object

        Output:
            data
                Array containing data, in code units
            scaling_factor
                Scaling factor for unit conversion (multiply data by this
                number to get the requested unit)
            unitinfo
                UnitInfo object with the label and the name of the unit
            label
                Label of plotted quantity (string before the unit)
        '''

        quantity = getattr(self, axis + 'quantity')
        unit = getattr(self, axis + 'unit')

        unitinfo, data, scaling_factor, label = UserQuantity(quantity).fetch(
            self._type, snap, unit)

        return unitinfo, data, scaling_factor, label
Пример #7
0
    def mass(self, unit='default'):
        '''Returns total mass of gas inside blob'''

        mass_info = UserQuantity('m').fetch(self.type, self.snap, unit=unit)
        mass_type = mass_info[1]
        scaling_factor = mass_info[2]
        return mass_type[self.ids].sum() * scaling_factor
Пример #8
0
def time_derivative(snap, quantity, type="default", unit="default", id=None):
    '''Return for a given snapshot, the time derivative of a given quantity
    of a given type. If possible, use central difference. Otherwise, use
    forward/backward difference. If id is not specified, return an array with
    the quantity for each particle. Otherwise, return a scalar quantity only
    for the given particle.
    '''
    from data_fetcher import get_time_snapshot

    if unit != "default":
        raise NotImplementedError("""time_derivative implemented only with default units
        at the moment!""")

    # Find previous and next snapshots.  If first or last snapshot, then
    # return the current snapshot to compute a value
    try:
        snap1 = SimBuffer.get_previous_snapshot_from_object(snap)
    except BufferException:
        snap1 = snap
    try:
        snap2 = SimBuffer.get_next_snapshot_from_object(snap)
    except BufferException:
        snap2 = snap

    # Return array of values of quantity.  If either are empty, return nan
    quantityunitinfo, values1, quantityscaling_factor, label = UserQuantity(quantity).fetch(type, snap1)
    values2 = UserQuantity(quantity).fetch(type, snap2)[1]

    timeunitinfo, time, timescaling_factor, tlabel = get_time_snapshot(snap)
    scaling_factor = quantityscaling_factor/timescaling_factor
    unitinfo = UnitInfo()
    unitinfo.name= quantityunitinfo.name + "_" + timeunitinfo.name
    unitinfo.label= quantityunitinfo.label + "\\ " + timeunitinfo.label + "^{-1}"

    # Calculate the time derivative with central difference and return value
    tdiff = snap2.t - snap1.t
    if values1.size == 0 or values2.size == 0:
        timederiv = np.nan
    else:
        if id == None:
            timederiv = (values2 - values1)/tdiff
        else:
            timederiv = (values2[id] - values1[id])/tdiff
    return unitinfo, timederiv, scaling_factor, label+"_t"
Пример #9
0
    def SPH_velocities_sim_frame(self, unit='default'):
        '''Returns array of velocities of particles comprising gas blob'''

        ndim = self.snap.ndim
        velocities = np.zeros((self.n_particles(), ndim))
        first_coordinate_info = UserQuantity('vx').fetch(self.type,
                                                         self.snap,
                                                         unit=unit)
        scaling_factor = first_coordinate_info[2]
        velocities[:, 0] = first_coordinate_info[1][self.ids]
        if ndim > 1:
            velocities[:, 1] = UserQuantity('vy').fetch(self.type,
                                                        self.snap,
                                                        unit=unit)[1][self.ids]
        if ndim > 2:
            velocities[:, 2] = UserQuantity('vz').fetch(self.type,
                                                        self.snap,
                                                        unit=unit)[1][self.ids]
        return velocities * scaling_factor
Пример #10
0
    def SPH_positions_sim_frame(self, unit='default'):
        '''Returns array of positions of particles comprising gas blob'''

        ndim = self.snap.ndim
        positions = np.zeros((self.n_particles(), ndim))
        first_coordinate_info = UserQuantity('x').fetch(self.type,
                                                        self.snap,
                                                        unit=unit)
        scaling_factor = first_coordinate_info[2]
        positions[:, 0] = first_coordinate_info[1][self.ids]
        if ndim > 1:
            positions[:, 1] = UserQuantity('y').fetch(self.type,
                                                      self.snap,
                                                      unit=unit)[1][self.ids]
        if ndim > 2:
            positions[:, 2] = UserQuantity('z').fetch(self.type,
                                                      self.snap,
                                                      unit=unit)[1][self.ids]
        return positions * scaling_factor
Пример #11
0
def get_data(quantity, snap="current",type="default",sim="current",unit="default" ):
    '''Returns the array with the data for the given quantity.
    The data is returned scaled to the specified unit
    
    Required argument:
        quantity        :The quantity required. Must be a string
        
    Optional arguments:
        type            :The type of the particles (e.g. 'star')
        snap            :Number of the snapshot. Defaults to 'current'
        sim             :Number of the simulation. Defaults to 'current'
        unit            :Specifies the unit to use to return the data
    '''
    simno = get_sim_no(sim)
    sim = SimBuffer.get_sim_no(simno)
    snapobject = SimBuffer.get_snapshot_extended(sim, snap)
    nspecies = snapobject.GetNTypes()
    if type=="all":
        raise Exception("You requested all particle types to get_data, but we can return only one array!")
    fetcher=UserQuantity(quantity)
    unitinfo,data,scaling,label=fetcher.fetch(type=type,snap=snapobject,unit=unit)
    return data*scaling
Пример #12
0
def particle_data(snap, quantity, type="default", unit="default", id=None):
    '''Return for a given snapshot, a given quantity of a given type. If id is
not specified, return an array with the quantity for each particle. Otherwise,
return a scalar quantity only for the given particle.
'''
    unitinfo, values, scaling_factor, label = UserQuantity(quantity).fetch(type, snap, unit=unit)
    if values.size == 0:
        values_to_return = np.nan
    else:
        if id == None:
            values_to_return = values
        else:
            values_to_return = values[id]
    return unitinfo, values_to_return, scaling_factor, label
Пример #13
0
def structure_function(snap,
                       type="default",
                       nbin=8,
                       npoints=1000,
                       rmin=0.001,
                       rmax=10.0):
    '''Calculate the structure function for a given snapshot'''

    # Return all relevant particle data (positions and velocity)
    x = UserQuantity("x").fetch(type, snap)[1]
    y = UserQuantity("y").fetch(type, snap)[1]
    z = UserQuantity("z").fetch(type, snap)[1]
    vx = UserQuantity("vx").fetch(type, snap)[1]
    vy = UserQuantity("vy").fetch(type, snap)[1]
    vz = UserQuantity("vz").fetch(type, snap)[1]
    n = x.size
    r = np.zeros(n)
    vsqd = np.zeros(n)

    # Create logarithmic bins based on inputted range
    bins = np.linspace(log10(rmin), log10(rmax), nbin + 1)
    vsqdmean = np.zeros(nbin + 2)
    npart = np.zeros(nbin + 2)

    # Loop through a random selection of points
    for j in range(npoints):
        i = random.randrange(0, n - 1)
        x0 = x[i]
        y0 = y[i]
        z0 = z[i]
        vx0 = vx[i]
        vy0 = vy[i]
        vz0 = vz[i]

        r[:] = (x[:] - x0)**2
        r[:] += (y[:] - y0)**2
        r[:] += (z[:] - z0)**2
        r = np.log10(np.sqrt(r))

        vsqd[:] = (vx[:] - vx0)**2
        vsqd[:] += (vy[:] - vy0)**2
        vsqd[:] += (vz[:] - vz0)**2

        # Now discretise values into bins and sum up values
        binpos = np.digitize(r, bins, right=True)
        for jj in range(npoints):
            ii = random.randrange(0, n - 1)
            vsqdmean[binpos[ii]] += vsqd[ii]
            npart[binpos[ii]] += 1

    # Normalise velocity bins to arithmetic mean values
    for j in range(nbin):
        if npart[j] > 0: vsqdmean[j] = vsqdmean[j] / npart[j]

    vsqdmean = np.log10(vsqdmean)

    # Print out results when finished (for now)
    print bins
    print vsqdmean
    print npart

    return bins[0:nbin], vsqdmean[0:nbin]
Пример #14
0
def extract_discs(snapno,
                  sim,
                  type='default',
                  eccenlimit=0.9,
                  distancelimit=1.,
                  limiteigenvalues=0.2):
    '''This function takes a snapshot and a simulation number ("current" is
    also fine) and looks for which particles are bound to the stars. It
    returns a tuple, consisting of an Ambient_gas object (representing the
    gas that is not bound to any star) and of a list of Disc objects, one for
    each star.
    '''

    snap = SimBuffer.get_snapshot_extended(sim, snapno)

    parameters = dict(
        eccenlimit=eccenlimit,
        distancelimit=distancelimit,
        limiteigenvalues=limiteigenvalues,
    )

    # Query the number of dimensions
    ndim = snap.ndim

    # Fetch the data - we use code units

    # First extract coordinates, velocities and masses for the given type
    x_type = UserQuantity('x').fetch(type, snap)[1]
    vx_type = UserQuantity('vx').fetch(type, snap)[1]
    x_star = UserQuantity('x').fetch('star', snap)[1]
    vx_star = UserQuantity('vx').fetch('star', snap)[1]

    if ndim > 1:
        y_type = UserQuantity('y').fetch(type, snap)[1]
        vy_type = UserQuantity('vy').fetch(type, snap)[1]
        y_star = UserQuantity('y').fetch('star', snap)[1]
        vy_star = UserQuantity('vy').fetch('star', snap)[1]

    if ndim > 2:
        z_type = UserQuantity('z').fetch(type, snap)[1]
        vz_type = UserQuantity('vz').fetch(type, snap)[1]
        z_star = UserQuantity('z').fetch('star', snap)[1]
        vz_star = UserQuantity('vz').fetch('star', snap)[1]

    m_type = UserQuantity('m').fetch(type, snap)[1]
    m_star = UserQuantity('m').fetch('star', snap)[1]

    n_star = snap.GetNparticlesType('star')

    if ndim == 2:
        owner = extract_disc_cython.flag_owner2d(x_type, y_type, vx_type,
                                                 vy_type, m_type, x_star,
                                                 y_star, vx_star, vy_star,
                                                 m_star, parameters)
    elif ndim == 3:
        owner = extract_disc_cython.flag_owner3d(x_type, y_type, z_type,
                                                 vx_type, vy_type, vz_type,
                                                 m_type, x_star, y_star,
                                                 z_star, vx_star, vy_star,
                                                 vz_star, m_star, parameters)

    # Loops over all stars and creates the disc objects
    disclist = []
    for istar in range(n_star):
        ids = (owner == istar)
        disc = Disc(istar, ids, snap, type)
        disclist.append(disc)
        print 'mass disc number', istar, ':', disc.mass()

    # Create the ambient gas object
    ids = (owner == -1)
    ambient = Ambient_gas(ids, snap, type)
    print 'ambient gas mass:', ambient.mass()

    # Return a tuple with the ambient gas and a list of discs
    return (ambient, disclist)