def _get_imr_duration(m1, m2, s1z, s2z, f_low, approximant="SEOBNRv4"): """Wrapper of lalsimulation template duration approximate formula""" m1, m2, s1z, s2z, f_low = float(m1), float(m2), float(s1z), float(s2z),\ float(f_low) if approximant == "SEOBNRv2": chi = lalsimulation.SimIMRPhenomBComputeChi(m1, m2, s1z, s2z) time_length = lalsimulation.SimIMRSEOBNRv2ChirpTimeSingleSpin( m1 * lal.MSUN_SI, m2 * lal.MSUN_SI, chi, f_low) elif approximant == "IMRPhenomD": time_length = lalsimulation.SimIMRPhenomDChirpTime( m1 * lal.MSUN_SI, m2 * lal.MSUN_SI, s1z, s2z, f_low) elif approximant == "SEOBNRv4": # NB for no clear reason this function has f_low as first argument time_length = lalsimulation.SimIMRSEOBNRv4ROMTimeOfFrequency( f_low, m1 * lal.MSUN_SI, m2 * lal.MSUN_SI, s1z, s2z) elif approximant == 'SPAtmplt' or approximant == 'TaylorF2': chi = lalsimulation.SimInspiralTaylorF2ReducedSpinComputeChi( m1, m2, s1z, s2z ) time_length = lalsimulation.SimInspiralTaylorF2ReducedSpinChirpTime( f_low, m1 * lal.MSUN_SI, m2 * lal.MSUN_SI, chi, -1 ) else: raise RuntimeError("I can't calculate a duration for %s" % approximant) # FIXME Add an extra factor of 1.1 for 'safety' since the duration # functions are approximate return time_length * 1.1
def __init__(self, m1, m2, spin1z, spin2z, bank, flow=None, duration=None): AlignedSpinTemplate.__init__(self, m1, m2, spin1z, spin2z, bank, flow=flow, duration=duration) self.chired = lalsim.SimInspiralTaylorF2ReducedSpinComputeChi(m1, m2, spin1z, spin2z) self._eta = m1*m2/(m1+m2)**2 self._theta0, self._theta3, self._theta3s = compute_chirptimes(self._mchirp, self._eta, self.chired, self.flow)
def __init__(self, m1, m2, spin1z, spin2z, bank, flow=None, duration=None): warn_msg = ("DEPRECATION WARNING: It is not a good idea to use this " "approximant. The TaylorF2 approximant is the best thing " "to use if you are constructing a 'brute-force match' " "bank. This allows the use of both spins correctly, and " "the inclusion of all PN terms currently known. " "If using the metric, the implementation in PyCBC, which " "gets terms directly from lalsimulation, and so " "automatically stays up to date, is more accurate.") logging.warn(warn_msg) AlignedSpinTemplate.__init__(self, m1, m2, spin1z, spin2z, bank, flow=flow, duration=duration) self.chired = lalsim.SimInspiralTaylorF2ReducedSpinComputeChi( m1, m2, spin1z, spin2z ) self._eta = m1*m2/(m1+m2)**2 self._theta0, self._theta3, self._theta3s = compute_chirptimes( self._mchirp, self._eta, self.chired, self.flow )
def __init__(self, m1, m2, spin1z, spin2z, bank): AlignedSpinTemplate.__init__(self, m1, m2, spin1z, spin2z, bank) self.chired = lalsim.SimInspiralTaylorF2ReducedSpinComputeChi( m1, m2, spin1z, spin2z) self._dur = self._get_dur() self._eta = m1 * m2 / (m1 + m2)**2 self._theta0, self._theta3, self._theta3s = compute_chirptimes( self._mchirp, self._eta, self.chired, self.bank.flow)
def __init__(self, m1, m2, spin1z, spin2z, bank, flow=None, duration=None): self.chired = lalsim.SimInspiralTaylorF2ReducedSpinComputeChi( m1, m2, spin1z, spin2z ) AlignedSpinTemplate.__init__(self, m1, m2, spin1z, spin2z, bank, flow=flow, duration=duration)
def __init__(self, m1, m2, s1x, s1y, s1z, s2x, s2y, s2z, inclination, theta, phi, psi, bank): Template.__init__(self, m1, m2, bank) self.m1 = float(m1) self.m2 = float(m2) self.s1x = float(s1x) self.s1y = float(s1y) self.s1z = float(s1z) self.s2x = float(s2x) self.s2y = float(s2y) self.s2z = float(s2z) self.inclination = float(inclination) self.theta = float(theta) self.phi = float(phi) self.psi = float(psi) self.bank = bank # derived quantities self._dur = lalsim.SimInspiralTaylorF2ReducedSpinChirpTime( bank.flow, m1 * MSUN_SI, m2 * MSUN_SI, lalsim.SimInspiralTaylorF2ReducedSpinComputeChi( self.m1 * MSUN_SI, self.m2 * MSUN_SI, self.s1z, self.s2z), 7) self._mchirp = compute_mchirp(m1, m2)
def chi(self): return lalsimulation.SimInspiralTaylorF2ReducedSpinComputeChi( self.mass1, self.mass2, self.spin1z, self.spin2z)
def __init__(self, m1, m2, spin1z, spin2z, bank): self.chired = lalsim.SimInspiralTaylorF2ReducedSpinComputeChi( m1, m2, spin1z, spin2z) AlignedSpinTemplate.__init__(self, m1, m2, spin1z, spin2z, bank)
def evolve_spins_dt(v0, m1, m2, chi1x, chi1y, chi1z, chi2x, chi2y, chi2z, Lnx, Lny, Lnz, v_final, dt): """ evolve the spins and orb ang momentum according to the PN precession eqns.""" # Set maximum dv/dt for stopping condition dvdt_max = 1.e-4 # Set maximum deviation from v_final allowed (unless dv/dt is greater than dvdt_max or negative, in which case just print a warning) delta_vf_max = 1.e-2 # Set largest deviation from normalization of orbital angular momentum allowed delta_Lnorm_max = 1.e-8 # Give indices for various quantities in the solution vector V_POS = 0 # Location of v (and thus dv/dt) LNX_POS = 7 # Location of the x component of Ln LNY_POS = 8 # Location of the y component of Ln LNZ_POS = 9 # Location of the z component of Ln # some sanity checks if m1 < 0: raise ValueError("ERROR: mass1 is negative") if m2 < 0: raise ValueError("ERROR: mass2 is negative") if (chi1x**2 + chi1y**2 + chi1z**2) > 1.: raise ValueError("ERROR: magnitude of spin1 is greater than 1") if (chi2x**2 + chi2y**2 + chi2z**2) > 1.: raise ValueError("ERROR: magnitude of spin2 is greater than 1") if dt < 0: raise ValueError("ERROR: time step is negative") m1_sqr = m1 * m1 m2_sqr = m2 * m2 # pack the inputs y_vec0 = [ v0, chi1x * m1_sqr, chi1y * m1_sqr, chi1z * m1_sqr, chi2x * m2_sqr, chi2y * m2_sqr, chi2z * m2_sqr, Lnx, Lny, Lnz ] t0 = 0. # Defining chi_eff and Newtonian chirp time. T_MAX is set to twice of chirp time. chi_eff = lalsim.SimInspiralTaylorF2ReducedSpinComputeChi( m1, m2, chi1z, chi2z) T_MAX = 2. * lalsim.SimInspiralTaylorF2ReducedSpinChirpTime( v0**3. / (PI * (m1 + m2) * MTSUN_SI), m1 * MSUN_SI, m2 * MSUN_SI, chi_eff, 0) / MTSUN_SI R_TOL = 1e-6 A_TOL = 1e-6 #print("T_MAX = %f"%(T_MAX)) # initialize the ODE solver backend = "dopri5" solver = ode(precession_eqns) solver.set_integrator(backend, atol=R_TOL, rtol=R_TOL) # nsteps=1 solver.set_initial_value(y_vec0, t0) solver.set_f_params(m1, m2) y_result = [] t_output = [] y_result.append(y_vec0) t_output.append(t0) # Set diagnostic quantities to some initial values that won't trigger any stopping conditions v_current = 0. dvdt_current = 1.e-5 Lnorm_current = 1. # evolve the eqns while solver.successful( ) and solver.t < 2. * T_MAX and v_current <= v_final and dvdt_current > 0. and dvdt_current < dvdt_max and abs( Lnorm_current - 1.) < delta_Lnorm_max: solver.integrate(solver.t + dt, step=1) y_result.append(solver.y) t_output.append(solver.t) #print '... t = ', solver.t, ' y = ', solver.y v_current = solver.y[V_POS] dvdt_current = precession_eqns(solver.t, solver.y, m1, m2)[V_POS] Lnorm_current = np.sqrt((solver.y[LNX_POS])**2 + (solver.y[LNY_POS])**2 + (solver.y[LNZ_POS])**2) Y = np.array(y_result) t = np.array(t_output) # Check if the integration stopped more than delta_vf_max away from v_final. If so, check if this occurred because dv/dt became larger than dvdt_max or negative. In this case, print a warning and remove the offending data, else raise an error v_last = Y.T[V_POS][-1] if abs(v_last - v_final) > delta_vf_max: if dvdt_current <= 0 or dvdt_current > dvdt_max: Y = np.delete(Y, -1, axis=0) print( "Warning: Integration stopped at v_max = {0}, more than {1} different from v_final = {2}, because dv/dt became negative or exceeded {3}, with a value of {4}. The final value used is {5}." .format(v_last, delta_vf_max, v_final, dvdt_max, dvdt_current, precession_eqns(t, Y[-1], m1, m2)[V_POS])) else: raise ValueError( "v_max = {0} is more than {1} different from v_final = {2} and dv/dt is positive and less than {3}" .format(v_v[-1], delta_vf, v_final, dvdt_max)) if abs(Lnorm_current - 1.) >= delta_Lnorm_max: raise ValueError( "norm of Ln is more than {0:e} different from 1, with distance {1:e}" .format(delta_Lnorm_max, abs(Lnorm_current - 1.))) v_v, S1x_v, S1y_v, S1z_v, S2x_v, S2y_v, S2z_v, Lx_v, Ly_v, Lz_v = Y.T return v_v, S1x_v / m1_sqr, S1y_v / m1_sqr, S1z_v / m1_sqr, S2x_v / m2_sqr, S2y_v / m2_sqr, S2z_v / m2_sqr, Lx_v, Ly_v, Lz_v
def evolve_spins_dt(v0, m1, m2, chi1x, chi1y, chi1z, chi2x, chi2y, chi2z, Lnx, Lny, Lnz, v_final, dt): """ evolve the spins and orb ang momentum according to the PN precession eqns.""" # some sanity checks if m1<0: raise ValueError("ERROR: mass1 is negative") if m2<0: raise ValueError("ERROR: mass2 is negative") if (chi1x**2+chi1y**2+chi1z**2)>1.: raise ValueError("ERROR: magnitude of spin1 is greater than 1") if (chi2x**2+chi2y**2+chi2z**2)>1.: raise ValueError("ERROR: magnitude of spin2 is greater than 1") if dt<0: raise ValueError("ERROR: time step is negative") m1_sqr = m1*m1 m2_sqr = m2*m2 # pack the inputs y_vec0 = [v0, chi1x*m1_sqr, chi1y*m1_sqr, chi1z*m1_sqr, chi2x*m2_sqr, chi2y*m2_sqr, chi2z*m2_sqr, Lnx, Lny, Lnz] t0 = 0. # Defining chi_eff and Newtonian chirp time. T_MAX is set to twice of chirp time. chi_eff = lalsim.SimInspiralTaylorF2ReducedSpinComputeChi(m1, m2, chi1z, chi2z) T_MAX = 2.* lalsim.SimInspiralTaylorF2ReducedSpinChirpTime(v0**3./(PI*(m1+m2)*MTSUN_SI), m1*MSUN_SI, m2*MSUN_SI, chi_eff, 0)/MTSUN_SI R_TOL = 1e-6 A_TOL = 1e-6 #print("T_MAX = %f"%(T_MAX)) # initialize the ODE solver backend = "dopri5" solver = ode(precession_eqns) solver.set_integrator(backend, atol=R_TOL, rtol=R_TOL) # nsteps=1 solver.set_initial_value(y_vec0, t0) solver.set_f_params(m1, m2) y_result = [] t_output = [] y_result.append(y_vec0) t_output.append(t0) # evolve the eqns while solver.successful() and solver.t < 2.*T_MAX and solver.y[0] <= v_final and abs(np.sqrt((solver.y[7])**2+(solver.y[8])**2+(solver.y[9])**2)-1.)<1e-8: solver.integrate(solver.t + dt, step=1) y_result.append(solver.y) t_output.append(solver.t) #print '... t = ', solver.t, ' y = ', solver.y Y = np.array(y_result) t = np.array(t_output) v_v, S1x_v, S1y_v, S1z_v, S2x_v, S2y_v, S2z_v, Lx_v, Ly_v, Lz_v = Y.T if abs(v_v[-1]-v_final)>1e-2: raise ValueError("v_max = {0} is more than 0.01 different from v_final = {1}".format(v_v[-1], v_final)) if abs(np.sqrt((solver.y[7])**2+(solver.y[8])**2+(solver.y[9])**2)-1.)>=1e-8: raise ValueError("norm of Ln is more than 10^{-8} different from 1, with distance {0}".format(abs(np.sqrt((solver.y[7])**2+(solver.y[8])**2+(solver.y[9])**2)-1.))) return v_v, S1x_v/m1_sqr, S1y_v/m1_sqr, S1z_v/m1_sqr, S2x_v/m2_sqr, S2y_v/m2_sqr, S2z_v/m2_sqr, Lx_v, Ly_v, Lz_v