def getVelCM(group): """Finds and returns a COM velocity vector for a given group.""" mass = charm.getAttributeSum(group, 'gas', 'mass') mass += charm.getAttributeSum(group, 'star', 'mass') mass += charm.getAttributeSum(group, 'dark', 'mass') vmoment = charm.reduceParticle(group, centMassVelMap, centMassReduce, None)[0][1:4] vcm = (vmoment[0]/mass, vmoment[1]/mass, vmoment[2]/mass) return vcm #return the COM velocity vector
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)
def getFamilyAttributeSum(center2,r,family,attribute): """Integrates attributes of a given family over a given sphere.""" charm.createGroupAttributeSphere('group', 'All', 'position', center2[0], center2[1], center2[2], r) charm.createGroup_Family('group','group',family) sum = charm.getAttributeSum('group', family, attribute) charm.deleteGroup('group') return sum
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
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
def getVelCMStars(center2, radius): "Returns the vector for the center of mass velocity of a group of stars defined by center2 coordinates and a radius." charm.createGroupAttributeSphere('tmpGal', 'All', 'position', center2[0], center2[1], center2[2], radius) #use cmVelCompare2.py to choose length charm.createGroup_Family('tmpStarGroup', 'tmpGal', 'star') #select star particles only massStar = charm.getAttributeSum('tmpGal', 'star', 'mass') mass = massStar #calculate total mass vmomentStar = charm.reduceParticle('tmpStarGroup', centMassVelMap, centMassReduce, None) vmoment = [vmomentStar[0][1],vmomentStar[0][2],vmomentStar[0][3]] vcm = (vmoment[0]/mass, vmoment[1]/mass, vmoment[2]/mass) #Clean up charm.deleteGroup('tmpGal') charm.deleteGroup('tmpStarGroup') return vcm #return the COM velocity vector
def boxstat(group, family='all') : """Print statistics for a group as in the tipsy boxstat command Arguments are group and family Return physical parameters of particles: number, mass, center of box, size of box, center of mass, center of mass's velocity, angular momentum vector. Format output to say if gas, dark, star, baryon, or all. Check error cases: Bad input, Not a proper data type, Box not loaded.""" import charm # check if simulation loaded if charm.getGroups() == None : raise StandardError('Simulation not loaded') # There is a potential issue with the capitalization of "all" being mixed # in different implementations. Take either. if family == 'All': family = 'all' if group == 'all': group = 'All' # Prepare values based on selected family if family == 'all': nPartGas = charm.getNumParticles(group, 'gas') nPartDark = charm.getNumParticles(group, 'dark') nPartStar = charm.getNumParticles(group, 'star') mass = charm.getAttributeSum(group, 'gas', 'mass') mass += charm.getAttributeSum(group, 'dark', 'mass') mass += charm.getAttributeSum(group, 'star', 'mass') bBox = list(charm.getAttributeRangeGroup(group, 'gas', 'position')) bBoxTmp = charm.getAttributeRangeGroup(group, 'dark', 'position') bBox[0] = map(lambda x, y : min(x,y), bBox[0], bBoxTmp[0]) bBox[1] = map(lambda x, y : max(x,y), bBox[1], bBoxTmp[1]) bBoxTmp = charm.getAttributeRangeGroup(group, 'star', 'position') bBox[0] = map(lambda x, y : min(x,y), bBox[0], bBoxTmp[0]) bBox[1] = map(lambda x, y : max(x,y), bBox[1], bBoxTmp[1]) groupfamname = group elif family == 'baryon': nPartGas = charm.getNumParticles(group, 'gas') nPartStar = charm.getNumParticles(group, 'star') mass = charm.getAttributeSum(group, 'gas', 'mass') mass += charm.getAttributeSum(group, 'star', 'mass') bBox = list(charm.getAttributeRangeGroup(group, 'gas', 'position')) bBoxTmp = charm.getAttributeRangeGroup(group, 'star', 'position') bBox[0] = map(lambda x, y : min(x,y), bBox[0], bBoxTmp[0]) bBox[1] = map(lambda x, y : max(x,y), bBox[1], bBoxTmp[1]) groupfamname = group else : nPart = charm.getNumParticles(group, family) mass = charm.getAttributeSum(group, family, 'mass') bBox = charm.getAttributeRangeGroup(group, family, 'position') groupfamname = group + 'FAM' + family charm.createGroup_Family(groupfamname, group, family) # Derive box properties size = map(lambda min, max : max - min, bBox[0], bBox[1]) center = map(lambda min, max : 0.5*(max + min), bBox[1], bBox[0]) mmoment = charm.reduceParticle(groupfamname, centmassmap, centmassreduce, None) cm = [mmoment[0][1]/mass, mmoment[0][2]/mass, mmoment[0][3]/mass] vmoment = charm.reduceParticle(groupfamname, centmassVelmap, centmassreduce, None) vcm = [vmoment[0][1]/mass, vmoment[0][2]/mass, vmoment[0][3]/mass] angmom1 = charm.reduceParticle(groupfamname, angmomMap, centmassreduce, None) # Apply parallel axis theorem and make specific angmom = [0,0,0] angmom[0] = (angmom1[0][1] - mass*(cm[1]*vcm[2] - cm[2]*vcm[1]))/mass angmom[1] = (angmom1[0][2] - mass*(cm[2]*vcm[0] - cm[0]*vcm[2]))/mass angmom[2] = (angmom1[0][3] - mass*(cm[0]*vcm[1] - cm[1]*vcm[0]))/mass # Write output header according to type of particles if family == 'all' : print 'number of dark, gas and star particles =', nPartDark, nPartGas, nPartStar elif family == 'baryon' : print 'number of baryon particles =', (nPartGas + nPartStar) else: print 'number of', family, 'particles =', nPart # Write physical parameters print 'mass =', mass print 'center coordinates =', center print 'size =', size print 'center of mass coordinates =', cm print 'center of mass velocity =', vcm print 'angular momentum vector =', angmom