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 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 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
EOS_FROM_SPRECTRAL_DECOMPOSITION = EOSFamily(SpectralDecompositionEOS(gammas=[0.8651, 0.1548, -0.0151, -0.0002], p0=1.5e33, e0=2.02e14, xmax=7.04)) MASSES_TO_TEST = numpy.linspace(0.9, 2.0, 12) PRESSURE = 1e-11 ENTHALPY = 1.2 ENERGY_DENSITY = 9.541419e-11 # Setup for MPA1 Comparison PRESSURE_0 = 5.3716e32 ENERGY_DENSITY_0 = 1.1555e35 / (utils.speed_of_light * 100) ** 2. XMAX = 12.3081 GAMMAS = [1.0215, 0.1653, -0.0235, -0.0004] LALSIM_MPA1 = lalsim.SimNeutronStarEOS4ParameterSpectralDecomposition(GAMMAS[0], GAMMAS[1], GAMMAS[2], GAMMAS[3]) BILBY_MPA1 = SpectralDecompositionEOS(GAMMAS, PRESSURE_0, ENERGY_DENSITY_0, XMAX) MPA1_PRESSURES = BILBY_MPA1.e_pdat.T[0] LALSIM_MPA1_ENERGY_DENSITY = [lalsim.SimNeutronStarEOSEnergyDensityOfPressureGeometerized(PRESSURE, LALSIM_MPA1) for PRESSURE in MPA1_PRESSURES[:-1]] BILBY_MPA1_ENERGY_DENSITY = BILBY_MPA1.e_pdat.T[1][:-1] class TestEOSFamily(unittest.TestCase): def test_spectral_decomposition_energy_from_pressure(self): self.assertAlmostEqual(EOS_FROM_TABLE.eos.energy_from_pressure(PRESSURE), 3.2736497985232014e-10) self.assertAlmostEqual(EOS_FROM_SPRECTRAL_DECOMPOSITION.eos.energy_from_pressure(PRESSURE), 3.270622527256167e-10)
n_rej = 0 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):