Extracting minor mergers from TNG

Claire Ye
  • 8 Jul

Hi TNG Team!

I have a few questions regarding extracting full merger trees from the TNG simulations. I've been following the Python tutorial to extract the mass and snapshot number of minor mergers in TNG50, along with the mass of the subhalo they merge into. To do this, I modified the numMergers function from sublink.py.

As this is my first time working with the TNG data, I wanted to check whether my extraction approach is correct. I’ve attached the Python code I'm using--would you mind taking a quick look? Specifically, is fpMass = maxPastMass(tree, fpIndex, massPartType) always the stellar mass of the current FirstProgenitor subhalo (when massPartType=4)? I'm also wondering if I matched the IDs, masses, and snapshot numbers of the subhalos when I added them to a python dictionary since I'm unsure about the fpIndex and npIndex and where they're pointing to.

In addition, is it possible to extract the distance between the center of mass of the NextProgenitor subhalos and the center of mass of the FirstProgenitor subhalo from the merger tree or snapshots before they merge?

#Find the massive halos
basePath = '../sims.TNG/TNG50-1/output/'
ste_mass_min = 5*10**10/mass_unit_TNG

groupfields = ['GroupFirstSub', 'GroupMassType'] 
GroupFirstSub = il.groupcat.loadHalos(basePath,99,fields=groupfields)
groupids = GroupFirstSub['GroupFirstSub'] 
groupmass_star = GroupFirstSub['GroupMassType'][:,4]

selected_ids = groupids[groupmass_star>=ste_mass_min]
selected_m_star = groupmass_star[groupmass_star>=ste_mass_min]

#Using one id (selected_ids[3]) as an example
fields = ['SubhaloMass','SubfindID','SnapNum','SubhaloID','NextProgenitorID','SubhaloMassType', 'MainLeafProgenitorID','FirstProgenitorID',]
tree = il.sublink.loadTree(basePath, 99, selected_ids[3],fields=fields)

def Merger_Histories(tree, minMassRatio=1e-10, massPartType='stars',index=0, alongFullTree=True):  #copy from sublink.py
   """ Calculate the number of mergers, along the main progenitor branch, in this sub-tree (optionally above some mass ratio threshold). If alongFullTree, count across the full
   sub-tree and not only along the MPB. """
   # verify the input sub-tree has the required fields
   reqFields = ['SubhaloID', 'NextProgenitorID', 'MainLeafProgenitorID',
                'FirstProgenitorID', 'SubhaloMassType']

   if not set(reqFields).issubset(tree.keys()):
       raise Exception('Error: Input tree needs to have loaded fields: '+','.join(reqFields))

   num = 0
   #invMassRatio = 1.0 / minMassRatio
   dictTree = {}

   # walk back main progenitor branch
   rootID = tree['SubhaloID'][index]
   fpID   = tree['FirstProgenitorID'][index]

   while fpID != -1:
       fpIndex = index + (fpID - rootID)
       fpMass  = maxPastMass(tree, fpIndex, massPartType)

       if fpMass<10**10/mass_unit_TNG:
           break

       dictTree[str(fpID)] = {'Mstar': fpMass, 'Progen_ID':[fpID], 'Progen_Mass':[tree['SubhaloMassType'][fpIndex][partTypeNum('star')]],
                               'Progen_SnapNum':[tree['SnapNum'][fpIndex]]}

       # explore breadth
       npID = tree['NextProgenitorID'][fpIndex]

       while npID != -1:
           npIndex = index + (npID - rootID)
           npMass  = maxPastMass(tree, npIndex, massPartType)

           # count if both masses are non-zero, and ratio exceeds threshold
           if fpMass > 0.0 and npMass > 0.0:
               ratio = npMass / fpMass

               #if ratio >= minMassRatio and ratio <= invMassRatio:
               #    num += 1

               if npMass>=5*10**6/mass_unit_TNG and ratio <= 0.1:
                   num+=1

                   dictTree[str(fpID)]['Progen_ID'].append(npID)
                   dictTree[str(fpID)]['Progen_Mass'].append(npMass)

                   dictTree[str(fpID)]['Progen_SnapNum'].append(tree['SnapNum'][npIndex])

           npID = tree['NextProgenitorID'][npIndex]

           # count along full tree instead of just along the MPB? (non-standard)
           if alongFullTree:
               if tree['FirstProgenitorID'][npIndex] != -1:
                   numSubtree, dictSubtree = Merger_Histories(tree, minMassRatio=minMassRatio, massPartType=massPartType, index=npIndex, alongFullTree=True)
                   num += numSubtree
                   dictTree.update(dictSubtree)

       fpID = tree['FirstProgenitorID'][fpIndex]

   return num, dictTree

