def eval_baryon_density(self, p): if isinstance(p, list) or isinstance(p, np.ndarray): rho = np.zeros(len(p)) for i, pres in enumerate(p): rho [i] = lalsim.SimNeutronStarEOSRestMassDensityOfPseudoEnthalpy( lalsim.SimNeutronStarEOSPseudoEnthalpyOfPressure(pres,self.eos), self.eos) else: rho = lalsim.SimNeutronStarEOSRestMassDensityOfPseudoEnthalpy( lalsim.SimNeutronStarEOSPseudoEnthalpyOfPressure(p,self.eos), self.eos) return rho
def eval_speed_of_sound(self, p): if isinstance(p, list) or isinstance(p, np.ndarray): cs = np.zeros(len(p)) for i, pres in enumerate(p): try: h = lalsim.SimNeutronStarEOSPseudoEnthalpyOfPressure( pres, self.eos) cs[i] = lalsim.SimNeutronStarEOSSpeedOfSound(h, self.eos) except: print(pres, "failed to produce a valid sound speed") break else: h = lalsim.SimNeutronStarEOSPseudoEnthalpyOfPressure(p, self.eos) cs = lalsim.SimNeutronStarEOSSpeedOfSound(h, self.eos) return cs
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 test_speed_of_sound_causal(self, test_only_under_mmax=True, fast_test=True): """ Test if EOS satisfies speed of sound. Relies on low-level lalsimulation interpolation routines to get v(h) and as such is not very reliable By DEFAULT, we are testing the part of the EOS that is - at the largest pressure (assuming monotonic sound speed) - associated with the maximum mass NS that is stable We can also test the full table that is provided to us. https://git.ligo.org/lscsoft/lalsuite/blob/lalinference_o2/lalinference/src/LALInference.c#L2513 """ npts_internal = 1000 eos = self.eos fam = self.eos_fam # Largest NS provides largest attained central pressure m_max_SI = self.mMaxMsun * lal.MSUN_SI if not test_only_under_mmax: hmax = lalsim.SimNeutronStarEOSMaxPseudoEnthalpy(eos) else: try: pmax = lalsim.SimNeutronStarCentralPressure(m_max_SI, fam) hmax = lalsim.SimNeutronStarEOSPseudoEnthalpyOfPressure( pmax, eos) except: # gatch gsl interpolation errors for example return False if fast_test: # https://git.ligo.org/lscsoft/lalsuite/blob/lalinference_o2/lalinference/src/LALInference.c#L2513 try: vsmax = lalsim.SimNeutronStarEOSSpeedOfSoundGeometerized( hmax, eos) return vsmax < 1.1 except: # catch gsl interpolation errors for example return False else: if rosDebug: print(" performing comprehensive test ") h = np.linspace(0.0001, hmax, npts_internal) # h = np.linspace(0.0001,lalsim.SimNeutronStarEOSMinAcausalPseudoEnthalpy(eos),npts_internal) vs_internal = np.zeros(npts_internal) for indx in np.arange(npts_internal): vs_internal[ indx] = lalsim.SimNeutronStarEOSSpeedOfSoundGeometerized( h[indx], eos) if rosDebug: print(h[indx], vs_internal[indx]) return not np.any( vs_internal > 1.1) # allow buffer, so we have some threshold
def is_causal(self): p_max = lalsim.SimNeutronStarEOSMaxPressure(self.eos) c_s_max = lalsim.SimNeutronStarEOSSpeedOfSound( lalsim.SimNeutronStarEOSPseudoEnthalpyOfPressure(p_max, self.eos), self.eos) return c_s_max < c / 100 * 1.1 # Conversion from cgs to SI (leave some leeway like in 1805.11217)