Restarting a binary¶
COSMIC allows you to restart a binary from any point in its evolution from a COSMIC generated bpp array.
In [1]: from cosmic.sample.initialbinarytable import InitialBinaryTable
In [2]: from cosmic.evolve import Evolve
Below we provide an example of the same evolutionary track started from the beginning and three different points in the evolution:
sometime between the beginning and the first object going supernova
between the first and second supernova
after both supernova
In [3]: single_binary = InitialBinaryTable.InitialBinaries(m1=25.543645, m2=20.99784, porb=446.795757, ecc=0.448872, tphysf=13700.0, kstar1=1, kstar2=1, metallicity=0.002)
In [4]: BSEDict = {'xi': 1.0, 'bhflag': 1, 'neta': 0.5, 'windflag': 3, 'wdflag': 1, 'alpha1': 5.0, 'pts1': 0.001, 'pts3': 0.02, 'pts2': 0.01, 'epsnov': 0.001, 'hewind': 0.5, 'ck': 1000, 'bwind': 0.0, 'lambdaf': 0.0, 'mxns': 3.0, 'beta': -1.0, 'tflag': 1, 'acc2': 1.5, 'remnantflag': 3, 'ceflag': 0, 'eddfac': 1.0, 'ifflag': 0, 'bconst': 3000, 'sigma': 265.0, 'gamma': -2.0, 'pisn': 45.0, 'natal_kick_array' : [[-100.0,-100.0,-100.0,-100.0,0.0], [-100.0,-100.0,-100.0,-100.0,0.0]], 'bhsigmafrac' : 1.0, 'polar_kick_angle' : 90, 'qcrit_array' : [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0], 'cekickflag' : 2, 'cehestarflag' : 0, 'cemergeflag' : 0, 'ecsn' : 2.5, 'ecsn_mlow' : 1.4, 'aic' : 1, 'ussn' : 0, 'sigmadiv' :-20.0, 'qcflag' : 1, 'eddlimflag' : 0, 'fprimc_array' : [2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0,2.0/21.0], 'bhspinflag' : 0, 'bhspinmag' : 0.0, 'rejuv_fac' : 1.0, 'rejuvflag' : 0, 'htpmb' : 1, 'ST_cr' : 1, 'ST_tide' : 0, 'bdecayfac' : 1, 'randomseed' : -1235453, 'grflag' : 1, 'rembar_massloss' : 0.5, 'kickflag' : 1, 'zsun' : 0.014, 'grflag' : 1, 'bhms_coll_flag' : 0, 'don_lim' : -1, 'acc_lim' : -1, 'rtmsflag' : 0, 'wd_mass_lim': 1}
In [5]: for i in [3, 7, 11]:
...: bpp, bcm, initC, kick_info = Evolve.evolve(initialbinarytable=single_binary, BSEDict=BSEDict)
...: for column in bpp.columns:
...: initC = initC.assign(**{column:bpp.iloc[i][column]})
...: bpp_mid, bcm_mid, initC_mid, kick_info = Evolve.evolve(initialbinarytable=initC, BSEDict={})
...: if i == 3:
...: print("From beginning")
...: print(bpp)
...: print("Started in middle at Index {0}".format(i))
...: print(bpp_mid)
...:
From beginning
tphys mass_1 mass_2 ... bhspin_1 bhspin_2 bin_num
0 0.000000 25.543645 20.997840 ... 0.0 0.0 0
0 7.710210 24.912154 20.771614 ... 0.0 0.0 0
0 7.721745 24.907454 20.771066 ... 0.0 0.0 0
0 8.032373 24.637985 20.771096 ... 0.0 0.0 0
0 8.118834 23.485300 21.763718 ... 0.0 0.0 0
0 8.118834 23.485300 21.763718 ... 0.0 0.0 0
0 8.118834 8.667346 21.763718 ... 0.0 0.0 0
0 8.118834 8.667346 21.763718 ... 0.0 0.0 0
0 8.475465 8.308986 21.742361 ... 0.0 0.0 0
0 8.508776 8.257190 21.740508 ... 0.0 0.0 0
0 8.508776 7.757190 21.740508 ... 0.0 0.0 0
0 9.733484 7.757206 21.659308 ... 0.0 0.0 0
0 9.744085 7.757291 21.656867 ... 0.0 0.0 0
0 9.748186 7.758263 21.651144 ... 0.0 0.0 0
0 9.924034 7.817984 19.332325 ... 0.0 0.0 0
0 9.924034 7.817984 19.332325 ... 0.0 0.0 0
0 9.924034 7.817984 6.622061 ... 0.0 0.0 0
0 9.924034 7.817984 6.622061 ... 0.0 0.0 0
0 10.654655 7.835389 6.331263 ... 0.0 0.0 0
0 10.705711 7.838450 6.290103 ... 0.0 0.0 0
0 10.705711 7.838450 1.675145 ... 0.0 0.0 0
0 13700.000000 7.838450 1.675145 ... 0.0 0.0 0
[22 rows x 44 columns]
Started in middle at Index 3
tphys mass_1 mass_2 ... bhspin_1 bhspin_2 bin_num
0 8.032373 24.637985 20.771096 ... 0.0 0.0 0
0 8.118986 23.475794 21.772953 ... 0.0 0.0 0
0 8.118986 23.475794 21.772953 ... 0.0 0.0 0
0 8.118986 8.667779 21.772953 ... 0.0 0.0 0
0 8.118986 8.667779 21.772953 ... 0.0 0.0 0
0 8.475461 8.309496 21.751553 ... 0.0 0.0 0
0 8.508770 8.257698 21.749694 ... 0.0 0.0 0
0 8.508770 7.757698 21.749694 ... 0.0 0.0 0
0 9.735862 7.757713 21.668160 ... 0.0 0.0 0
0 9.746470 7.757798 21.665712 ... 0.0 0.0 0
0 9.750553 7.758765 21.660049 ... 0.0 0.0 0
0 9.929751 7.819623 19.251575 ... 0.0 0.0 0
0 9.929751 7.819623 19.251575 ... 0.0 0.0 0
0 9.929751 7.819623 6.633627 ... 0.0 0.0 0
0 9.929751 7.819623 6.633627 ... 0.0 0.0 0
0 10.655673 7.836718 6.342619 ... 0.0 0.0 0
0 10.706576 7.839724 6.301393 ... 0.0 0.0 0
0 10.706576 7.839724 1.677151 ... 0.0 0.0 0
0 13708.032373 7.839724 1.677151 ... 0.0 0.0 0
[19 rows x 44 columns]
Started in middle at Index 7
tphys mass_1 mass_2 ... bhspin_1 bhspin_2 bin_num
0 8.475465 8.308986 21.742361 ... 0.0 0.0 0
0 8.508776 8.257190 21.740508 ... 0.0 0.0 0
0 8.508776 7.757190 21.740508 ... 0.0 0.0 0
0 9.733484 7.757206 21.659308 ... 0.0 0.0 0
0 9.744085 7.757291 21.656867 ... 0.0 0.0 0
0 9.748186 7.758265 21.651121 ... 0.0 0.0 0
0 9.923706 7.817875 19.328905 ... 0.0 0.0 0
0 9.923706 7.817875 19.328905 ... 0.0 0.0 0
0 9.923706 7.817875 6.621344 ... 0.0 0.0 0
0 9.923706 7.817875 6.621344 ... 0.0 0.0 0
0 10.654718 7.835284 6.330535 ... 0.0 0.0 0
0 10.705783 7.838346 6.289379 ... 0.0 0.0 0
0 10.705783 7.838346 1.675016 ... 0.0 0.0 0
0 13708.118834 7.838346 1.675016 ... 0.0 0.0 0
[14 rows x 44 columns]
Started in middle at Index 11
tphys mass_1 mass_2 ... bhspin_1 bhspin_2 bin_num
0 9.744085 7.757291 21.656867 ... 0.0 0.0 0
0 9.748186 7.758263 21.651144 ... 0.0 0.0 0
0 9.924034 7.817984 19.332325 ... 0.0 0.0 0
0 9.924034 7.817984 19.332325 ... 0.0 0.0 0
0 9.924034 7.817984 6.622061 ... 0.0 0.0 0
0 9.924034 7.817984 6.622061 ... 0.0 0.0 0
0 10.654655 7.835389 6.331263 ... 0.0 0.0 0
0 10.705711 7.838451 6.290103 ... 0.0 0.0 0
0 10.705711 7.838451 1.675145 ... 0.0 0.0 0
0 13709.733484 7.838451 1.675145 ... 0.0 0.0 0
[10 rows x 44 columns]
Natal kick example¶
One example of where restarting a binary can be extremely helpful is studying how natal kicks affect a binary independently of its previous evolution. This is particularly relevant for Gaia BH1 and Gaia BH2 which are difficult to produce through the standard common envelope channels. We can still study the effect of natal kicks on these binaries if we restart the evolution after the mass transfer would occur. We can do this by using a binary which gets us to the right masses given the metallicity, then overwrite some of the initial conditions to resample the natal kicks and pre-explosion separation.
In [6]: from cosmic import utils
...: import pandas as pd
...:
In [7]: single_binary = InitialBinaryTable.InitialBinaries(m1=65.0, m2=0.93, porb=4500, ecc=0.448872,
...: tphysf=13700.0, kstar1=1, kstar2=1, metallicity=0.014*0.6)
...:
In [8]: bpp, bcm, initC, kick_info = Evolve.evolve(initialbinarytable=single_binary, BSEDict=BSEDict)
In [9]: for column in bpp.columns:
...: initC = initC.assign(**{column:bpp.iloc[6][column]})
...:
In [10]: initC = pd.concat([initC]*1000)
....: initC['natal_kick_1'] = np.random.uniform(0, 100, 1000)
....: initC['phi_1'] = np.random.uniform(-90, 90, 1000)
....: initC['theta_1'] = np.random.uniform(0, 360, 1000)
....: initC['mean_anomaly_1'] = np.random.uniform(0, 360, 1000)
....: initC['porb'] = np.random.uniform(50, 190, 1000)
....: initC['sep'] = utils.a_from_p(p=initC.porb.values, m1=initC.mass_1.values, m2=initC.mass_2.values)
....: initC['bin_num'] = np.linspace(0, 1000, 1000)
....:
In [11]: bpp_restart, bcm_restart, initC_restart, kick_info_restart = Evolve.evolve(initialbinarytable=initC, BSEDict={})
In [12]: bpp_BH = bpp_restart.loc[(bpp_restart.kstar_1 == 14) & (bpp_restart.kstar_2 == 1) & (bpp_restart.porb > 0)].groupby('bin_num', as_index=False).first()
In [13]: bpp_BH[['tphys', 'mass_1', 'mass_2', 'porb', 'ecc']]
Out[13]:
tphys mass_1 mass_2 porb ecc
0 4.558013 9.416665 0.931310 608.557515 0.254016
1 4.558013 9.416665 0.931310 9075.539664 0.901623
2 4.558013 9.416665 0.931311 742.645232 0.648649
3 4.558013 9.416665 0.931310 194.218144 0.824820
4 4.558013 9.416665 0.931311 186.672389 0.903305
.. ... ... ... ... ...
567 4.558013 9.416665 0.931310 1911.767648 0.696450
568 4.558013 9.416665 0.931310 847.020068 0.322726
569 4.558013 9.416665 0.931310 6586.733265 0.817416
570 4.558013 9.416665 0.931310 628.541452 0.221635
571 4.558013 9.416665 0.931311 869.108278 0.631821
[572 rows x 5 columns]