Ejemplo n.º 1
0
def getEpsilonDist(group='gal', nBins=50, epsCut=2., center='pot'):
    """Returns a histogram of dimension 2 x nbins of stellar epsilons (jz/jcirc) and mass-fraction.  epsCut defines the histogram bound in both directions. Center can be either 'pot' or 'com'"""
    numRotBins   = 400 #number of points at which we linearly interpolate 
    radiusVCM    = 0.25 #fraction of group radius to use when calculating COM velocity
    radiusAngMom = 0.25 #fraction of group radius to use when calculating stellar angular momentum
    
    
    a = charm.getTime()
    if ((group in charm.getGroups()==False)) & (group !='gal'):
        print "Group does not exist, please try again."
        return
    if (group == 'gal'): 
        rgal = quesoConfig.rgalFraction*virialgroup.getVirialGroup()
        center=findcenter.findCenter(group2='virialGroup', method=center)
        charm.createGroupAttributeSphere('gal', 'All', 'position', center[0], center[1], center[2], rgal)
    else:
        center=findcenter.findCenter(group2=group, method=center)
        
    # Find maximum radius
    charm.createGroup_Family('tmp',group,'star')
    maxRad = getgroupradius.getGroupRadius('tmp', center)
    massDist = [0]*(numRotBins+1)
    rad = [0]*(numRotBins+1)
    radialStep = maxRad/numRotBins
    #populate mass bins
    for i in range(numRotBins+1): 
        charm.createGroupAttributeSphere('tmp', 'All', 'position', center[0], center[1], center[2], radialStep*i)
        massDist[i]  = charm.getAttributeSum('tmp','star','mass')
        massDist[i] += charm.getAttributeSum('tmp','dark','mass')
        massDist[i] += charm.getAttributeSum('tmp','gas' ,'mass')
        #Note: I tried shells instead of spheres and it made no real difference.
        rad[i] = radialStep*i
        
    vCM = getVelCMStars(center2=center, radius=radiusVCM*maxRad) #COM velocity
    angMomVec = getNormalStarAngMom(center2=center, radius=radiusAngMom*maxRad, comVel=vCM) #Ang Mom Velocity
    #vCM = getVelCMStars(center2=center, radius=10/(a*quesoConfig.kpcunit)) #COM velocity
    #angMomVec = getNormalStarAngMom(center2=center, radius=6/(a*quesoConfig.kpcunit), comVel=vCM) #Ang Mom Velocity
    
    param = (center, vCM, angMomVec, maxRad, numRotBins,massDist, nBins,epsCut)
    charm.createGroupAttributeSphere('tmp', 'All', 'position', center[0], center[1], center[2], maxRad)
    charm.createGroup_Family('tmp',group,'star')
    #calc total stellar mass for mass weighted average
    reduceResult = charm.reduceParticle('tmp', mapEpsilon, reduceEpsilon, param) 
    sMass = charm.getAttributeSum('tmp','star', 'mass')
    epsilonDist = [0]*nBins
    eps  = [0]*nBins
    for i in range(nBins): eps[i] = -epsCut+ 2*epsCut/nBins*(i)
    for i in range(len(reduceResult)):
        try:
            bin = reduceResult[i][0]
            epsilonDist[bin] = reduceResult[i][1]/sMass #return the mass fraction
        except:{}
    return (eps, epsilonDist)
Ejemplo n.º 2
0
def calcGalacticCoordinates(angMomGroup=None, center ='pot'):
    '''Assigns particles a position in the galactic coordinate system. galVelocity = (v+Hr).  angMomGroup'''
    #===========================================================================
    # --Overview--
    # 1.Form transformation matrix
    # 2.Translate the coordinates to the center of the galaxy (or COM velocity)
    # 3.Rotate the coordinate system to be aligned with the angular momentum vector
    # 4.Write information to vector attributes
    #===========================================================================
    if ((angMomGroup in charm.getGroups())==False) & (angMomGroup!=None):
        print "Group does not exist, please try again."
        return
    ##############################
    # Actual Routine
    ##############################
    if (angMomGroup==None):
        angMomGroup = 'angMomGroup'
        cnt = findcenter.findCenter(method=center)
        virialRadius = virialgroup.getVirialGroup()
        charm.createGroupAttributeSphere('angMomGroup', 'All', 'position', cnt[0], cnt[1], cnt[2], virialRadius*quesoConfig.rgalFraction)
        charm.createGroup_Family('angMomGroup', 'angMomGroup', 'gas')
        charm.createGroup_AttributeRange('angMomGroup', 'angMomGroup', 'temperature', 0, quesoConfig.coldGasTemp)
    else: 
        cnt = findcenter.findCenter(group2=angMomGroup,method=center)
        
    angmom.getAngMomVector(group=angMomGroup,center=center)
    # Transformation Matrix
    galZ = vectormath.normalizeVector(angmom.getAngMomVector(group=angMomGroup,center=center))
    galX = vectormath.normalizeVector(vectormath.crossVectors((0,1,0),galZ))
    galY = vectormath.normalizeVector(vectormath.crossVectors(galZ,galX))
    transMatrix = (galX,
                   galY,
                   galZ)
    
    fHubble       = quesoConfig.fHubble0*math.sqrt(quesoConfig.omega0/charm.getTime()**3+(1-quesoConfig.omega0))
    # Galactic Position                    
    charm.createVectorAttribute('star','galPosition')
    charm.createVectorAttribute('gas', 'galPosition')
    charm.createVectorAttribute('dark','galPosition')
    param = (cnt, transMatrix)
    charm.runLocalParticleCodeGroup('All', calcGalPosition, param)
    # Galactic velocity
    vCM=angmom.getVelCM(angMomGroup)
    param = (cnt, transMatrix,vCM, fHubble)
    charm.createVectorAttribute('star','galVelocity')
    charm.createVectorAttribute('gas', 'galVelocity')
    charm.createVectorAttribute('dark','galVelocity')
    charm.runLocalParticleCodeGroup('All', calcGalVelocity, param)
    return
