LALSimulation  5.4.0.1-fe68b98
LALSimBHNSRemnantFits.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <complex.h>
5 #include <lal/LALStdlib.h>
6 #include <lal/LALConstants.h>
7 #include <lal/Date.h>
8 #include <lal/Units.h>
9 #include <lal/LALSimIMR.h>
10 
11 #include "LALSimBHNSRemnantFits.h"
12 
13 /**
14  * @author Andrew Matas, Jonathan Thompson, Edward Fauchon-Jones, Sebastian Khan
15  * @addtogroup LALSimBHNSRemnantFits_c Module LALSimBHNSRemnantFits.c
16  * @ingroup lalsimulation_general
17  * @brief Provides routines for NSBH remnant fits.
18  *
19  * This module provides an implementation of the NSBH remnant fits described by
20  * \cite Zappa:2019ntl and the underlying BBH remnant fits described by
21  * \cite Jimenez-Forteza:2016oae. For a standalone python implementation please
22  * see https://git.tpi.uni-jena.de/core/bhnsremnant.
23  * @{
24  *
25  * @name NSBH remnant routines
26  * @{
27  */
28 
29 /**
30  * Compute final black hole mass for aligned black hole spin
31  *
32  * See Table I (p7) in https://arxiv.org/abs/1903.11622 for the definition of
33  * the coefficients of this model.
34  */
36  const REAL8 m1, /**< Mass of BH (companion 1) (solar masses) */
37  const REAL8 m2, /**< Mass of NS (companion 2) (solar masses) */
38  const REAL8 chi1, /**< Dimensionless spin of BH (companion 1) */
39  const REAL8 lam /**< Dimensionless tidal deformability of NS (companion 2) */
40 ){
41  //TODO: Insert error checkking
42  REAL8 mtot=m1+m2;
43  REAL8 nu=m1*m2/pow(mtot,2);
44  REAL8 massc[]={-1.83417425e-03, 2.39226041e-03, 4.29407902e-03, 9.79775571e-03,
45  2.33868869e-07, -8.28090025e-07, -1.64315549e-06, 8.08340931e-06,
46  -2.00726981e-02, 1.31986011e-01, 6.50754064e-02, -1.42749961e-01};
47  REAL8 model=model3a(nu,chi1,lam,massc);
48  if(chi1<0 && nu<0.188){
49  model=1;
50  }
51  if(chi1<-0.5){
52  model=1;
53  }
54  if(model>1){
55  model=1;
56  }
57  return XLALbbh_final_mass_non_precessing_UIB2016(m1,m2,chi1,0.) * model;
58 }
59 
60 /**
61  * Compute final black hole spin for aligned black hole spin
62  *
63  * See Table I (p7) in https://arxiv.org/abs/1903.11622 for the definition of
64  * the coefficients of this model.
65  */
67  const REAL8 m1, /**< Mass of BH (companion 1) (solar masses) */
68  const REAL8 m2, /**< Mass of NS (companion 2) (solar masses) */
69  const REAL8 chi1, /**< Dimensionless spin of BH (companion 1) */
70  const REAL8 lam /**< Dimensionless tidal deformability of NS (companion 2) */
71 ){
72  //TODO: Insert error checking
73  REAL8 mtot=m1+m2;
74  REAL8 nu=m1*m2/pow(mtot,2);
75  REAL8 spinc[]={-5.44187381e-03, 7.91165608e-03, 2.33362046e-02, 2.47764497e-02,
76  -8.56844797e-07, -2.81727682e-06, 6.61290966e-06, 4.28979016e-05,
77  -3.04174272e-02, 2.54889050e-01, 1.47549350e-01, -4.27905832e-01};
78 
79  REAL8 model=model3a(nu,chi1,lam,spinc);
80  if(chi1<0 && nu<0.188){
81  model=1;
82  }
83  if(chi1<-0.5){
84  model=1;
85  }
86  if(model>1){
87  model=1;
88  }
89  return XLALbbh_final_spin_non_precessing_UIB2016(m1,m2,chi1,0.) * model;
90 }
91 
92 /**
93  * Template 3D model for an NSBH remnant property
94  *
95  * See Eq. (4) (p7) in https://arxiv.org/abs/1903.11622 for the definition of
96  * this function.
97  */
98 static REAL8 model3a(
99  const REAL8 nu, /**< Symmetric mass ratio */
100  const REAL8 ai, /**< Dimensionless spin of BH (companion 1) */
101  const REAL8 lam, /**< Dimensionless tidal deformability of NS (companion 2) */
102  const REAL8 *par /**< Best fit parameters for particular instance of remnant fit */
103 ){
104  REAL8 p[]={0,0,0};
105  pijk_to_pk(p,nu,ai,par);
106  return model1a(lam,p);
107 }
108 
109 /**
110  * Calculate parameters for 1D model
111  *
112  * See Eq. (5,6) (p7) in https://arxiv.org/abs/1903.11622 for the definition of
113  * this function.
114  */
115 static void pijk_to_pk(
116  REAL8 *p, /**< Output: Coefficients for 1D model */
117  const REAL8 nu, /**< Symmetric mass ratio */
118  const REAL8 ai, /**< Dimensionless spin of BH (companion 1) */
119  const REAL8 *par /**< Best fit parameters for particular instance of remnant fit */
120 ){
121  //REAL8 p[] = {0, 0, 0};
122  REAL8 p110 = par[0];
123  REAL8 p111 = par[1];
124  REAL8 p120 = par[2];
125  REAL8 p121 = par[3];
126  REAL8 p210 = par[4];
127  REAL8 p211 = par[5];
128  REAL8 p220 = par[6];
129  REAL8 p221 = par[7];
130  REAL8 p310 = par[8];
131  REAL8 p311 = par[9];
132  REAL8 p320 = par[10];
133  REAL8 p321 = par[11];
134  REAL8 p11 = p110*ai + p111;
135  REAL8 p12 = p120*ai + p121;
136  REAL8 p21 = p210*ai + p211;
137  REAL8 p22 = p220*ai + p221;
138  REAL8 p31 = p310*ai + p311;
139  REAL8 p32 = p320*ai + p321;
140  p[0] = (p11 + p12*nu)*nu;
141  p[1] = (p21 + p22*nu)*nu;
142  p[2] = (p31 + p32*nu)*nu;
143  //return p;
144 }
145 
146 /**
147  * Template 1D model for an NSBH remnant property
148  *
149  * See Eq. (4) (p7) in https://arxiv.org/abs/1903.11622 for the definition of
150  * this function.
151  */
152 static double model1a(
153  const REAL8 x, /**< Input parameter for 1D model */
154  const REAL8 *p /**< Coefficients for 1D model */
155 ){
156  return (1 + x * p[0] + pow(x,2) * p[1]) / pow(1 + x * pow(p[2],2),2);
157 }
158 
159 /**
160  * @}
161  *
162  * @name BBH remnant routines
163  * @{
164  */
165 
166 /**
167  * Calculate the final mass with the aligned-spin NR fit
168  *
169  * Calculate the final mass with the aligned-spin NR fit by Xisco Jimenez
170  * Forteza, David Keitel, Sascha Husa et al. [LIGO-P1600270]
171  * [https://arxiv.org/abs/1611.00332] versions v1 and v2 use the same ansatz,
172  * with v2 calibrated to additional SXS and RIT data
173  */
175  const REAL8 m1, /**< component mass of first BH (solar masses) */
176  const REAL8 m2, /**< component mass of second BH (solar masses) */
177  const REAL8 chi1, /**< dimensionless spin of first BH */
178  const REAL8 chi2 /**< dimensionless spin of second BH */
179 ){
180  // binary masses
181  REAL8 m = m1+m2;
182  REAL8 msq = m*m;
183  REAL8 m1sq = m1*m1;
184  REAL8 m2sq = m2*m2;
185  // symmetric mass ratio
186  REAL8 eta = m1*m2/msq;
187  if (eta>0.25){
188  printf("Truncating eta from above to 0.25. This should only be necessary in some rounding corner cases, but better check your m1 and m2 inputs...");
189  eta = 0.25;
190  }
191  if (eta<0.0){
192  printf("Truncating negative eta to 0.0. This should only be necessary in some rounding corner cases, but better check your m1 and m2 inputs...");
193  eta = 0.0;
194  }
195  REAL8 eta2 = eta*eta;
196  REAL8 eta3 = eta2*eta;
197  REAL8 eta4 = eta2*eta2;
198  // spin variables (in m = 1 units)
199  //REAL8 S1 = chi1*m1sq/msq; // spin angular momentum 1
200  //REAL8 S2 = chi2*m2sq/msq; // spin angular momentum 2
201  //REAL8 Stot = S1+S2; // total spin
202  REAL8 Shat = (chi1*m1sq+chi2*m2sq)/(m1sq+m2sq); // effective spin, = msq*Stot/(m1sq+m2sq)
203  REAL8 Shat2 = Shat*Shat;
204  REAL8 Shat3 = Shat2*Shat;
205  //REAL8 Shat4 = Shat2*Shat2;
206  // spin difference, assuming m1>m2
207  REAL8 chidiff = chi1 - chi2;
208  if (m2>m1){ // fit assumes m1>m2
209  chidiff = -chidiff;
210  }
211  REAL8 chidiff2 = chidiff*chidiff;
212  // typical squareroots and functions of eta
213  REAL8 sqrt2 = pow(2.,0.5);
214  //REAL8 sqrt3 = pow(3.,0.5);
215  REAL8 sqrt1m4eta = pow((1. - 4.*eta),0.5);
216 
217 
218  // rational-function Pade coefficients (exact) from Eq. (22) of 1611.00332v2
219  REAL8 b10 = 0.346;
220  REAL8 b20 = 0.211;
221  REAL8 b30 = 0.128;
222  REAL8 b50 = -0.212;
223  // fit coefficients from Tables VII-X of 1611.00332v2
224  // values at increased numerical precision copied from
225  // https://git.ligo.org/uib-papers/finalstate2016/blob/master/LALInference/EradUIB2016v2_pyform_coeffs.txt
226  // git commit f490774d3593adff5bb09ae26b7efc6deab76a42
227  REAL8 a2 = 0.5609904135313374;
228  REAL8 a3 = -0.84667563764404;
229  REAL8 a4 = 3.145145224278187;
230  REAL8 b1 = -0.2091189048177395;
231  REAL8 b2 = -0.19709136361080587;
232  REAL8 b3 = -0.1588185739358418;
233  REAL8 b5 = 2.9852925538232014;
234  REAL8 f20 = 4.271313308472851;
235  REAL8 f30 = 31.08987570280556;
236  REAL8 f50 = 1.5673498395263061;
237  REAL8 f10 = 1.8083565298668276;
238  REAL8 f21 = 0.;
239  REAL8 d10 = -0.09803730445895877;
240  REAL8 d11 = -3.2283713377939134;
241  REAL8 d20 = 0.01118530335431078;
242  REAL8 d30 = -0.01978238971523653;
243  REAL8 d31 = -4.91667749015812;
244  REAL8 f11 = 15.738082204419655;
245  REAL8 f31 = -243.6299258830685;
246  REAL8 f51 = -0.5808669012986468;
247  // Calculate the radiated-energy fit from Eq. (27) of 1611.00332
248  REAL8 Erad = (((1. + -2.0/3.0*sqrt2)*eta + a2*eta2 + a3*eta3 + a4*eta4)*(1. + b10*b1*Shat*(f10 + f11*eta + (16. - 16.*f10 - 4.*f11)*eta2) + b20*b2*Shat2*(f20 + f21*eta + (16. - 16.*f20 - 4.*f21)*eta2) + b30*b3*Shat3*(f30 + f31*eta + (16. - 16.*f30 - 4.*f31)*eta2)))/(1. + b50*b5*Shat*(f50 + f51*eta + (16. - 16.*f50 - 4.*f51)*eta2)) + d10*sqrt1m4eta*eta2*(1. + d11*eta)*chidiff + d30*Shat*sqrt1m4eta*eta*(1. + d31*eta)*chidiff + d20*eta3*chidiff2;
249  // Convert to actual final mass
250  REAL8 Mf = m*(1.-Erad);
251  return Mf;
252 }
253 
254 /**
255  * Calculate the final spin with the aligned-spin NR fit
256  *
257  * Calculate the final spin with the aligned-spin NR fit by Xisco Jimenez
258  * Forteza, David Keitel, Sascha Husa et al. [LIGO-P1600270]
259  * [https://arxiv.org/abs/1611.00332] versions v1 and v2 use the same ansatz,
260  * with v2 calibrated to additional SXS and RIT data
261  */
263  const REAL8 m1, /**< component mass of first BH (solar masses) */
264  const REAL8 m2, /**< component mass of second BH (solar masses) */
265  const REAL8 chi1, /**< dimensionless spin of first BH */
266  const REAL8 chi2 /**< dimensionless spin of second BH */
267 ){
268  // binary masses
269  REAL8 m = m1+m2;
270  REAL8 msq = m*m;
271  REAL8 m1sq = m1*m1;
272  REAL8 m2sq = m2*m2;
273  // symmetric mass ratio
274  REAL8 eta = m1*m2/msq;
275  if (eta>0.25){
276  printf("Truncating eta from above to 0.25. This should only be necessary in some rounding corner cases, but better check your m1 and m2 inputs...");
277  eta = 0.25;
278  }
279  if (eta<0.0){
280  printf("Truncating negative eta to 0.0. This should only be necessary in some rounding corner cases, but better check your m1 and m2 inputs...");
281  eta = 0.0;
282  }
283  REAL8 eta2 = eta*eta;
284  REAL8 eta3 = eta2*eta;
285  //REAL8 eta4 = eta2*eta2;
286  // spin variables (in m = 1 units)
287  REAL8 S1 = chi1*m1sq/msq; // spin angular momentum 1
288  REAL8 S2 = chi2*m2sq/msq; // spin angular momentum 2
289  REAL8 Stot = S1+S2; // total spin
290  REAL8 Shat = (chi1*m1sq+chi2*m2sq)/(m1sq+m2sq); // effective spin, = msq*Stot/(m1sq+m2sq)
291  REAL8 Shat2 = Shat*Shat;
292  REAL8 Shat3 = Shat2*Shat;
293  //REAL8 Shat4 = Shat2*Shat2;
294  // spin difference, assuming m1>m2
295  REAL8 chidiff = chi1 - chi2;
296  if (m2>m1){ // fit assumes m1>m2
297  chidiff = -chidiff;
298  }
299  REAL8 chidiff2 = chidiff*chidiff;
300  // typical squareroots and functions of eta
301  //REAL8 sqrt2 = pow(2.,0.5);
302  REAL8 sqrt3 = pow(3.,0.5);
303  REAL8 sqrt1m4eta = pow((1. - 4.*eta),0.5);
304 
305 
306  REAL8 a20 = 5.24;
307  REAL8 a30 = 1.3;
308  REAL8 a50 = 2.88;
309  REAL8 b10 = -0.194;
310  REAL8 b20 = 0.0851;
311  REAL8 b30 = 0.00954;
312  REAL8 b50 = -0.579;
313  // fit coefficients from Tables I-IV of 1611.00332v2
314  // values at increased numerical precision copied from
315  // https://git.ligo.org/uib-papers/finalstate2016/blob/master/LALInference/FinalSpinUIB2016v2_pyform_coeffs.txt
316  // git commit f490774d3593adff5bb09ae26b7efc6deab76a42
317  REAL8 a2 = 3.8326341618708577;
318  REAL8 a3 = -9.487364155598392;
319  REAL8 a5 = 2.5134875145648374;
320  REAL8 b1 = 1.0009563702914628;
321  REAL8 b2 = 0.7877509372255369;
322  REAL8 b3 = 0.6540138407185817;
323  REAL8 b5 = 0.8396665722805308;
324  REAL8 f21 = 8.77367320110712;
325  REAL8 f31 = 22.830033250479833;
326  REAL8 f50 = 1.8804718791591157;
327  REAL8 f11 = 4.409160174224525;
328  REAL8 f52 = 0.;
329  REAL8 d10 = 0.3223660562764661;
330  REAL8 d11 = 9.332575956437443;
331  REAL8 d20 = -0.059808322561702126;
332  REAL8 d30 = 2.3170397514509933;
333  REAL8 d31 = -3.2624649875884852;
334  REAL8 f12 = 0.5118334706832706;
335  REAL8 f22 = -32.060648277652994;
336  REAL8 f32 = -153.83722669033995;
337  REAL8 f51 = -4.770246856212403;
338 
339  // Calculate the fit for the Lorb' quantity from Eq. (16) of 1611.00332
340  REAL8 Lorb = (2.*sqrt3*eta + a20*a2*eta2 + a30*a3*eta3)/(1. + a50*a5*eta) + (b10*b1*Shat*(f11*eta + f12*eta2 + (64. - 16.*f11 - 4.*f12)*eta3) + b20*b2*Shat2*(f21*eta + f22*eta2 + (64. - 16.*f21 - 4.*f22)*eta3) + b30*b3*Shat3*(f31*eta + f32*eta2 + (64. - 16.*f31 - 4.*f32)*eta3))/(1. + b50*b5*Shat*(f50 + f51*eta + f52*eta2 + (64. - 64.*f50 - 16.*f51 - 4.*f52)*eta3)) + d10*sqrt1m4eta*eta2*(1. + d11*eta)*chidiff + d30*Shat*sqrt1m4eta*eta3*(1. + d31*eta)*chidiff + d20*eta3*chidiff2;
341  // Convert to actual final spin
342  REAL8 chif = Lorb + Stot;
343  return chif;
344 
345 }
346 
347 /** @} */
348 
349 /** @} */
const double b1
const double b2
const double a4
const double a2
double REAL8
static REAL8 model3a(const REAL8 nu, const REAL8 ai, const REAL8 lam, const REAL8 *par)
Template 3D model for an NSBH remnant property.
REAL8 XLALBHNS_spin_aligned(const REAL8 m1, const REAL8 m2, const REAL8 chi1, const REAL8 lam)
Compute final black hole spin for aligned black hole spin.
static void pijk_to_pk(REAL8 *p, const REAL8 nu, const REAL8 ai, const REAL8 *par)
Calculate parameters for 1D model.
REAL8 XLALbbh_final_mass_non_precessing_UIB2016(const REAL8 m1, const REAL8 m2, const REAL8 chi1, const REAL8 chi2)
Calculate the final mass with the aligned-spin NR fit.
REAL8 XLALbbh_final_spin_non_precessing_UIB2016(const REAL8 m1, const REAL8 m2, const REAL8 chi1, const REAL8 chi2)
Calculate the final spin with the aligned-spin NR fit.
REAL8 XLALBHNS_mass_aligned(const REAL8 m1, const REAL8 m2, const REAL8 chi1, const REAL8 lam)
Compute final black hole mass for aligned black hole spin.
static double model1a(const REAL8 x, const REAL8 *p)
Template 1D model for an NSBH remnant property.
static const INT4 m
list x
list p