Thank you so much for you help!

Best,
Claire

Dylan Nelson
  • 13 Jul

You can see the code of maxPastMass(), it is very simple, and can also be changed if you need to.

The first and next progenitor indices are shown schematically on the merger tree diagram.

You can certainly save the SubhaloPos of all the relevant subhalos in your dict as well, and then calculate distances between these positions.

Claire Ye
  • 15 Jul

Hi Dylan,

Thank you for your reply. After re-staring at the merger tree diagram, I have some follow-up questions. There are subhalos from different fof groups that merge into the main branch the diagram is showing (i.e., 5-7). Do these subhalos that belonging to a different fof group merge with the main branch because of galaxy flybys? In addition, how is a subhalo merger defined (e.g., by distance)?

Thank you again,
Claire

Dylan Nelson
  • 15 Jul

A subhalo merger is the event that occurs because a subhalo ceases to exist (in the Subfind catalog). Meaning, it existed in the previous snapshot, but in the current snapshot it no longer exists (its particles have been given to another subhalo, the merger descendant).

A flyby, where by definition the subhalo still exists after the event, is not a merger. In fact, such events are not captured in the merger trees. To find them, you would have to do a separate analysis.

The merger of a subhalo from a different FoF group is the normal picture you should have in mind. In general, two (massive) galaxies originally each sit in their own FoF groups. When these two halos come together, the FoF groups combine. If there are enough snapshots, you may then see one of the two galaxies as a second subhalo of this FoF, and then it would eventually merge. If there aren't enough snapshots, or the merger is quick enough, you may never see this phase, i.e. it will look like a central subhalo of a separate FoF merges into the central subhalo of a different FoF.

Claire Ye
  • 25 Jul

Thanks for your help. I've been able to extract the merger trees. I'm hoping to track the inspiral of a dwarf galaxy into a major galaxy until they merge but realized that the subhaloIDs change in different snapshots. If subhalo1 (the dwarf galaxy) merge with subhalo0 at snapshot 99, the merger tree provides their relative positions at snapshot 98. However, is it possible to also get their positions at snapshot 97 and lower, especially if snaphalo1 doesn't have a merger event beyond snapshot 98?

Dylan Nelson
  • 26 Jul

Yes the merger trees provide connections between subhalos at all previous snapshots, not just the immediately prior snapshot.

Claire Ye
  • 11 Aug

Hi Dylan,

About the distances between subhalos and central halos at the snapshot immediately before they merge, I found that some of the distances can be as large as ~1000 kpc. The central halo I'm looking at is the most massive one in TNG50 at redshift z=0 (or the one with the most massive history). I'm surprised that the distances right before merger can be this large. Is there a physical reason that some of the distances can be ~1000 kpc or does it seem like I made mistakes in my calculation? I checked my unit conversion (1/((1+z)*h)) * vectordistance(SubhaloPos0-SubhaloPos1) and it looks correct to me.

Thank you,
Claire

Dylan Nelson
  • 18 Aug

Keep in mind the "merger" is, by definition, the snapshot where one of the two subhalos no longer exists (i.e. is no longer identified by Subfind).

1 Mpc is about the virial radius of a large halo, so if an infalling satellite is disrupted/destroyed shortly after infall, it could "merge" at such a distance.

It could also be moving quite fast (you can look at the relative velocity, multiplied by the time between snapshots, to get a sense of if it could have made it close to the halo center).

  • Page 1 of 1