Ejemplo n.º 3
0
def getMomentInertiaTensor(group2,center='pot'):
    '''Return the moment of inertia tensor for given group.  center can be 'pot' or 'com'.  This is in physical units.
        [[Ixx, Ixy, Ixz],
         [Iyx, Iyy, Iyz],
         [Izx, Izy, Izz]]
    '''
    group = group2
    if ((group2 in charm.getGroups())==False):
        print "Group does not exist, please try again."
        return
    center = findcenter.findCenter(group2=group,method=center)
    triangleTensor = charm.reduceParticle(group , mapMomentInertiaTensor, reduceMomentInertiaTensor, center)[0][1]
    fullTensor = [[0]*3,[0]*3,[0]*3]
    units = quesoConfig.msolunit*((charm.getTime()*quesoConfig.kpcunit)**2)
    fullTensor[0] = vectormath.multVectorScalar(units, triangleTensor[0][0:3])
    fullTensor[1] = vectormath.multVectorScalar(units, [triangleTensor[0][1],triangleTensor[1][0],triangleTensor[1][1]])
    fullTensor[2] = vectormath.multVectorScalar(units, [triangleTensor[0][2],triangleTensor[1][1],triangleTensor[2][0]])
    return fullTensor
Ejemplo n.º 4
0
def getHalfMassRadius(group, center='pot') :
    """Returns the current stellar half mass radius."""
    #get the current galactic stellar mass
    rgal = 0.1*virialgroup.getVirialGroup()
    center = findcenter.findCenter(group2=group,method=center)
    halfMass = getFamilyAttributeSum(center,rgal,'star','mass')/2.0
    if (halfMass == 0 ): 
        print "Halfmass is zero inside rgal.  Are there stars inside rgal yet?." 
        return (0,0)
    #Bisection Method to locate half mass
    epsilon = .01
    count = 0
    maxIterations = 50
    a = charm.getTime()
    leftr = .1/(a*quesoConfig.kpcunit)
    rightr = 50/(a*quesoConfig.kpcunit)
    midpoint = (leftr + rightr)/2.0
    leftMass  = getFamilyAttributeSum(center,leftr   ,'star','mass')-halfMass  #Initialize values
    rightMass = getFamilyAttributeSum(center,rightr  ,'star','mass')-halfMass #offset to find root  
    midMass   = getFamilyAttributeSum(center,midpoint,'star','mass')-halfMass #offset so we can find root
    #Bisection to find halfmass radius using initialMass and mass
    #Run until values converge within epsilon or reach max count
    while (count<maxIterations) and (math.fabs((leftMass-rightMass)/halfMass) > epsilon*2.0):
        midpoint = (leftr + rightr)/2.0
        
        #if (math.fabs(leftMass-rightMass)/halfMass < 4*epsilon):break
        leftMass = getFamilyAttributeSum(center,leftr   ,'star','mass')-halfMass  #Initialize values
        rightMass= getFamilyAttributeSum(center,rightr  ,'star','mass')-halfMass #offset to find root  
        midMass  = getFamilyAttributeSum(center,midpoint,'star','mass')-halfMass #offset so we can find root
        #print str((leftMass,midMass,rightMass)) + "    " + str(math.fabs(leftMass-rightMass)/halfMass) +str((leftr,midpoint,rightr))
        if (leftMass*midMass<0)   : rightr = midpoint
        elif (rightMass*midMass<0): leftr  = midpoint
        elif (midMass==0)         : break
        elif (leftMass*midMass>0) and (rightMass*midMass>0):
            print "\nStellar half mass radius will not converge. Try larger bounds."
            return
        count += 1
    #Don't get stuck in a loop
    if (count==maxIterations): 
        print "\nDid not converge in " + str(maxIterations) + " iterations.  Try smaller bounds or raise epsilon in source."
        return
    resultVec=midpoint #already in units of kpc taking into account the expansion factor
    #print resultVec[i]
    return resultVec
