def get_lalsim_eos(eos_name): """ EOS tables described by Ozel `here <https://arxiv.org/pdf/1603.02698.pdf>`_ and downloadable `here <http://xtreme.as.arizona.edu/NeutronStars/data/eos_tables.tar>`_. LALSim utilizes this tables, but needs some interfacing (i.e. conversion to SI units, and conversion from non monotonic to monotonic pressure density tables) """ import os import lalsimulation import lal obs_max_mass = 2.01 - 0.04 print("Checking %s" % eos_name) eos_fname = "" if os.path.exists(eos_name): # NOTE: Adapted from code by Monica Rizzo print("Loading from %s" % eos_name) bdens, press, edens = np.loadtxt(eos_name, unpack=True) press *= 7.42591549e-25 edens *= 7.42591549e-25 eos_name = os.path.basename(eos_name) eos_name = os.path.splitext(eos_name)[0].upper() if not np.all(np.diff(press) > 0): keep_idx = np.where(np.diff(press) > 0)[0] + 1 keep_idx = np.concatenate(([0], keep_idx)) press = press[keep_idx] edens = edens[keep_idx] assert np.all(np.diff(press) > 0) if not np.all(np.diff(edens) > 0): keep_idx = np.where(np.diff(edens) > 0)[0] + 1 keep_idx = np.concatenate(([0], keep_idx)) press = press[keep_idx] edens = edens[keep_idx] assert np.all(np.diff(edens) > 0) print("Dumping to %s" % eos_fname) eos_fname = "./." + eos_name + ".dat" np.savetxt(eos_fname, np.transpose((press, edens)), delimiter='\t') eos = lalsimulation.SimNeutronStarEOSFromFile(eos_fname) fam = lalsimulation.CreateSimNeutronStarFamily(eos) else: eos = lalsimulation.SimNeutronStarEOSByName(eos_name) fam = lalsimulation.CreateSimNeutronStarFamily(eos) mmass = lalsimulation.SimNeutronStarMaximumMass(fam) / lal.MSUN_SI print("Family %s, maximum mass: %1.2f" % (eos_name, mmass)) if np.isnan(mmass) or mmass > 3. or mmass < obs_max_mass: return return eos, fam
def construct_eos_from_polytrope(eos_name): """ Uses lalsimulation to read polytrope parameters from table """ import lalsimulation as lalsim from astropy.io import ascii polytrope_table = np.genfromtxt(find_executable('polytrope_table.dat'), dtype=("|S10", '<f8', '<f8', '<f8', '<f8'), names=True) #convert all eos names to lower case for i in range(0, len(polytrope_table['eos'])): polytrope_table['eos'][i] = polytrope_table['eos'][i].lower() #convert logp from cgs to si for i in range(0, len(polytrope_table['logP1'])): polytrope_table['logP1'][i] = np.log10( 10**(polytrope_table['logP1'][i]) * 0.1) eos_indx = np.where(polytrope_table['eos'] == eos)[0][0] eos = lalsim.SimNeutronStarEOS4ParameterPiecewisePolytrope( polytrope_table['logP1'][eos_indx], polytrope_table['gamma1'][eos_indx], polytrope_table['gamma2'][eos_indx], polytrope_table['gamma3'][eos_indx]) fam = lalsim.CreateSimNeutronStarFamily(eos) return eos, fam
def __init__(self, EOS): """Initialize EOS and calculate a family of TOV stars. """ print(find_executable('polytrope_table.dat')) # load in polytop table polytable = Table.read(find_executable('polytrope_table.dat'), format='ascii') polytable = polytable[polytable['col1'] == EOS] lp_cgs = float(polytable['col2']) g1 = float(polytable['col3']) g2 = float(polytable['col4']) g3 = float(polytable['col5']) # lalsimulation uses SI units. lp_si = lp_cgs - 1. # Initialize with piecewise polytrope parameters (logp1 in SI units) eos = lalsimulation.SimNeutronStarEOS4ParameterPiecewisePolytrope( lp_si, g1, g2, g3) # This creates the interpolated functions R(M), k2(M), etc. # after doing many TOV integrations. self.fam = lalsimulation.CreateSimNeutronStarFamily(eos) # Get maximum mass for this EOS self.mmax = lalsimulation.SimNeutronStarMaximumMass( self.fam) / lal.MSUN_SI
def __init__(self, logp1, gamma1, gamma2, gamma3): self.gamma1 = gamma1 self.gamma2 = gamma2 self.gamma3 = gamma3 self.logp1 = logp1 self.eos = lalsim.SimNeutronStarEOS4ParameterPiecewisePolytrope( self.logp1 - 1, self.gamma1, self.gamma2, self.gamma3) self.family = lalsim.CreateSimNeutronStarFamily(self.eos)
def lal_inf_eos_physical_check(gammas, verbose=False): ''' Python version of LALInferenceEOSPhysicalCheck: https://lscsoft.docs.ligo.org/lalsuite/lalinference/_l_a_l_inference_8c_source.html#l02404 ''' # apply 0.6 < Gamma(p) < 4.5 constraint if not lalinf_sd_gamma_check(gammas): return False else: # create LAL EOS object eos = lalsim.SimNeutronStarEOS4ParameterSpectralDecomposition(*gammas) # ensure mass turnover doesn't happen too soon mdat_prev = 0.0 logpmin = 75.5 logpmax = np.log(lalsim.SimNeutronStarEOSMaxPressure(eos)) dlogp = (logpmax - logpmin) / 100.0 for j in range(4): # determine if maximum mass has been found pdat = np.exp(logpmin + j * dlogp) rdat, mdat, kdat = lalsim.SimNeutronStarTOVODEIntegrate(pdat, eos) if mdat <= mdat_prev: if verbose: print('rejecting: too few EOS points', gammas) return False mdat_prev = mdat # make EOS family, and calculate speed of sound and max # and min mass allowed by EOS fam = lalsim.CreateSimNeutronStarFamily(eos) min_mass_kg = lalsim.SimNeutronStarFamMinimumMass(fam) max_mass_kg = lalsim.SimNeutronStarMaximumMass(fam) pmax = lalsim.SimNeutronStarCentralPressure(max_mass_kg, fam) hmax = lalsim.SimNeutronStarEOSPseudoEnthalpyOfPressure(pmax, eos) vsmax = lalsim.SimNeutronStarEOSSpeedOfSoundGeometerized(hmax, eos) # apply constraints on speed of sound and maximum mass if vsmax > c_s_max: if verbose: print('rejecting:', \ 'sound speed {:4.2f} too high'.format(vsmax), \ gammas) return False if max_mass_kg < ns_mass_max_kg: if verbose: print('rejecting:', \ 'max NS mass {:4.2f} too low'.format(max_mass_kg / m_sol_kg), \ gammas) return False return True
def __init__(self, gamma0, gamma1, gamma2, gamma3): self.gamma0 = gamma0 self.gamma1 = gamma1 self.gamma2 = gamma2 self.gamma3 = gamma3 self.eos = lalsim.SimNeutronStarEOS4ParameterSpectralDecomposition( self.gamma0, self.gamma1, self.gamma2, self.gamma3) self.family = lalsim.CreateSimNeutronStarFamily(self.eos)
def calculate_ns_properties(self): # Initialize with piecewise polytrope parameters (logp1 in SI units) self.eos = lalsimulation.SimNeutronStarEOS4ParameterPiecewisePolytrope( self.lp_si, self.g1, self.g2, self.g3) # This creates the interpolated functions R(M), k2(M), etc. # after doing many TOV integrations. self.fam = lalsimulation.CreateSimNeutronStarFamily(self.eos) # Change flag self.properties_flag = 1
def lal_inf_sd_gammas_fam(gammas): ''' Modified from LALInferenceSDGammasMasses2Lambdas: https://lscsoft.docs.ligo.org/lalsuite/lalinference/_l_a_l_inference_8c_source.html#l02364 ''' # create EOS & family eos = lalsim.SimNeutronStarEOS4ParameterSpectralDecomposition(*gammas) fam = lalsim.CreateSimNeutronStarFamily(eos) return fam
def lambda_from_m(m): eos = lalsim.SimNeutronStarEOSByName("AP4") eos_fam = lalsim.CreateSimNeutronStarFamily(eos) if m < 10**15: m = m * lal.MSUN_SI k2 = lalsim.SimNeutronStarLoveNumberK2(m, eos_fam) r = lalsim.SimNeutronStarRadius(m, eos_fam) m = m * lal.G_SI / lal.C_SI**2 lam = 2. / (3 * lal.G_SI) * k2 * r**5 dimensionless_lam = lal.G_SI * lam * (1 / m)**5 return dimensionless_lam
def __init__(self, name): self.name = name self.eos = None self.eos_fam = None self.mMaxMsun = None eos = lalsim.SimNeutronStarEOSByName(name) fam = lalsim.CreateSimNeutronStarFamily(eos) mmass = lalsim.SimNeutronStarMaximumMass(fam) / lal.MSUN_SI self.eos = eos self.eos_fam = fam self.mMaxMsun = mmass return None
def __init__(self, name, param_dict=None): self.name = name self.eos = None self.eos_fam = None self.mMaxMsun = None eos = self.eos = lalsim.SimNeutronStarEOS4ParameterPiecewisePolytrope( param_dict['logP1'], param_dict['gamma1'], param_dict['gamma2'], param_dict['gamma3']) eos_fam = self.eos_fam = lalsim.CreateSimNeutronStarFamily(eos) self.mMaxMsun = lalsim.SimNeutronStarMaximumMass(eos_fam) / lal.MSUN_SI return None
def lal_inf_sd_gammas_mass_to_lambda(gammas, mass_m_sol): ''' Modified from LALInferenceSDGammasMasses2Lambdas: https://lscsoft.docs.ligo.org/lalsuite/lalinference/_l_a_l_inference_8c_source.html#l02364 ''' # create EOS & family eos = lalsim.SimNeutronStarEOS4ParameterSpectralDecomposition(*gammas) fam = lalsim.CreateSimNeutronStarFamily(eos) # calculate lambda(m|eos) mass_kg = mass_m_sol * m_sol_kg rad = lalsim.SimNeutronStarRadius(mass_kg, fam) love = lalsim.SimNeutronStarLoveNumberK2(mass_kg, fam) comp = big_g * mass_kg / (c**2) / rad return 2.0 / 3.0 * love / comp**5
def eos_ls(self): # From Monica, but using code from GWEMLightcurves # https://gwemlightcurves.github.io/_modules/gwemlightcurves/KNModels/table.html """ EOS tables described by Ozel `here <https://arxiv.org/pdf/1603.02698.pdf>`_ and downloadable `here <http://xtreme.as.arizona.edu/NeutronStars/data/eos_tables.tar>`_. LALSim utilizes this tables, but needs some interfacing (i.e. conversion to SI units, and conversion from non monotonic to monotonic pressure density tables) """ obs_max_mass = 2.01 - 0.04 # used print("Checking %s" % self.name) eos_fname = "" if os.path.exists(self.fname): # NOTE: Adapted from code by Monica Rizzo print("Loading from %s" % self.fname) bdens, press, edens = np.loadtxt(self.fname, unpack=True) press *= DENSITY_CGS_IN_MSQUARED edens *= DENSITY_CGS_IN_MSQUARED eos_name = self.name if not np.all(np.diff(press) > 0): keep_idx = np.where(np.diff(press) > 0)[0] + 1 keep_idx = np.concatenate(([0], keep_idx)) press = press[keep_idx] edens = edens[keep_idx] assert np.all(np.diff(press) > 0) if not np.all(np.diff(edens) > 0): keep_idx = np.where(np.diff(edens) > 0)[0] + 1 keep_idx = np.concatenate(([0], keep_idx)) press = press[keep_idx] edens = edens[keep_idx] assert np.all(np.diff(edens) > 0) # Creating temporary file in suitable units print("Dumping to %s" % self.fname) eos_fname = "./" + eos_name + "_geom.dat" # assume write acces np.savetxt(eos_fname, np.transpose((press, edens)), delimiter='\t') eos = lalsim.SimNeutronStarEOSFromFile(eos_fname) fam = lalsim.CreateSimNeutronStarFamily(eos) else: print(" No such file ", self.fname) sys.exit(0) mmass = lalsim.SimNeutronStarMaximumMass(fam) / lal.MSUN_SI self.mMaxMsun = mmass return eos, fam
def Lambdas(params): #Unpack params eosname = params['eosname'] m1 = params['m1'] m2 = params['m2'] #Create EOS/Family structures eos = lalsim.SimNeutronStarEOSByName(eosname) fam = lalsim.CreateSimNeutronStarFamily(eos) r1 = lalsim.SimNeutronStarRadius(m1 * MSUN_SI, fam) r2 = lalsim.SimNeutronStarRadius(m2 * MSUN_SI, fam) k1 = lalsim.SimNeutronStarLoveNumberK2(m1 * MSUN_SI, fam) k2 = lalsim.SimNeutronStarLoveNumberK2(m2 * MSUN_SI, fam) c1 = m1 * MRSUN_SI / r1 c2 = m2 * MRSUN_SI / r2 Lambda1 = (2.0 / 3.0) * k1 / c1**5. Lambda2 = (2.0 / 3.0) * k2 / c2**5. return [Lambda1, Lambda2]
def make_mr_lambda_lal(eos, n_bins=100): """ Construct mass-radius curve from EOS Based on modern code resources (https://git.ligo.org/publications/gw170817/bns-eos/blob/master/scripts/eos-params.py) which access low-level structures """ fam = lalsim.CreateSimNeutronStarFamily(eos) max_m = lalsim.SimNeutronStarMaximumMass(fam) / lal.MSUN_SI min_m = lalsim.SimNeutronStarFamMinimumMass(fam) / lal.MSUN_SI mgrid = np.linspace(min_m, max_m, n_bins) mrL_dat = np.zeros((n_bins, 3)) mrL_dat[:, 0] = mgrid for indx in np.arange(n_bins): mass_now = mgrid[indx] r = lalsim.SimNeutronStarRadius(mass_now * lal.MSUN_SI, fam) / 1000. mrL_dat[indx, 1] = r k = lalsim.SimNeutronStarLoveNumberK2(mass_now * lal.MSUN_SI, fam) c = mass_now * lal.MRSUN_SI / (r * 1000.) mrL_dat[indx, 2] = (2. / 3.) * k / c**5. return mrL_dat
def __init__(self, name=None, spec_params=None, verbose=False, use_lal_spec_eos=False): if name is None: self.name = 'spectral' else: self.name = name self.eos = None self.eos_fam = None self.spec_params = spec_params # print spec_params if use_lal_spec_eos: # self.eos=lalsim.SimNeutronStarEOS4ParameterSpectralDecomposition(spec_params['gamma1'], spec_params['gamma2'], spec_params['gamma3'], spec_params['gamma4']) # Should have this function! but only on master self.eos = lalsim.SimNeutronStarEOSSpectralDecomposition_for_plot( spec_params['gamma1'], spec_params['gamma2'], spec_params['gamma3'], spec_params['gamma4'], 4) else: # Create data file self.make_spec_param_eos(500, save_dat=True, ligo_units=True, verbose=verbose) # Use data file #print " Trying to load ",name+"_geom.dat" import os #print os.listdir('.') cwd = os.getcwd() self.eos = eos = lalsim.SimNeutronStarEOSFromFile(cwd + "/" + name + "_geom.dat") self.eos_fam = fam = lalsim.CreateSimNeutronStarFamily(self.eos) mmass = lalsim.SimNeutronStarMaximumMass(fam) / lal.MSUN_SI self.mMaxMsun = mmass return None
while i < n_samples: # draw random samples from SD priors for j in range(n_inds): gammas[j] = npr.uniform(prior_ranges[j][0], \ prior_ranges[j][1]) # check if physical using LAL code, which is much quicker if not lal_inf_eos_physical_check(gammas): continue # calculate maximum mass allowed by EOS: don't allow prior draws # beyond this limit eos = lalsim.SimNeutronStarEOS4ParameterSpectralDecomposition(*gammas) fam = lalsim.CreateSimNeutronStarFamily(eos) m_max_eos = lalsim.SimNeutronStarMaximumMass(fam) / m_sol_kg # loop over mass draws per EOS for k in range(n_m_samples): # sample neutron star masses from most efficient range. this # is from the greater of m_min_ns and m_ns_like_support[j][0] # (which is automatically satisfied in the calculation of # m_ns_like_support) to the lesser of m_max_eos and # m_ns_like_support[j][1]. the weights must then be adjusted # to account for the restricted prior range used, which # should be m_min_ns -> m_max_eos i_tot = i * n_m_samples + k for j in range(n_targets): m_max_sample = min(m_ns_like_support[j][1], m_max_eos)
def make_mr_lambda(eos, use_lal=False): """ construct mass-radius curve from EOS DOES NOT YET WORK RELIABLY """ if use_lal: make_mr_lambda_lal(eos) fam = lalsim.CreateSimNeutronStarFamily(eos) r_cut = 40 # Some EOS we consider for PE purposes will have very large radius! #set p_nuc max # - start at a fiducial nuclear density # - not sure what these termination conditions are designed to do ... generally this pushes to 20 km # - generally this quantity is the least reliable p_nuc = 3. * 10**33 # consistent with examples fac_min = 0 r_fin = 0 while r_fin > r_cut + 8 or r_fin < r_cut: # Generally tries to converge to density corresponding to 20km radius try: answer = lalsim.SimNeutronStarTOVODEIntegrate( (10**fac_min) * p_nuc, eos) # r(SI), m(SI), lambda except: # If failure, backoff fac_min = -0.05 break r_fin = answer[0] r_fin = r_fin * 10**-3 # convert to SI # print "R: ",r_fin if r_fin < r_cut: fac_min -= 0.05 elif r_fin > r_cut + 8: fac_min += 0.01 answer = lalsim.SimNeutronStarTOVODEIntegrate((10**fac_min) * p_nuc, eos) # r(SI), m(SI), lambda m_min = answer[1] / lal.MSUN_SI #set p_nuc min # - tries to converge to central pressure corresponding to maximum NS mass # - very frustrating...this data is embedded in the C code fac_max = 1.6 r_fin = 20. m_ref = lalsim.SimNeutronStarMaximumMass(fam) / lal.MSUN_SI r_ref = lalsim.SimNeutronStarRadius(lalsim.SimNeutronStarMaximumMass(fam), fam) / (10**3) answer = None while r_fin > r_ref or r_fin < 7: #print "Trying min:" # print "p_c: ",(10**fac_max)*p_nuc try: answer = lalsim.SimNeutronStarTOVODEIntegrate( (10**fac_max) * p_nuc, eos) if answer[0] * 10**-3 < r_ref: break except: fac_max -= 0.05 working = False while working == False: try: answer_tmp = lalsim.SimNeutronStarTOVODEIntegrate( (10**fac_max) * p_nuc, eos) working = True except: fac_max -= 0.05 break #print lalsim.SimNeutronStarTOVODEIntegrate((10**fac_max)*p_nuc, eos) r_fin = answer[0] / 10**3 # convert to km if rosDebug: print("R: ", r_fin, r_ref, " M: ", answer[1] / lal.MSUN_SI, m_ref, m_min) # should converge to maximum mass if r_fin > 8: fac_max += 0.05 if r_fin < 6: fac_max -= 0.01 # print 10**fac_max #generate mass-radius curve npts_out = 1000 scale = np.logspace(fac_min, fac_max, npts_out) mr_array = np.zeros((npts_out, 3)) for s, i in zip(scale, range(0, len(scale))): # print s mr_array[i, :] = lalsim.SimNeutronStarTOVODEIntegrate(s * p_nuc, eos) mr_array[:, 0] = mr_array[:, 0] / 10**3 mr_array[:, 1] = mr_array[:, 1] / lal.MSUN_SI mr_array[:, 2] = 2. / (3 * lal.G_SI) * mr_array[:, 2] * (mr_array[:, 0] * 10**3)**5 mr_array[:, 2] = lal.G_SI * mr_array[:, 2] * ( 1 / (mr_array[:, 1] * lal.MSUN_SI * lal.G_SI / lal.C_SI**2))**5 # print mr_array[:,1] return mr_array
def make_tidal_waveform(approx='TaylorT4', rate=4096, Lambda1=None, Lambda2=None, mass1=1.4, mass2=1.3, inclination=0, distance=100, eccentricity=0, meanPerAno=0, phiRef=0, f_min=30, f_ref=0, longAscNodes=0, s1x=0, s1y=0, s1z=0, s2x=0, s2y=0, s2z=0, eos=None, save=False): # Sanity check if (Lambda1 is None) and (Lambda2 is None) and (eos is None): # Assuming Lambdas to be zero is not provided print("Assuming tidal deformability is zero") print( "Use arguments Lambda1=, and Lambda2= to provide deformabilities") Lambda1 = 0.0 Lambda2 = 0.0 if eos: if Lambda1 or Lambda2: print( "Warning: Both eos and Lambda1 and/or Lambda2 has been provided" ) print("Ignoring Lambdas in favor of the eos") e = lalsim.SimNeutronStarEOSByName(eos) fam = lalsim.CreateSimNeutronStarFamily(e) max_mass = lalsim.SimNeutronStarMaximumMass(fam) / lal.MSUN_SI assert mass1 < max_mass, "mass1 greater than maximum mass allowed for the neutron star" assert mass2 < max_mass, "mass2 greater than the maximum mass allowed for the neutron star" r1 = lalsim.SimNeutronStarRadius(mass1 * lal.MSUN_SI, fam) k1 = lalsim.SimNeutronStarLoveNumberK2(mass1 * lal.MSUN_SI, fam) r2 = lalsim.SimNeutronStarRadius(mass2 * lal.MSUN_SI, fam) k2 = lalsim.SimNeutronStarLoveNumberK2(mass2 * lal.MSUN_SI, fam) c2 = mass2 * lal.MRSUN_SI / r2 c1 = mass1 * lal.MRSUN_SI / r1 Lambda1 = (2 / 3) * k1 / (c1**5) Lambda2 = (2 / 3) * k2 / (c2**5) mass1 = mass1 * lal.MSUN_SI mass2 = mass2 * lal.MSUN_SI distance = distance * 1e6 * lal.PC_SI deltaT = 1.0 / rate approximant = lalsim.GetApproximantFromString(approx) lal_pars = lal.CreateDict() lalsim.SimInspiralWaveformParamsInsertTidalLambda1(lal_pars, Lambda1) lalsim.SimInspiralWaveformParamsInsertTidalLambda2(lal_pars, Lambda2) hp, hc = lalsim.SimInspiralChooseTDWaveform(mass1, mass2, s1x=s1x, s1y=s1y, s1z=s1z, s2x=s2x, s2y=s2y, s2z=s2z, distance=distance, inclination=inclination, phiRef=phiRef, longAscNodes=longAscNodes, eccentricity=eccentricity, meanPerAno=meanPerAno, deltaT=deltaT, f_min=f_min, f_ref=f_ref, params=lal_pars, approximant=approximant) if save: plus_data = hp.data.data cross_data = hc.data.data tstart_p = hp.epoch.gpsSeconds + hp.epoch.gpsNanoSeconds * 1e-9 tstart_c = hc.epoch.gpsSeconds + hc.epoch.gpsNanoSeconds * 1e-9 tp = np.arange(tstart_p, 0, hp.deltaT) tp = tp[:len(hp.data.data)] tc = np.arange(tstart_c, 0, hc.deltaT) tc = tc[:len(hc.data.data)] output_plus = np.vstack((tp, plus_data)).T output_cross = np.vstack((tc, cross_data)).T np.savetxt("plus_polarization_data.txt", output_plus, fmt="%f\t%e") np.savetxt("cross_polarization_data.txt", output_cross, fmt="%f\t%e") return (hp, hc)
def __init__(self, sim, eos="WFF1"): # Load if from sim inspiral table if isinstance(sim, lsctables.SimInspiral): self.sim = sim # Set NS self.m_ns = sim.mass2 self.s_ns_x = sim.spin2x self.s_ns_y = sim.spin2y self.s_ns_z = sim.spin2z # Set BH self.m_bh = sim.mass1 self.s_bh_x = sim.spin1x self.s_bh_y = sim.spin1y self.s_bh_z = sim.spin1z self.s_bh = np.sqrt(self.s_bh_x**2 + self.s_bh_y**2 + self.s_bh_z**2) self.s_bh_tilt = np.arccos(self.s_bh_z / self.s_bh) # Load if from LALInference posterior samples elif isinstance(sim, np.void): # Set NS self.m_ns = sim["m2"] # Set BH self.m_bh = sim["m1"] self.s_bh = sim["a1"] self.s_bh_tilt = sim["tilt1"] self.s_bh_z = self.s_bh * np.cos(self.s_bh_tilt) elif isinstance(sim, dict): # Set NS self.m_ns = sim['mass2'] self.s_ns_x = sim['spin2x'] self.s_ns_y = sim['spin2y'] self.s_ns_z = sim['spin2z'] # Set BH self.m_bh = sim['mass1'] self.s_bh_x = sim['spin1x'] self.s_bh_y = sim['spin1y'] self.s_bh_z = sim['spin1z'] self.s_bh = np.sqrt(self.s_bh_x**2 + self.s_bh_y**2 + self.s_bh_z**2) self.s_bh_tilt = np.arccos(self.s_bh_z / self.s_bh) else: raise NotImplementedError( "Input of type {} not yet supported!".format(type(sim))) #print("BH = {:.2f}, NS = {:.2f}".format(self.m_bh, self.m_ns)) if eos in list(lalsim.SimNeutronStarEOSNames): eos_obj = lalsim.SimNeutronStarEOSByName(eos) self.eos = lalsim.CreateSimNeutronStarFamily(eos_obj) # Get limiting NS masses and ensure valid input m_max = lalsim.SimNeutronStarMaximumMass(self.eos) self.m_max = m_max / lal.MSUN_SI assert (self.m_ns < self.m_max) m_min = lalsim.SimNeutronStarFamMinimumMass(self.eos) self.m_min = m_min / lal.MSUN_SI assert (self.m_ns > self.m_min) # Get NS radius self.r_ns = lalsim.SimNeutronStarRadius(self.m_ns * lal.MSUN_SI, self.eos) # NS tidal deformability self.compactness = self.get_compactness() self.love = lalsim.SimNeutronStarLoveNumberK2( self.m_ns * lal.MSUN_SI, self.eos) self.lamb = 2. / 3. * self.love * self.compactness**-5 else: eos_func, mr_func, self.m_max, self.m_min = choose_func(eos) assert (self.m_ns < self.m_max) assert (self.m_ns > self.m_min) self.lamb = eos_func(self.m_ns) self.r_ns = mr_func(self.m_ns) * 1e3 self.compactness = self.get_compactness()