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 emcee_log_post_wysocki(thetas): # evaluate prior within this function to save a second # deprojection. first check projected gammas are in # appropriate range for i in range(n_inds): if thetas[i] < gammas_rs_tf_min[i] * 1.1 or \ thetas[i] > gammas_rs_tf_max[i] * 1.1: return -np.inf # deproject gammas = gammas_std * pca.inverse_transform(thetas) + \ gammas_mean # check if physical using LAL code, which is much quicker try: is_phys = lal_inf_eos_physical_check(gammas) except: print('LAL error') return -np.inf if not is_phys: return -np.inf else: log_prior = 0.0 # calculate log-likelihood. this is a numerical integration # over each merger's mass-lambda likelihood. log_like = 0.0 n_grid = 1000 # @TODO: test this out. 100, 1000 and 10000 agree pretty well lambdas = np.zeros(n_grid) likes = np.zeros(n_grid) # use gammas to define mass grid for integration fam = lal_inf_sd_gammas_fam(gammas) m_max_eos = lalsim.SimNeutronStarMaximumMass(fam) / m_sol_kg masses = np.linspace(m_min_ns, m_max_eos * 0.99999999, n_grid) # calculate lambdas on that grid for j in range(n_grid): lambdas[j] = lal_inf_sd_gammas_mass_to_lambda(fam, masses[j]) # loop over targets performing integrals for k in range(n_targets): for j in range(n_grid): likes[j] = m_l_ns_posts[k](masses[j], lambdas[j])[0, 0] # correct for -ve spline likelihoods and integrate neg_like = likes < 0.0 likes[neg_like] = 0.0 integral = np.trapz(likes, masses) log_like += np.log(integral) # @TODO: mass prior volume effect! # return log-posterior return log_prior + log_like
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, 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 __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 max_mass(self): """Calculate the maximum mass. """ if self.properties_flag==None: self.calculate_ns_properties() if self.mmax==None: mmax = lalsimulation.SimNeutronStarMaximumMass(self.fam)/lal.MSUN_SI # Create a little buffer so you don't interpolate right at the maximum mass # TODO: this is crude and should be fixed self.mmax = mmax - 0.01 return self.mmax else: return self.mmax
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 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 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 emcee_log_post(gammas): # first call prior and immediately return if non-physical EOS log_prior = emcee_log_prior(gammas) if not np.isfinite(log_prior): return log_prior # calculate log-likelihood. this is a numerical integration # over each merger's mass-lambda likelihood. log_like = 0.0 n_grid = 1000 # @TODO: test this out. 100, 1000 and 10000 agree pretty well lambdas = np.zeros(n_grid) likes = np.zeros(n_grid) # use gammas to define mass grid for integration fam = lal_inf_sd_gammas_fam(gammas) m_max_eos = lalsim.SimNeutronStarMaximumMass(fam) / m_sol_kg masses = np.linspace(m_min_ns, m_max_eos * 0.99999999, n_grid) # calculate lambdas on that grid for j in range(n_grid): lambdas[j] = lal_inf_sd_gammas_mass_to_lambda(fam, masses[j]) # loop over targets performing integrals for k in range(n_targets): for j in range(n_grid): likes[j] = m_l_ns_posts[k](masses[j], lambdas[j])[0, 0] # correct for -ve spline likelihoods and integrate neg_like = likes < 0.0 likes[neg_like] = 0.0 integral = np.trapz(likes, masses) log_like += np.log(integral) # @TODO: mass prior volume effect! # return log-posterior return log_prior + log_like
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
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 is_M_big_enough(self): m_max = lalsim.SimNeutronStarMaximumMass(self.family) return m_max > 1.76 * M_sun_si
# 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) masses[j] = npr.uniform(m_ns_like_support[j][0], m_max_sample)
csi = const.c.si.value ccgs = const.c.cgs.value eos_list = [] params = np.array([[0.551056367273767, -0.5417148996519847, 0.06503562059334078, -0.00148604021538651],[0.5433926488753059, -0.4917361657495225, 0.13413782935878904, -0.009271344015786902]]) N = len(params) for i in range(N): eos = py_spec_eos.eos_spectral(*params[i]) print("testing for segfault") eos.get_fam() print("passed") eos_list.append(eos) print("eos is causal : ", eos.is_causal(np.linspace(*py_spec_eos.p_range, 100))) print("eos is confined : ", eos.is_confined(np.linspace(*py_spec_eos.p_range, 100))) print("i is ", i) max_masses = np.array([lalsim.SimNeutronStarMaximumMass(eos.get_fam())/lal.MSUN_SI for eos in eos_list if eos.get_fam() is not None]) M1p4s = lal.MSUN_SI*1.4 R1p4s =[] nuc_rho_cgs = 2.8e14 # This is in cgs nuc_rho_si = 2.8e17 # this is in SI # I can't believe there's no function to get pressure as a function of density. def find_pressure_of_density(rho, eos_wrapper): def rootable(logp): p = np.exp(logp) return np.arcsinh(eos_wrapper.eval_baryon_density(p) - rho) return np.exp((scipy.optimize.root_scalar(rootable, bracket=(np.log(2.0e27), np.log(1.0e37))).root)) P2nucs = []
import lal import numpy as np import matplotlib.pyplot as plt import scipy.optimize # Number of samples to draw N = 200 import astropy.constants as const Gsi = const.G.si.value csi = const.c.si.value ccgs = const.c.cgs.value eos_list = [] for i in range(N): eos_list.append(pyeos.get_eos_realization_uniform_constrained_poly() ) #Use default parameter range max_masses = np.array([ lalsim.SimNeutronStarMaximumMass(eos.family) / lal.MSUN_SI for eos in eos_list ]) M1p4s = lal.MSUN_SI * 1.4 R1p4s = [] nuc_rho_cgs = 2.8e14 # This is in cgs nuc_rho_si = 2.8e17 # this is in SI # I can't believe there's no function to get pressure as a function of density. def find_pressure_of_density(rho, eos_wrapper): def rootable(logp): p = np.exp(logp) return np.arcsinh(eos_wrapper.eval_baryon_density(p) - rho) print(rootable(np.log(2.0e25)), rootable(np.log(2.0e38)))
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()
def get_max_M(self): return lalsim.SimNeutronStarMaximumMass(self.family)/lal.MSUN_SI
pc2 = [] # Loop over EOS samples print "MCMC samples =", len(mass1) for i in range(len(mass1)): print "Sample ", i, "/", len(mass1) eos = None if model == '4piece': eos = lalsim.SimNeutronStarEOS4ParameterPiecewisePolytrope( logp1[i] - 1, gamma1[i], gamma2[i], gamma3[i]) if model == 'spectral': eos = lalsim.SimNeutronStarEOSSpectralDecomposition_for_plot( sd_gamma0[i], sd_gamma1[i], sd_gamma2[i], sd_gamma3[i], spec_size) assert eos is not None fam = lalsim.CreateSimNeutronStarFamily(eos) max_m = lalsim.SimNeutronStarMaximumMass(fam) / lal.MSUN_SI # [M_sun] min_m = lalsim.SimNeutronStarFamMinimumMass( fam) / lal.MSUN_SI # [M_sun] # Find NS properties for each EOS sample max_mass.append(max_m) # [M_sun] m1_d.append(mass1[i]) # [M_sun] m1_s.append(m1_d[i] / (1. + red_z)) # [M_sun] r1.append( lalsim.SimNeutronStarRadius(m1_s[i] * lal.MSUN_SI, fam) / 1000.) # [km] k1.append(lalsim.SimNeutronStarLoveNumberK2(m1_s[i] * lal.MSUN_SI, fam)) # [ ] c1.append(m1_s[i] * lal.MRSUN_SI / (r1[i] * 1000.)) # [ ] l1.append((2. / 3.) * k1[i] / c1[i]**5.) # [ ] pc1.append( lalsim.SimNeutronStarCentralPressure(m1_s[i] * lal.MSUN_SI, fam) *