Ejemplo n.º 5
0
def getAngMomVector(group, center='pot'):
    """Returns specific angular momentum vectors in physical units.  Center can be 'pot' or 'com'"""
    if ((group in charm.getGroups())==False):
        print "Group does not exist, please try again."
        return
    def multVectorScalar(scalar,vector):
        return (vector[0]*scalar,vector[1]*scalar,vector[2]*scalar)
    center = findcenter.findCenter(group2=group,method=center)
    #find COM Velocity
    vCM=getVelCM(group)
    
    angMomVector  = charm.reduceParticle(group, getParticleAngMomentum, sumAngMomentum, [center,vCM]) 
    mass   = charm.getAttributeSum(group, 'gas',  'mass')
    mass  += charm.getAttributeSum(group, 'star', 'mass')
    mass  += charm.getAttributeSum(group, 'dark', 'mass')
    unitConvert = quesoConfig.kpcunit*quesoConfig.velocityunit #masses are divided out anyway.
    #Convert this into a specific angular momentum 3-vector
    angMomVector    = multVectorScalar(unitConvert/mass, (angMomVector[0][1] ,angMomVector[0][2] ,angMomVector[0][3]))
    return angMomVector
Ejemplo n.º 6
0
def getVirialGroup(group="All", center2="pot", virialGroup="virialGroup"):
    """This method returns the virial radius of a given group, bases around a center that can be given by one of three options: Default 'pot' finds the potential minimum, 'com' uses the center of mass, or a tuple of length 3 can be given.  virialGroup specifies the group name of the resulting """
    global center
    if center2 == "pot":
        cnt = findcenter.findCenter(group2=group, method="pot")
    elif center2 == "com":
        cnt = findcenter.findCenter(group2=group, method="com")
    elif len(center2) == 3:
        cnt = center2
    center = cnt  # use center variable at later times.
    # ===========================================================================
    # Use center coordinates to find virial radius and return group
    # Returns virial radius in sim units via bisection method.
    # If this doesn't converge, try larger bounds or adjust the
    # other parameters in source.
    # ===========================================================================
    def getGalDensity(center2, r):
        charm.createGroupAttributeSphere(virialGroup, "All", "position", center[0], center[1], center[2], r)
        totMass = 0.0
        for fam in charm.getFamilies():
            totMass += charm.getAttributeSum(virialGroup, fam, "mass")
        v = (4 * math.pi / 3.0) * r ** 3
        density = totMass / v
        return density

    # ================================================================
    # Specify bounds of bisection.  Default is 0.1 to 400kpc (at redshift zero)
    epsilon = 0.001  # maximum error in density convergence
    count = 0
    maxIterations = 200
    leftr = 0.1 / quesoConfig.kpcunit
    rightr = 4000.0 / quesoConfig.kpcunit
    # ================================================================
    from queso.quesoConfig import virialRadiusDensity

    midpoint = (leftr + rightr) / 2
    leftDensity = getGalDensity(center, leftr) - virialRadiusDensity  # Initialize values
    rightDensity = getGalDensity(center, rightr) - virialRadiusDensity  # offset so we can find root
    midDensity = getGalDensity(center, midpoint) - virialRadiusDensity  # offset so we can find root
    # Bisection to find virial radius as defined in quesoConfig
    # Run until values converge within epsilon or reach max count
    while (count < maxIterations) & (math.fabs(leftDensity - rightDensity) > epsilon):
        midpoint = (leftr + rightr) / 2
        leftDensity = getGalDensity(center, leftr) - virialRadiusDensity  # offset so we can find root
        rightDensity = getGalDensity(center, rightr) - virialRadiusDensity  # offset so we can find root
        midDensity = getGalDensity(center, midpoint) - virialRadiusDensity  # offset so we can find root
        if leftDensity * midDensity < 0:
            rightr = midpoint
        elif rightDensity * midDensity < 0:
            leftr = midpoint
        elif midDensity == 0:
            break
        elif (leftDensity * midDensity > 0) & (rightDensity * midDensity > 0):
            print "\nVirial radius calculation will not converge. Try larger bounds."
            return
        count += 1
    # Don't get stuck in a loop
    if count == maxIterations:
        print "\nDid not converge in " + str(
            maxIterations
        ) + " iterations.  Try smaller bounds or raise epsilon in source."
        return
    charm.createGroupAttributeSphere(virialGroup, "All", "position", center[0], center[1], center[2], midpoint)
    return midpoint  # in sim units