ml4gw 0.4.2__py3-none-any.whl → 0.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ml4gw might be problematic. Click here for more details.

@@ -1,1361 +1,1443 @@
1
1
  import torch
2
- from torchtyping import TensorType
3
-
4
- from . import phenom_d_data
5
- from .taylorf2 import MTSUN_SI, PI, taylorf2_amplitude, taylorf2_phase
6
-
7
-
8
- # Utility functions taken from PhenomD utilities in lalsimulation
9
- # https://git.ligo.org/lscsoft/lalsuite/-/blob/master/lalsimulation/lib/LALSimIMRPhenomD_internals.c
10
- def sigma1Fit(eta, eta2, xi):
11
- return (
12
- 2096.551999295543
13
- + 1463.7493168261553 * eta
14
- + (
15
- 1312.5493286098522
16
- + 18307.330017082117 * eta
17
- - 43534.1440746107 * eta2
18
- + (
19
- -833.2889543511114
20
- + 32047.31997183187 * eta
21
- - 108609.45037520859 * eta2
22
- )
23
- * xi
24
- + (
25
- 452.25136398112204
26
- + 8353.439546391714 * eta
27
- - 44531.3250037322 * eta2
28
- )
29
- * xi
30
- * xi
2
+ from jaxtyping import Float
3
+
4
+ from ml4gw.constants import MTSUN_SI, PI
5
+ from ml4gw.types import BatchTensor, FrequencySeries1d
6
+
7
+ from .phenom_d_data import QNMData_a, QNMData_fdamp, QNMData_fring
8
+ from .taylorf2 import TaylorF2
9
+
10
+
11
+ class IMRPhenomD(TaylorF2):
12
+ def __init__(self):
13
+ super().__init__()
14
+ self.register_buffer("qnmdata_a", QNMData_a)
15
+ self.register_buffer("qnmdata_fdamp", QNMData_fdamp)
16
+ self.register_buffer("qnmdata_fring", QNMData_fring)
17
+
18
+ def forward(
19
+ self,
20
+ f: FrequencySeries1d,
21
+ chirp_mass: BatchTensor,
22
+ mass_ratio: BatchTensor,
23
+ chi1: BatchTensor,
24
+ chi2: BatchTensor,
25
+ distance: BatchTensor,
26
+ phic: BatchTensor,
27
+ inclination: BatchTensor,
28
+ f_ref: float,
29
+ ):
30
+ """
31
+ IMRPhenomD waveform
32
+
33
+ Args:
34
+ f:
35
+ Frequency series in Hz.
36
+ chirp_mass:
37
+ Chirp mass in solar masses
38
+ mass_ratio:
39
+ Mass ratio m1/m2
40
+ chi1:
41
+ Spin of m1
42
+ chi2:
43
+ Spin of m2
44
+ distance:
45
+ Distance to source in Mpc
46
+ phic:
47
+ Phase at coalescence
48
+ inclination:
49
+ Inclination of the source
50
+ f_ref:
51
+ Reference frequency
52
+
53
+ Returns:
54
+ hc, hp: Tuple[torch.Tensor, torch.Tensor]
55
+ Cross and plus polarizations
56
+ """
57
+ # shape assumed (n_batch, params)
58
+ if (
59
+ chirp_mass.shape[0] != mass_ratio.shape[0]
60
+ or mass_ratio.shape[0] != chi1.shape[0]
61
+ or chi1.shape[0] != chi2.shape[0]
62
+ or chi2.shape[0] != distance.shape[0]
63
+ or distance.shape[0] != phic.shape[0]
64
+ or phic.shape[0] != inclination.shape[0]
65
+ ):
66
+ raise RuntimeError("Tensors should have same batch size")
67
+ cfac = torch.cos(inclination)
68
+ pfac = 0.5 * (1.0 + cfac * cfac)
69
+
70
+ htilde = self.phenom_d_htilde(
71
+ f, chirp_mass, mass_ratio, chi1, chi2, distance, phic, f_ref
31
72
  )
32
- * xi
33
- )
34
-
35
-
36
- def sigma2Fit(eta, eta2, xi):
37
- return (
38
- -10114.056472621156
39
- - 44631.01109458185 * eta
40
- + (
41
- -6541.308761668722
42
- - 266959.23419307504 * eta
43
- + 686328.3229317984 * eta2
44
- + (
45
- 3405.6372187679685
46
- - 437507.7208209015 * eta
47
- + 1.6318171307344697e6 * eta2
48
- )
49
- * xi
50
- + (
51
- -7462.648563007646
52
- - 114585.25177153319 * eta
53
- + 674402.4689098676 * eta2
54
- )
55
- * xi
56
- * xi
73
+
74
+ hp = (htilde.mT * pfac).mT
75
+ hc = -1j * (htilde.mT * cfac).mT
76
+
77
+ return hc, hp
78
+
79
+ def phenom_d_htilde(
80
+ self,
81
+ f: FrequencySeries1d,
82
+ chirp_mass: BatchTensor,
83
+ mass_ratio: BatchTensor,
84
+ chi1: BatchTensor,
85
+ chi2: BatchTensor,
86
+ distance: BatchTensor,
87
+ phic: BatchTensor,
88
+ f_ref: float,
89
+ ) -> Float[FrequencySeries1d, " batch"]:
90
+ total_mass = chirp_mass * (1 + mass_ratio) ** 1.2 / mass_ratio**0.6
91
+ mass_1 = total_mass / (1 + mass_ratio)
92
+ mass_2 = mass_1 * mass_ratio
93
+ eta = (chirp_mass / total_mass) ** (5 / 3)
94
+ eta2 = eta * eta
95
+ Seta = torch.sqrt(1.0 - 4.0 * eta)
96
+ chi = self.chiPN(Seta, eta, chi1, chi2)
97
+ chi22 = chi2 * chi2
98
+ chi12 = chi1 * chi1
99
+ xi = -1.0 + chi
100
+ M_s = total_mass * MTSUN_SI
101
+
102
+ gamma2 = self.gamma2_fun(eta, eta2, xi)
103
+ gamma3 = self.gamma3_fun(eta, eta2, xi)
104
+
105
+ fRD, fDM = self.fring_fdamp(eta, eta2, chi1, chi2)
106
+ Mf_peak = self.fmaxCalc(fRD, fDM, gamma2, gamma3)
107
+ _, t0 = self.phenom_d_mrd_phase(Mf_peak, eta, eta2, chi1, chi2, xi)
108
+
109
+ Mf = torch.outer(M_s, f)
110
+ Mf_ref = torch.outer(M_s, f_ref * torch.ones_like(f))
111
+
112
+ Psi, _ = self.phenom_d_phase(
113
+ Mf, mass_1, mass_2, eta, eta2, chi1, chi2, xi
57
114
  )
58
- * xi
59
- )
60
-
61
-
62
- def sigma3Fit(eta, eta2, xi):
63
- return (
64
- 22933.658273436497
65
- + 230960.00814979506 * eta
66
- + (
67
- 14961.083974183695
68
- + 1.1940181342318142e6 * eta
69
- - 3.1042239693052764e6 * eta2
70
- + (
71
- -3038.166617199259
72
- + 1.8720322849093592e6 * eta
73
- - 7.309145012085539e6 * eta2
74
- )
75
- * xi
76
- + (
77
- 42738.22871475411
78
- + 467502.018616601 * eta
79
- - 3.064853498512499e6 * eta2
80
- )
81
- * xi
82
- * xi
115
+ Psi_ref, _ = self.phenom_d_phase(
116
+ Mf_ref, mass_1, mass_2, eta, eta2, chi1, chi2, xi
83
117
  )
84
- * xi
85
- )
86
-
87
-
88
- def sigma4Fit(eta, eta2, xi):
89
- return (
90
- -14621.71522218357
91
- - 377812.8579387104 * eta
92
- + (
93
- -9608.682631509726
94
- - 1.7108925257214056e6 * eta
95
- + 4.332924601416521e6 * eta2
96
- + (
97
- -22366.683262266528
98
- - 2.5019716386377467e6 * eta
99
- + 1.0274495902259542e7 * eta2
100
- )
101
- * xi
102
- + (
103
- -85360.30079034246
104
- - 570025.3441737515 * eta
105
- + 4.396844346849777e6 * eta2
106
- )
107
- * xi
108
- * xi
118
+
119
+ Psi = (Psi.mT - 2 * phic).mT
120
+ Psi -= Psi_ref
121
+ Psi -= ((Mf - Mf_ref).mT * t0).mT
122
+
123
+ amp, _ = self.phenom_d_amp(
124
+ Mf,
125
+ mass_1,
126
+ mass_2,
127
+ eta,
128
+ eta2,
129
+ Seta,
130
+ chi1,
131
+ chi2,
132
+ chi12,
133
+ chi22,
134
+ xi,
135
+ distance,
109
136
  )
110
- * xi
111
- )
112
-
113
-
114
- def gamma1_fun(eta, eta2, xi):
115
- return (
116
- 0.006927402739328343
117
- + 0.03020474290328911 * eta
118
- + (
119
- 0.006308024337706171
120
- - 0.12074130661131138 * eta
121
- + 0.26271598905781324 * eta2
122
- + (
123
- 0.0034151773647198794
124
- - 0.10779338611188374 * eta
125
- + 0.27098966966891747 * eta2
137
+
138
+ amp_0 = self.taylorf2_amplitude(
139
+ Mf, mass_1, mass_2, eta, distance
140
+ ) # this includes f^(-7/6) dependence
141
+
142
+ h0 = -amp_0 * amp * torch.exp(-1j * Psi)
143
+
144
+ return h0
145
+
146
+ def phenom_d_amp(
147
+ self,
148
+ Mf,
149
+ mass_1,
150
+ mass_2,
151
+ eta,
152
+ eta2,
153
+ Seta,
154
+ chi1,
155
+ chi2,
156
+ chi12,
157
+ chi22,
158
+ xi,
159
+ distance,
160
+ ):
161
+ ins_amp, ins_Damp = self.phenom_d_inspiral_amp(
162
+ Mf, eta, eta2, Seta, xi, chi1, chi2, chi12, chi22
163
+ )
164
+ int_amp, int_Damp = self.phenom_d_int_amp(
165
+ Mf, eta, eta2, Seta, chi1, chi2, chi12, chi22, xi
166
+ )
167
+ mrd_amp, mrd_Damp = self.phenom_d_mrd_amp(
168
+ Mf, eta, eta2, chi1, chi2, xi
169
+ )
170
+
171
+ gamma2 = self.gamma2_fun(eta, eta2, xi)
172
+ gamma3 = self.gamma3_fun(eta, eta2, xi)
173
+ fRD, fDM = self.fring_fdamp(eta, eta2, chi1, chi2)
174
+ Mf_peak = self.fmaxCalc(fRD, fDM, gamma2, gamma3)
175
+ # Geometric peak and joining frequencies
176
+ Mf_peak = (torch.ones_like(Mf).mT * Mf_peak).mT
177
+ Mf_join_ins = 0.014 * torch.ones_like(Mf)
178
+
179
+ # construct full IMR Amp
180
+ theta_minus_f1 = torch.heaviside(
181
+ Mf_join_ins - Mf, torch.tensor(0.0, device=Mf.device)
182
+ )
183
+ theta_plus_f1 = torch.heaviside(
184
+ Mf - Mf_join_ins, torch.tensor(1.0, device=Mf.device)
185
+ )
186
+ theta_minus_f2 = torch.heaviside(
187
+ Mf_peak - Mf, torch.tensor(0.0, device=Mf.device)
188
+ )
189
+ theta_plus_f2 = torch.heaviside(
190
+ Mf - Mf_peak, torch.tensor(1.0, device=Mf.device)
191
+ )
192
+
193
+ amp = theta_minus_f1 * ins_amp
194
+ amp += theta_plus_f1 * int_amp * theta_minus_f2
195
+ amp += theta_plus_f2 * mrd_amp
196
+
197
+ Damp = theta_minus_f1 * ins_Damp
198
+ Damp += theta_plus_f1 * int_Damp * theta_minus_f2
199
+ Damp += theta_plus_f2 * mrd_Damp
200
+
201
+ return amp, Damp
202
+
203
+ def phenom_d_int_amp(
204
+ self, Mf, eta, eta2, Seta, chi1, chi2, chi12, chi22, xi
205
+ ):
206
+ # merger ringdown
207
+ fRD, fDM = self.fring_fdamp(eta, eta2, chi1, chi2)
208
+ # Geometric frequency definition from PhenomD header file
209
+ AMP_fJoin_INS = 0.014
210
+
211
+ Mf1 = AMP_fJoin_INS * torch.ones_like(Mf)
212
+ gamma2 = self.gamma2_fun(eta, eta2, xi)
213
+ gamma3 = self.gamma3_fun(eta, eta2, xi)
214
+
215
+ fpeak = self.fmaxCalc(fRD, fDM, gamma2, gamma3)
216
+ Mf3 = (torch.ones_like(Mf).mT * fpeak).mT
217
+ dfx = 0.5 * (Mf3 - Mf1)
218
+ Mf2 = Mf1 + dfx
219
+
220
+ v1, d1 = self.phenom_d_inspiral_amp(
221
+ Mf1, eta, eta2, Seta, xi, chi1, chi2, chi12, chi22
222
+ )
223
+ v3, d2 = self.phenom_d_mrd_amp(Mf3, eta, eta2, chi1, chi2, xi)
224
+ v2 = (
225
+ torch.ones_like(Mf).mT * self.AmpIntColFitCoeff(eta, eta2, xi)
226
+ ).mT
227
+
228
+ delta_0, delta_1, delta_2, delta_3, delta_4 = self.delta_values(
229
+ f1=Mf1, f2=Mf2, f3=Mf3, v1=v1, v2=v2, v3=v3, d1=d1, d2=d2
230
+ )
231
+
232
+ amp = (
233
+ delta_0
234
+ + Mf * delta_1
235
+ + Mf**2 * (delta_2 + Mf * delta_3 + Mf**2 * delta_4)
236
+ )
237
+ Damp = delta_1 + Mf * (
238
+ 2 * delta_2 + 3 * Mf * delta_3 + 4 * Mf**2 * delta_4
239
+ )
240
+ return amp, Damp
241
+
242
+ def phenom_d_mrd_amp(self, Mf, eta, eta2, chi1, chi2, xi):
243
+ # merger ringdown
244
+ fRD, fDM = self.fring_fdamp(eta, eta2, chi1, chi2)
245
+
246
+ gamma1 = self.gamma1_fun(eta, eta2, xi)
247
+ gamma2 = self.gamma2_fun(eta, eta2, xi)
248
+ gamma3 = self.gamma3_fun(eta, eta2, xi)
249
+ fDMgamma3 = fDM * gamma3
250
+ pow2_fDMgamma3 = (torch.ones_like(Mf).mT * fDMgamma3 * fDMgamma3).mT
251
+ fminfRD = Mf - (torch.ones_like(Mf).mT * fRD).mT
252
+ exp_times_lorentzian = torch.exp(fminfRD.mT * gamma2 / fDMgamma3).mT
253
+ exp_times_lorentzian *= fminfRD**2 + pow2_fDMgamma3
254
+
255
+ amp = (1 / exp_times_lorentzian.mT * gamma1 * gamma3 * fDM).mT
256
+ Damp = (fminfRD.mT * -2 * fDM * gamma1 * gamma3) / (
257
+ fminfRD * fminfRD + pow2_fDMgamma3
258
+ ).mT - (gamma2 * gamma1)
259
+ Damp = Damp.mT / exp_times_lorentzian
260
+ return amp, Damp
261
+
262
+ def phenom_d_inspiral_amp(
263
+ self, Mf, eta, eta2, Seta, xi, chi1, chi2, chi12, chi22
264
+ ):
265
+ SetaPlus1 = 1 + Seta
266
+
267
+ Mf_one_third = Mf ** (1.0 / 3.0)
268
+ Mf_two_third = Mf_one_third * Mf_one_third
269
+ Mf_four_third = Mf_two_third * Mf_two_third
270
+ Mf_five_third = Mf_four_third * Mf_one_third
271
+ Mf_seven_third = Mf_five_third * Mf_two_third
272
+ MF_eight_third = Mf_seven_third * Mf_one_third
273
+ Mf_two = Mf * Mf
274
+ Mf_three = Mf_two * Mf
275
+
276
+ prefactors_two_thirds = ((-969 + 1804 * eta) * PI ** (2.0 / 3.0)) / 672
277
+ prefactors_one = (
278
+ (
279
+ chi1 * (81 * SetaPlus1 - 44 * eta)
280
+ + chi2 * (81 - 81 * Seta - 44 * eta)
126
281
  )
127
- * xi
128
- + (
129
- 0.0007374185938559283
130
- - 0.02749621038376281 * eta
131
- + 0.0733150789135702 * eta2
282
+ * PI
283
+ ) / 48.0
284
+ prefactors_four_thirds = (
285
+ (
286
+ -27312085.0
287
+ - 10287648 * chi22
288
+ - 10287648 * chi12 * SetaPlus1
289
+ + 10287648 * chi22 * Seta
290
+ + 24
291
+ * (
292
+ -1975055
293
+ + 857304 * chi12
294
+ - 994896 * chi1 * chi2
295
+ + 857304 * chi22
296
+ )
297
+ * eta
298
+ + 35371056 * eta2
132
299
  )
133
- * xi
134
- * xi
135
- )
136
- * xi
137
- )
138
-
139
-
140
- def gamma2_fun(eta, eta2, xi):
141
- return (
142
- 1.010344404799477
143
- + 0.0008993122007234548 * eta
144
- + (
145
- 0.283949116804459
146
- - 4.049752962958005 * eta
147
- + 13.207828172665366 * eta2
148
- + (
149
- 0.10396278486805426
150
- - 7.025059158961947 * eta
151
- + 24.784892370130475 * eta2
300
+ * PI ** (4.0 / 3.0)
301
+ ) / 8.128512e6
302
+ prefactors_five_thirds = (
303
+ PI ** (5.0 / 3.0)
304
+ * (
305
+ chi2
306
+ * (
307
+ -285197 * (-1 + Seta)
308
+ + 4 * (-91902 + 1579 * Seta) * eta
309
+ - 35632 * eta2
310
+ )
311
+ + chi1
312
+ * (
313
+ 285197 * SetaPlus1
314
+ - 4 * (91902 + 1579 * Seta) * eta
315
+ - 35632 * eta2
316
+ )
317
+ + 42840 * (-1.0 + 4 * eta) * PI
152
318
  )
153
- * xi
154
- + (
155
- 0.03093202475605892
156
- - 2.6924023896851663 * eta
157
- + 9.609374464684983 * eta2
319
+ ) / 32256.0
320
+ prefactors_two = (
321
+ -(
322
+ PI**2
323
+ * (
324
+ -336
325
+ * (
326
+ -3248849057.0
327
+ + 2943675504 * chi12
328
+ - 3339284256 * chi1 * chi2
329
+ + 2943675504 * chi22
330
+ )
331
+ * eta2
332
+ - 324322727232 * eta2 * eta
333
+ - 7
334
+ * (
335
+ -177520268561
336
+ + 107414046432 * chi22
337
+ + 107414046432 * chi12 * SetaPlus1
338
+ - 107414046432 * chi22 * Seta
339
+ + 11087290368
340
+ * (chi1 + chi2 + chi1 * Seta - chi2 * Seta)
341
+ * PI
342
+ )
343
+ + 12
344
+ * eta
345
+ * (
346
+ -545384828789
347
+ - 176491177632 * chi1 * chi2
348
+ + 202603761360 * chi22
349
+ + 77616 * chi12 * (2610335 + 995766 * Seta)
350
+ - 77287373856 * chi22 * Seta
351
+ + 5841690624 * (chi1 + chi2) * PI
352
+ + 21384760320 * PI**2
353
+ )
354
+ )
158
355
  )
159
- * xi
160
- * xi
356
+ / 6.0085960704e10
357
+ )
358
+ prefactors_seven_thirds = self.rho1_fun(eta, eta2, xi)
359
+ prefactors_eight_thirds = self.rho2_fun(eta, eta2, xi)
360
+ prefactors_three = self.rho3_fun(eta, eta2, xi)
361
+
362
+ amp = torch.ones_like(Mf)
363
+ amp += (
364
+ Mf_two_third.mT * prefactors_two_thirds
365
+ + Mf_four_third.mT * prefactors_four_thirds
366
+ + Mf_five_third.mT * prefactors_five_thirds
367
+ + Mf_seven_third.mT * prefactors_seven_thirds
368
+ + MF_eight_third.mT * prefactors_eight_thirds
369
+ + Mf.mT * prefactors_one
370
+ + Mf_two.mT * prefactors_two
371
+ + Mf_three.mT * prefactors_three
372
+ ).mT
373
+
374
+ Damp = (
375
+ (2.0 / 3.0) / Mf_one_third.mT * prefactors_two_thirds
376
+ + (4.0 / 3.0) * Mf_one_third.mT * prefactors_four_thirds
377
+ + (5.0 / 3.0) * Mf_two_third.mT * prefactors_five_thirds
378
+ + (7.0 / 3.0) * Mf_four_third.mT * prefactors_seven_thirds
379
+ + (8.0 / 3.0) * Mf_five_third.mT * prefactors_eight_thirds
380
+ + prefactors_one
381
+ + 2.0 * Mf.mT * prefactors_two
382
+ + 3.0 * Mf_two.mT * prefactors_three
383
+ ).mT
384
+
385
+ return amp, Damp
386
+
387
+ def phenom_d_phase(self, Mf, mass_1, mass_2, eta, eta2, chi1, chi2, xi):
388
+ ins_phase, ins_Dphase = self.phenom_d_inspiral_phase(
389
+ Mf, mass_1, mass_2, eta, eta2, xi, chi1, chi2
390
+ )
391
+ int_phase, int_Dphase = self.phenom_d_int_phase(Mf, eta, eta2, xi)
392
+ mrd_phase, mrd_Dphase = self.phenom_d_mrd_phase(
393
+ Mf, eta, eta2, chi1, chi2, xi
394
+ )
395
+
396
+ # merger ringdown
397
+ fRD, fDM = self.fring_fdamp(eta, eta2, chi1, chi2)
398
+ # definitions in Eq. (35) of arXiv:1508.07253
399
+ # PHI_fJoin_INS in header LALSimIMRPhenomD.h
400
+ # C1 continuity at intermediate region i.e. f_1
401
+ PHI_fJoin_INS = 0.018 * torch.ones_like(Mf)
402
+ ins_phase_f1, ins_Dphase_f1 = self.phenom_d_inspiral_phase(
403
+ PHI_fJoin_INS, mass_1, mass_2, eta, eta2, xi, chi1, chi2
404
+ )
405
+ int_phase_f1, int_Dphase_f1 = self.phenom_d_int_phase(
406
+ PHI_fJoin_INS, eta, eta2, xi
407
+ )
408
+ C2Int = ins_Dphase_f1 - int_Dphase_f1
409
+ C1Int = (
410
+ ins_phase_f1 - (int_phase_f1.mT / eta).mT - C2Int * PHI_fJoin_INS
411
+ )
412
+ # C1 continuity at ringdown
413
+ fRDJoin = (0.5 * torch.ones_like(Mf).mT * fRD).mT
414
+ int_phase_rd, int_Dphase_rd = self.phenom_d_int_phase(
415
+ fRDJoin, eta, eta2, xi
161
416
  )
162
- * xi
163
- )
164
-
165
-
166
- def gamma3_fun(eta, eta2, xi):
167
- return (
168
- 1.3081615607036106
169
- - 0.005537729694807678 * eta
170
- + (
171
- -0.06782917938621007
172
- - 0.6689834970767117 * eta
173
- + 3.403147966134083 * eta2
417
+ mrd_phase_rd, mrd_Dphase_rd = self.phenom_d_mrd_phase(
418
+ fRDJoin, eta, eta2, chi1, chi2, xi
419
+ )
420
+ PhiIntTempVal = (int_phase_rd.mT / eta).mT + C1Int + C2Int * fRDJoin
421
+ # C2MRD = int_Dphase_rd - mrd_Dphase_rd
422
+ C2MRD = C2Int + int_Dphase_rd - mrd_Dphase_rd
423
+ C1MRD = PhiIntTempVal - (mrd_phase_rd.mT / eta).mT - C2MRD * fRDJoin
424
+
425
+ int_phase = (int_phase.mT / eta).mT
426
+ int_phase += C1Int
427
+ int_phase += Mf * C2Int
428
+
429
+ mrd_phase = (mrd_phase.mT / eta).mT
430
+ mrd_phase += C1MRD
431
+ mrd_phase += Mf * C2MRD
432
+
433
+ # construct full IMR phase
434
+ theta_minus_f1 = torch.heaviside(
435
+ PHI_fJoin_INS - Mf, torch.tensor(0.0, device=Mf.device)
436
+ )
437
+ theta_plus_f1 = torch.heaviside(
438
+ Mf - PHI_fJoin_INS, torch.tensor(1.0, device=Mf.device)
439
+ )
440
+ theta_minus_f2 = torch.heaviside(
441
+ fRDJoin - Mf, torch.tensor(0.0, device=Mf.device)
442
+ )
443
+ theta_plus_f2 = torch.heaviside(
444
+ Mf - fRDJoin, torch.tensor(1.0, device=Mf.device)
445
+ )
446
+
447
+ phasing = theta_minus_f1 * ins_phase
448
+ phasing += theta_plus_f1 * int_phase * theta_minus_f2
449
+ phasing += theta_plus_f2 * mrd_phase
450
+
451
+ Dphasing = theta_minus_f1 * ins_Dphase
452
+ Dphasing += theta_plus_f1 * int_Dphase * theta_minus_f2
453
+ Dphasing += theta_plus_f2 * mrd_Dphase
454
+
455
+ return phasing, Dphasing
456
+
457
+ def phenom_d_mrd_phase(self, Mf, eta, eta2, chi1, chi2, xi):
458
+ alpha1 = self.alpha1Fit(eta, eta2, xi)
459
+ alpha2 = self.alpha2Fit(eta, eta2, xi)
460
+ alpha3 = self.alpha3Fit(eta, eta2, xi)
461
+ alpha4 = self.alpha4Fit(eta, eta2, xi)
462
+ alpha5 = self.alpha5Fit(eta, eta2, xi)
463
+
464
+ # merger ringdown
465
+ fRD, fDM = self.fring_fdamp(eta, eta2, chi1, chi2)
466
+ f_minus_alpha5_fRD = (Mf.t() - alpha5 * fRD).t()
467
+
468
+ # Leading 1/eta is not multiplied at this stage
469
+ mrd_phasing = (Mf.t() * alpha1).t()
470
+ mrd_phasing -= (1 / Mf.t() * alpha2).t()
471
+ mrd_phasing += (4.0 / 3.0) * (Mf.t() ** (3.0 / 4.0) * alpha3).t()
472
+ mrd_phasing += (torch.atan(f_minus_alpha5_fRD.t() / fDM) * alpha4).t()
473
+
474
+ mrd_Dphasing = (
475
+ alpha4 * fDM / (f_minus_alpha5_fRD.t() ** 2 + fDM**2)
476
+ ).t()
477
+ mrd_Dphasing += (Mf.t() ** (-1.0 / 4.0) * alpha3).t()
478
+ mrd_Dphasing += (Mf.t() ** (-2.0) * alpha2).t()
479
+ mrd_Dphasing = (mrd_Dphasing.t() + alpha1).t()
480
+ mrd_Dphasing = (mrd_Dphasing.t() / eta).t()
481
+
482
+ return mrd_phasing, mrd_Dphasing
483
+
484
+ def phenom_d_int_phase(self, Mf, eta, eta2, xi):
485
+ beta1 = self.beta1Fit(eta, eta2, xi)
486
+ beta2 = self.beta2Fit(eta, eta2, xi)
487
+ beta3 = self.beta3Fit(eta, eta2, xi)
488
+ # Merger phase
489
+ # Leading beta0 is not added here
490
+ # overall 1/eta is not multiplied
491
+ int_phasing = (Mf.mT * beta1).mT
492
+ int_phasing += (torch.log(Mf).mT * beta2).mT
493
+ int_phasing -= (Mf.mT ** (-3.0) / 3.0 * beta3).mT
494
+
495
+ # overall 1/eta is multiple in derivative of
496
+ # intermediate phase
497
+ int_Dphasing = (Mf.mT ** (-4.0) * beta3).mT
498
+ int_Dphasing += (Mf.mT ** (-1.0) * beta2).mT
499
+ int_Dphasing = (int_Dphasing.mT + beta1).mT
500
+ int_Dphasing = (int_Dphasing.mT / eta).mT
501
+ return int_phasing, int_Dphasing
502
+
503
+ def subtract3PNSS(self, Mf, mass1, mass2, eta, eta2, xi, chi1, chi2):
504
+ M = mass1 + mass2
505
+ eta = mass1 * mass2 / M / M
506
+ m1byM = mass1 / M
507
+ m2byM = mass2 / M
508
+ chi1sq = chi1 * chi1
509
+ chi2sq = chi2 * chi2
510
+ v1 = (PI * Mf) ** (1.0 / 3.0)
511
+ v5 = v1**5.0
512
+ v6 = v1**6.0
513
+ v7 = v1**7.0
514
+ pfaN = 3.0 / (128.0 * eta)
515
+ pn_ss3 = (
516
+ (326.75 / 1.12 + 557.5 / 1.8 * eta) * eta * chi1 * chi2
174
517
  + (
175
- -0.05296577374411866
176
- - 0.9923793203111362 * eta
177
- + 4.820681208409587 * eta2
518
+ (4703.5 / 8.4 + 2935.0 / 6.0 * m1byM - 120.0 * m1byM * m1byM)
519
+ * m1byM
520
+ * m1byM
521
+ + (
522
+ -4108.25 / 6.72
523
+ - 108.5 / 1.2 * m1byM
524
+ + 125.5 / 3.6 * m1byM * m1byM
525
+ )
526
+ * m1byM
527
+ * m1byM
178
528
  )
179
- * xi
529
+ * chi1sq
180
530
  + (
181
- -0.006134139870393713
182
- - 0.38429253308696365 * eta
183
- + 1.7561754421985984 * eta2
531
+ (4703.5 / 8.4 + 2935.0 / 6.0 * m2byM - 120.0 * m2byM * m2byM)
532
+ * m2byM
533
+ * m2byM
534
+ + (
535
+ -4108.25 / 6.72
536
+ - 108.5 / 1.2 * m2byM
537
+ + 125.5 / 3.6 * m2byM * m2byM
538
+ )
539
+ * m2byM
540
+ * m2byM
184
541
  )
185
- * xi
186
- * xi
542
+ * chi2sq
187
543
  )
188
- * xi
189
- )
190
-
191
-
192
- def beta1Fit(eta, eta2, xi):
193
- return (
194
- 97.89747327985583
195
- - 42.659730877489224 * eta
196
- + (
197
- 153.48421037904913
198
- - 1417.0620760768954 * eta
199
- + 2752.8614143665027 * eta2
200
- + (
201
- 138.7406469558649
202
- - 1433.6585075135881 * eta
203
- + 2857.7418952430758 * eta2
544
+ phase_pn_ss3 = (((v6.mT * pn_ss3).mT / v5).mT * pfaN).mT
545
+ Dphase_pn_ss3 = (
546
+ (PI * (v6.mT * pn_ss3).mT / (3.0 * v1 * v7)).mT * pfaN
547
+ ).mT
548
+ return phase_pn_ss3, Dphase_pn_ss3
549
+
550
+ def phenom_d_inspiral_phase(
551
+ self, Mf, mass_1, mass_2, eta, eta2, xi, chi1, chi2
552
+ ):
553
+ ins_phasing, ins_Dphasing = self.taylorf2_phase(
554
+ Mf, mass_1, mass_2, chi1, chi2
555
+ )
556
+ # subtract 3PN spin-spin term as this is in LAL's TaylorF2
557
+ # implementation, but was not available when PhenomD was tuned.
558
+ # refer https://git.ligo.org/lscsoft/lalsuite/-/blob/master/lalsimulation/lib/LALSimIMRPhenomD.c#L397-398 # noqa: E501
559
+ pn_ss3, Dpn_ss3 = self.subtract3PNSS(
560
+ Mf, mass_1, mass_2, eta, eta2, xi, chi1, chi2
561
+ )
562
+ ins_phasing -= pn_ss3
563
+ ins_Dphasing -= Dpn_ss3
564
+
565
+ sigma1 = self.sigma1Fit(eta, eta2, xi)
566
+ sigma2 = self.sigma2Fit(eta, eta2, xi)
567
+ sigma3 = self.sigma3Fit(eta, eta2, xi)
568
+ sigma4 = self.sigma4Fit(eta, eta2, xi)
569
+
570
+ ins_phasing += (Mf.mT * sigma1 / eta).mT
571
+ ins_phasing += (Mf.mT ** (4.0 / 3.0) * 0.75 * sigma2 / eta).mT
572
+ ins_phasing += (Mf.mT ** (5.0 / 3.0) * 0.6 * sigma3 / eta).mT
573
+ ins_phasing += (Mf.mT**2.0 * 0.5 * sigma4 / eta).mT
574
+
575
+ ins_Dphasing = (ins_Dphasing.mT + sigma1 / eta).mT
576
+ ins_Dphasing += (Mf.mT ** (1.0 / 3.0) * sigma2 / eta).mT
577
+ ins_Dphasing += (Mf.mT ** (2.0 / 3.0) * sigma3 / eta).mT
578
+ ins_Dphasing += (Mf.mT * sigma4 / eta).mT
579
+
580
+ return ins_phasing, ins_Dphasing
581
+
582
+ def fring_fdamp(self, eta, eta2, chi1, chi2):
583
+ finspin = self.FinalSpin0815(eta, eta2, chi1, chi2)
584
+ Erad = self.PhenomInternal_EradRational0815(eta, eta2, chi1, chi2)
585
+
586
+ fRD, fDM = self._linear_interp_finspin(finspin)
587
+ fRD /= 1.0 - Erad
588
+ fDM /= 1.0 - Erad
589
+
590
+ return fRD, fDM
591
+
592
+ def fmaxCalc(self, fRD, fDM, gamma2, gamma3):
593
+ res = torch.zeros_like(gamma2)
594
+ res = torch.abs(fRD + (-fDM * gamma3) / gamma2) * (gamma2 > 1).to(
595
+ torch.int
596
+ ) + torch.abs(
597
+ fRD
598
+ + (fDM * (-1 + torch.sqrt(1 - gamma2 * gamma2)) * gamma3) / gamma2
599
+ ) * (
600
+ gamma2 <= 1
601
+ ).to(
602
+ torch.int
603
+ )
604
+ return res
605
+
606
+ def _linear_interp_finspin(self, finspin):
607
+ # chi is a batch of final spins i.e. torch.Size([n])
608
+ right_spin_idx = torch.bucketize(finspin, self.qnmdata_a)
609
+ right_spin_val = self.qnmdata_a[right_spin_idx]
610
+ # QNMData_a is sorted, hence take the previous index
611
+ left_spin_idx = right_spin_idx - 1
612
+ left_spin_val = self.qnmdata_a[left_spin_idx]
613
+
614
+ if not torch.all(left_spin_val < right_spin_val):
615
+ raise RuntimeError(
616
+ "Left value in grid should be greater than right. "
617
+ "Maybe be caused for extremal spin values."
204
618
  )
205
- * xi
619
+ left_fring = self.qnmdata_fring[left_spin_idx]
620
+ right_fring = self.qnmdata_fring[right_spin_idx]
621
+ slope_fring = right_fring - left_fring
622
+ slope_fring /= right_spin_val - left_spin_val
623
+
624
+ left_fdamp = self.qnmdata_fdamp[left_spin_idx]
625
+ right_fdamp = self.qnmdata_fdamp[right_spin_idx]
626
+ slope_fdamp = right_fdamp - left_fdamp
627
+ slope_fdamp /= right_spin_val - left_spin_val
628
+
629
+ return (
630
+ slope_fring * (finspin - left_spin_val) + left_fring,
631
+ slope_fdamp * (finspin - left_spin_val) + left_fdamp,
632
+ )
633
+
634
+ # Utility functions taken from PhenomD utilities in lalsimulation
635
+ # https://git.ligo.org/lscsoft/lalsuite/-/blob/master/lalsimulation/lib/LALSimIMRPhenomD_internals.c
636
+ def sigma1Fit(self, eta, eta2, xi):
637
+ return (
638
+ 2096.551999295543
639
+ + 1463.7493168261553 * eta
206
640
  + (
207
- 41.025109467376126
208
- - 423.680737974639 * eta
209
- + 850.3594335657173 * eta2
641
+ 1312.5493286098522
642
+ + 18307.330017082117 * eta
643
+ - 43534.1440746107 * eta2
644
+ + (
645
+ -833.2889543511114
646
+ + 32047.31997183187 * eta
647
+ - 108609.45037520859 * eta2
648
+ )
649
+ * xi
650
+ + (
651
+ 452.25136398112204
652
+ + 8353.439546391714 * eta
653
+ - 44531.3250037322 * eta2
654
+ )
655
+ * xi
656
+ * xi
210
657
  )
211
658
  * xi
212
- * xi
213
659
  )
214
- * xi
215
- )
216
-
217
-
218
- def beta2Fit(eta, eta2, xi):
219
- return (
220
- -3.282701958759534
221
- - 9.051384468245866 * eta
222
- + (
223
- -12.415449742258042
224
- + 55.4716447709787 * eta
225
- - 106.05109938966335 * eta2
660
+
661
+ def sigma2Fit(self, eta, eta2, xi):
662
+ return (
663
+ -10114.056472621156
664
+ - 44631.01109458185 * eta
226
665
  + (
227
- -11.953044553690658
228
- + 76.80704618365418 * eta
229
- - 155.33172948098394 * eta2
666
+ -6541.308761668722
667
+ - 266959.23419307504 * eta
668
+ + 686328.3229317984 * eta2
669
+ + (
670
+ 3405.6372187679685
671
+ - 437507.7208209015 * eta
672
+ + 1.6318171307344697e6 * eta2
673
+ )
674
+ * xi
675
+ + (
676
+ -7462.648563007646
677
+ - 114585.25177153319 * eta
678
+ + 674402.4689098676 * eta2
679
+ )
680
+ * xi
681
+ * xi
230
682
  )
231
683
  * xi
684
+ )
685
+
686
+ def sigma3Fit(self, eta, eta2, xi):
687
+ return (
688
+ 22933.658273436497
689
+ + 230960.00814979506 * eta
232
690
  + (
233
- -3.4129261592393263
234
- + 25.572377569952536 * eta
235
- - 54.408036707740465 * eta2
691
+ 14961.083974183695
692
+ + 1.1940181342318142e6 * eta
693
+ - 3.1042239693052764e6 * eta2
694
+ + (
695
+ -3038.166617199259
696
+ + 1.8720322849093592e6 * eta
697
+ - 7.309145012085539e6 * eta2
698
+ )
699
+ * xi
700
+ + (
701
+ 42738.22871475411
702
+ + 467502.018616601 * eta
703
+ - 3.064853498512499e6 * eta2
704
+ )
705
+ * xi
706
+ * xi
236
707
  )
237
708
  * xi
238
- * xi
239
709
  )
240
- * xi
241
- )
242
-
243
-
244
- def beta3Fit(eta, eta2, xi):
245
- return (
246
- -0.000025156429818799565
247
- + 0.000019750256942201327 * eta
248
- + (
249
- -0.000018370671469295915
250
- + 0.000021886317041311973 * eta
251
- + 0.00008250240316860033 * eta2
710
+
711
+ def sigma4Fit(self, eta, eta2, xi):
712
+ return (
713
+ -14621.71522218357
714
+ - 377812.8579387104 * eta
252
715
  + (
253
- 7.157371250566708e-6
254
- - 0.000055780000112270685 * eta
255
- + 0.00019142082884072178 * eta2
716
+ -9608.682631509726
717
+ - 1.7108925257214056e6 * eta
718
+ + 4.332924601416521e6 * eta2
719
+ + (
720
+ -22366.683262266528
721
+ - 2.5019716386377467e6 * eta
722
+ + 1.0274495902259542e7 * eta2
723
+ )
724
+ * xi
725
+ + (
726
+ -85360.30079034246
727
+ - 570025.3441737515 * eta
728
+ + 4.396844346849777e6 * eta2
729
+ )
730
+ * xi
731
+ * xi
256
732
  )
257
733
  * xi
734
+ )
735
+
736
+ def gamma1_fun(self, eta, eta2, xi):
737
+ return (
738
+ 0.006927402739328343
739
+ + 0.03020474290328911 * eta
258
740
  + (
259
- 5.447166261464217e-6
260
- - 0.00003220610095021982 * eta
261
- + 0.00007974016714984341 * eta2
741
+ 0.006308024337706171
742
+ - 0.12074130661131138 * eta
743
+ + 0.26271598905781324 * eta2
744
+ + (
745
+ 0.0034151773647198794
746
+ - 0.10779338611188374 * eta
747
+ + 0.27098966966891747 * eta2
748
+ )
749
+ * xi
750
+ + (
751
+ 0.0007374185938559283
752
+ - 0.02749621038376281 * eta
753
+ + 0.0733150789135702 * eta2
754
+ )
755
+ * xi
756
+ * xi
262
757
  )
263
758
  * xi
264
- * xi
265
759
  )
266
- * xi
267
- )
268
-
269
-
270
- def alpha1Fit(eta, eta2, xi):
271
- return (
272
- 43.31514709695348
273
- + 638.6332679188081 * eta
274
- + (
275
- -32.85768747216059
276
- + 2415.8938269370315 * eta
277
- - 5766.875169379177 * eta2
760
+
761
+ def gamma2_fun(self, eta, eta2, xi):
762
+ return (
763
+ 1.010344404799477
764
+ + 0.0008993122007234548 * eta
278
765
  + (
279
- -61.85459307173841
280
- + 2953.967762459948 * eta
281
- - 8986.29057591497 * eta2
766
+ 0.283949116804459
767
+ - 4.049752962958005 * eta
768
+ + 13.207828172665366 * eta2
769
+ + (
770
+ 0.10396278486805426
771
+ - 7.025059158961947 * eta
772
+ + 24.784892370130475 * eta2
773
+ )
774
+ * xi
775
+ + (
776
+ 0.03093202475605892
777
+ - 2.6924023896851663 * eta
778
+ + 9.609374464684983 * eta2
779
+ )
780
+ * xi
781
+ * xi
282
782
  )
283
783
  * xi
784
+ )
785
+
786
+ def gamma3_fun(self, eta, eta2, xi):
787
+ return (
788
+ 1.3081615607036106
789
+ - 0.005537729694807678 * eta
284
790
  + (
285
- -21.571435779762044
286
- + 981.2158224673428 * eta
287
- - 3239.5664895930286 * eta2
791
+ -0.06782917938621007
792
+ - 0.6689834970767117 * eta
793
+ + 3.403147966134083 * eta2
794
+ + (
795
+ -0.05296577374411866
796
+ - 0.9923793203111362 * eta
797
+ + 4.820681208409587 * eta2
798
+ )
799
+ * xi
800
+ + (
801
+ -0.006134139870393713
802
+ - 0.38429253308696365 * eta
803
+ + 1.7561754421985984 * eta2
804
+ )
805
+ * xi
806
+ * xi
288
807
  )
289
808
  * xi
290
- * xi
291
809
  )
292
- * xi
293
- )
294
-
295
-
296
- def alpha2Fit(eta, eta2, xi):
297
- return (
298
- -0.07020209449091723
299
- - 0.16269798450687084 * eta
300
- + (
301
- -0.1872514685185499
302
- + 1.138313650449945 * eta
303
- - 2.8334196304430046 * eta2
810
+
811
+ def beta1Fit(self, eta, eta2, xi):
812
+ return (
813
+ 97.89747327985583
814
+ - 42.659730877489224 * eta
304
815
  + (
305
- -0.17137955686840617
306
- + 1.7197549338119527 * eta
307
- - 4.539717148261272 * eta2
816
+ 153.48421037904913
817
+ - 1417.0620760768954 * eta
818
+ + 2752.8614143665027 * eta2
819
+ + (
820
+ 138.7406469558649
821
+ - 1433.6585075135881 * eta
822
+ + 2857.7418952430758 * eta2
823
+ )
824
+ * xi
825
+ + (
826
+ 41.025109467376126
827
+ - 423.680737974639 * eta
828
+ + 850.3594335657173 * eta2
829
+ )
830
+ * xi
831
+ * xi
308
832
  )
309
833
  * xi
834
+ )
835
+
836
+ def beta2Fit(self, eta, eta2, xi):
837
+ return (
838
+ -3.282701958759534
839
+ - 9.051384468245866 * eta
310
840
  + (
311
- -0.049983437357548705
312
- + 0.6062072055948309 * eta
313
- - 1.682769616644546 * eta2
841
+ -12.415449742258042
842
+ + 55.4716447709787 * eta
843
+ - 106.05109938966335 * eta2
844
+ + (
845
+ -11.953044553690658
846
+ + 76.80704618365418 * eta
847
+ - 155.33172948098394 * eta2
848
+ )
849
+ * xi
850
+ + (
851
+ -3.4129261592393263
852
+ + 25.572377569952536 * eta
853
+ - 54.408036707740465 * eta2
854
+ )
855
+ * xi
856
+ * xi
314
857
  )
315
858
  * xi
316
- * xi
317
859
  )
318
- * xi
319
- )
320
-
321
-
322
- def alpha3Fit(eta, eta2, xi):
323
- return (
324
- 9.5988072383479
325
- - 397.05438595557433 * eta
326
- + (
327
- 16.202126189517813
328
- - 1574.8286986717037 * eta
329
- + 3600.3410843831093 * eta2
860
+
861
+ def beta3Fit(self, eta, eta2, xi):
862
+ return (
863
+ -0.000025156429818799565
864
+ + 0.000019750256942201327 * eta
330
865
  + (
331
- 27.092429659075467
332
- - 1786.482357315139 * eta
333
- + 5152.919378666511 * eta2
866
+ -0.000018370671469295915
867
+ + 0.000021886317041311973 * eta
868
+ + 0.00008250240316860033 * eta2
869
+ + (
870
+ 7.157371250566708e-6
871
+ - 0.000055780000112270685 * eta
872
+ + 0.00019142082884072178 * eta2
873
+ )
874
+ * xi
875
+ + (
876
+ 5.447166261464217e-6
877
+ - 0.00003220610095021982 * eta
878
+ + 0.00007974016714984341 * eta2
879
+ )
880
+ * xi
881
+ * xi
334
882
  )
335
883
  * xi
884
+ )
885
+
886
+ def alpha1Fit(self, eta, eta2, xi):
887
+ return (
888
+ 43.31514709695348
889
+ + 638.6332679188081 * eta
336
890
  + (
337
- 11.175710130033895
338
- - 577.7999423177481 * eta
339
- + 1808.730762932043 * eta2
891
+ -32.85768747216059
892
+ + 2415.8938269370315 * eta
893
+ - 5766.875169379177 * eta2
894
+ + (
895
+ -61.85459307173841
896
+ + 2953.967762459948 * eta
897
+ - 8986.29057591497 * eta2
898
+ )
899
+ * xi
900
+ + (
901
+ -21.571435779762044
902
+ + 981.2158224673428 * eta
903
+ - 3239.5664895930286 * eta2
904
+ )
905
+ * xi
906
+ * xi
340
907
  )
341
908
  * xi
342
- * xi
343
909
  )
344
- * xi
345
- )
346
-
347
-
348
- def alpha4Fit(eta, eta2, xi):
349
- return (
350
- -0.02989487384493607
351
- + 1.4022106448583738 * eta
352
- + (
353
- -0.07356049468633846
354
- + 0.8337006542278661 * eta
355
- + 0.2240008282397391 * eta2
910
+
911
+ def alpha2Fit(self, eta, eta2, xi):
912
+ return (
913
+ -0.07020209449091723
914
+ - 0.16269798450687084 * eta
356
915
  + (
357
- -0.055202870001177226
358
- + 0.5667186343606578 * eta
359
- + 0.7186931973380503 * eta2
916
+ -0.1872514685185499
917
+ + 1.138313650449945 * eta
918
+ - 2.8334196304430046 * eta2
919
+ + (
920
+ -0.17137955686840617
921
+ + 1.7197549338119527 * eta
922
+ - 4.539717148261272 * eta2
923
+ )
924
+ * xi
925
+ + (
926
+ -0.049983437357548705
927
+ + 0.6062072055948309 * eta
928
+ - 1.682769616644546 * eta2
929
+ )
930
+ * xi
931
+ * xi
360
932
  )
361
933
  * xi
934
+ )
935
+
936
+ def alpha3Fit(self, eta, eta2, xi):
937
+ return (
938
+ 9.5988072383479
939
+ - 397.05438595557433 * eta
362
940
  + (
363
- -0.015507437354325743
364
- + 0.15750322779277187 * eta
365
- + 0.21076815715176228 * eta2
941
+ 16.202126189517813
942
+ - 1574.8286986717037 * eta
943
+ + 3600.3410843831093 * eta2
944
+ + (
945
+ 27.092429659075467
946
+ - 1786.482357315139 * eta
947
+ + 5152.919378666511 * eta2
948
+ )
949
+ * xi
950
+ + (
951
+ 11.175710130033895
952
+ - 577.7999423177481 * eta
953
+ + 1808.730762932043 * eta2
954
+ )
955
+ * xi
956
+ * xi
366
957
  )
367
958
  * xi
368
- * xi
369
959
  )
370
- * xi
371
- )
372
-
373
-
374
- def alpha5Fit(eta, eta2, xi):
375
- return (
376
- 0.9974408278363099
377
- - 0.007884449714907203 * eta
378
- + (
379
- -0.059046901195591035
380
- + 1.3958712396764088 * eta
381
- - 4.516631601676276 * eta2
960
+
961
+ def alpha4Fit(self, eta, eta2, xi):
962
+ return (
963
+ -0.02989487384493607
964
+ + 1.4022106448583738 * eta
382
965
  + (
383
- -0.05585343136869692
384
- + 1.7516580039343603 * eta
385
- - 5.990208965347804 * eta2
966
+ -0.07356049468633846
967
+ + 0.8337006542278661 * eta
968
+ + 0.2240008282397391 * eta2
969
+ + (
970
+ -0.055202870001177226
971
+ + 0.5667186343606578 * eta
972
+ + 0.7186931973380503 * eta2
973
+ )
974
+ * xi
975
+ + (
976
+ -0.015507437354325743
977
+ + 0.15750322779277187 * eta
978
+ + 0.21076815715176228 * eta2
979
+ )
980
+ * xi
981
+ * xi
386
982
  )
387
983
  * xi
984
+ )
985
+
986
+ def alpha5Fit(self, eta, eta2, xi):
987
+ return (
988
+ 0.9974408278363099
989
+ - 0.007884449714907203 * eta
388
990
  + (
389
- -0.017945336522161195
390
- + 0.5965097794825992 * eta
391
- - 2.0608879367971804 * eta2
991
+ -0.059046901195591035
992
+ + 1.3958712396764088 * eta
993
+ - 4.516631601676276 * eta2
994
+ + (
995
+ -0.05585343136869692
996
+ + 1.7516580039343603 * eta
997
+ - 5.990208965347804 * eta2
998
+ )
999
+ * xi
1000
+ + (
1001
+ -0.017945336522161195
1002
+ + 0.5965097794825992 * eta
1003
+ - 2.0608879367971804 * eta2
1004
+ )
1005
+ * xi
1006
+ * xi
392
1007
  )
393
1008
  * xi
394
- * xi
395
1009
  )
396
- * xi
397
- )
398
-
399
-
400
- def rho1_fun(eta, eta2, xi):
401
- return (
402
- 3931.8979897196696
403
- - 17395.758706812805 * eta
404
- + (
405
- 3132.375545898835
406
- + 343965.86092361377 * eta
407
- - 1.2162565819981997e6 * eta2
1010
+
1011
+ def rho1_fun(self, eta, eta2, xi):
1012
+ return (
1013
+ 3931.8979897196696
1014
+ - 17395.758706812805 * eta
408
1015
  + (
409
- -70698.00600428853
410
- + 1.383907177859705e6 * eta
411
- - 3.9662761890979446e6 * eta2
1016
+ 3132.375545898835
1017
+ + 343965.86092361377 * eta
1018
+ - 1.2162565819981997e6 * eta2
1019
+ + (
1020
+ -70698.00600428853
1021
+ + 1.383907177859705e6 * eta
1022
+ - 3.9662761890979446e6 * eta2
1023
+ )
1024
+ * xi
1025
+ + (
1026
+ -60017.52423652596
1027
+ + 803515.1181825735 * eta
1028
+ - 2.091710365941658e6 * eta2
1029
+ )
1030
+ * xi
1031
+ * xi
412
1032
  )
413
1033
  * xi
1034
+ )
1035
+
1036
+ def rho2_fun(self, eta, eta2, xi):
1037
+ return (
1038
+ -40105.47653771657
1039
+ + 112253.0169706701 * eta
414
1040
  + (
415
- -60017.52423652596
416
- + 803515.1181825735 * eta
417
- - 2.091710365941658e6 * eta2
1041
+ 23561.696065836168
1042
+ - 3.476180699403351e6 * eta
1043
+ + 1.137593670849482e7 * eta2
1044
+ + (
1045
+ 754313.1127166454
1046
+ - 1.308476044625268e7 * eta
1047
+ + 3.6444584853928134e7 * eta2
1048
+ )
1049
+ * xi
1050
+ + (
1051
+ 596226.612472288
1052
+ - 7.4277901143564405e6 * eta
1053
+ + 1.8928977514040343e7 * eta2
1054
+ )
1055
+ * xi
1056
+ * xi
418
1057
  )
419
1058
  * xi
420
- * xi
421
1059
  )
422
- * xi
423
- )
424
-
425
-
426
- def rho2_fun(eta, eta2, xi):
427
- return (
428
- -40105.47653771657
429
- + 112253.0169706701 * eta
430
- + (
431
- 23561.696065836168
432
- - 3.476180699403351e6 * eta
433
- + 1.137593670849482e7 * eta2
1060
+
1061
+ def rho3_fun(self, eta, eta2, xi):
1062
+ return (
1063
+ 83208.35471266537
1064
+ - 191237.7264145924 * eta
434
1065
  + (
435
- 754313.1127166454
436
- - 1.308476044625268e7 * eta
437
- + 3.6444584853928134e7 * eta2
1066
+ -210916.2454782992
1067
+ + 8.71797508352568e6 * eta
1068
+ - 2.6914942420669552e7 * eta2
1069
+ + (
1070
+ -1.9889806527362722e6
1071
+ + 3.0888029960154563e7 * eta
1072
+ - 8.390870279256162e7 * eta2
1073
+ )
1074
+ * xi
1075
+ + (
1076
+ -1.4535031953446497e6
1077
+ + 1.7063528990822166e7 * eta
1078
+ - 4.2748659731120914e7 * eta2
1079
+ )
1080
+ * xi
1081
+ * xi
438
1082
  )
439
1083
  * xi
1084
+ )
1085
+
1086
+ def FinalSpin0815(self, eta, eta2, chi1, chi2):
1087
+ Seta = torch.sqrt(1.0 - 4.0 * eta)
1088
+ Seta = torch.nan_to_num(Seta) # avoid nan around eta = 0.25
1089
+ m1 = 0.5 * (1.0 + Seta)
1090
+ m2 = 0.5 * (1.0 - Seta)
1091
+ m1s = m1 * m1
1092
+ m2s = m2 * m2
1093
+ s = m1s * chi1 + m2s * chi2
1094
+ eta3 = eta2 * eta
1095
+ s2 = s * s
1096
+ s3 = s2 * s
1097
+ return eta * (
1098
+ 3.4641016151377544
1099
+ - 4.399247300629289 * eta
1100
+ + 9.397292189321194 * eta2
1101
+ - 13.180949901606242 * eta3
440
1102
  + (
441
- 596226.612472288
442
- - 7.4277901143564405e6 * eta
443
- + 1.8928977514040343e7 * eta2
1103
+ (1.0 / eta - 0.0850917821418767 - 5.837029316602263 * eta)
1104
+ + (0.1014665242971878 - 2.0967746996832157 * eta) * s
1105
+ + (-1.3546806617824356 + 4.108962025369336 * eta) * s2
1106
+ + (-0.8676969352555539 + 2.064046835273906 * eta) * s3
444
1107
  )
445
- * xi
446
- * xi
1108
+ * s
447
1109
  )
448
- * xi
449
- )
450
-
451
-
452
- def rho3_fun(eta, eta2, xi):
453
- return (
454
- 83208.35471266537
455
- - 191237.7264145924 * eta
456
- + (
457
- -210916.2454782992
458
- + 8.71797508352568e6 * eta
459
- - 2.6914942420669552e7 * eta2
460
- + (
461
- -1.9889806527362722e6
462
- + 3.0888029960154563e7 * eta
463
- - 8.390870279256162e7 * eta2
1110
+
1111
+ def PhenomInternal_EradRational0815(self, eta, eta2, chi1, chi2):
1112
+ Seta = torch.sqrt(1.0 - 4.0 * eta)
1113
+ m1 = 0.5 * (1.0 + Seta)
1114
+ m2 = 0.5 * (1.0 - Seta)
1115
+ m1s = m1 * m1
1116
+ m2s = m2 * m2
1117
+ s = (m1s * chi1 + m2s * chi2) / (m1s + m2s)
1118
+
1119
+ eta3 = eta2 * eta
1120
+
1121
+ return (
1122
+ eta
1123
+ * (
1124
+ 0.055974469826360077
1125
+ + 0.5809510763115132 * eta
1126
+ - 0.9606726679372312 * eta2
1127
+ + 3.352411249771192 * eta3
464
1128
  )
465
- * xi
466
- + (
467
- -1.4535031953446497e6
468
- + 1.7063528990822166e7 * eta
469
- - 4.2748659731120914e7 * eta2
1129
+ * (
1130
+ 1.0
1131
+ + (
1132
+ -0.0030302335878845507
1133
+ - 2.0066110851351073 * eta
1134
+ + 7.7050567802399215 * eta2
1135
+ )
1136
+ * s
470
1137
  )
471
- * xi
472
- * xi
473
- )
474
- * xi
475
- )
476
-
477
-
478
- def FinalSpin0815(eta, eta2, chi1, chi2):
479
- Seta = torch.sqrt(1.0 - 4.0 * eta)
480
- Seta = torch.nan_to_num(Seta) # avoid nan around eta = 0.25
481
- m1 = 0.5 * (1.0 + Seta)
482
- m2 = 0.5 * (1.0 - Seta)
483
- m1s = m1 * m1
484
- m2s = m2 * m2
485
- s = m1s * chi1 + m2s * chi2
486
- eta3 = eta2 * eta
487
- s2 = s * s
488
- s3 = s2 * s
489
- return eta * (
490
- 3.4641016151377544
491
- - 4.399247300629289 * eta
492
- + 9.397292189321194 * eta2
493
- - 13.180949901606242 * eta3
494
- + (
495
- (1.0 / eta - 0.0850917821418767 - 5.837029316602263 * eta)
496
- + (0.1014665242971878 - 2.0967746996832157 * eta) * s
497
- + (-1.3546806617824356 + 4.108962025369336 * eta) * s2
498
- + (-0.8676969352555539 + 2.064046835273906 * eta) * s3
499
- )
500
- * s
501
- )
502
-
503
-
504
- def PhenomInternal_EradRational0815(eta, eta2, chi1, chi2):
505
- Seta = torch.sqrt(1.0 - 4.0 * eta)
506
- m1 = 0.5 * (1.0 + Seta)
507
- m2 = 0.5 * (1.0 - Seta)
508
- m1s = m1 * m1
509
- m2s = m2 * m2
510
- s = (m1s * chi1 + m2s * chi2) / (m1s + m2s)
511
-
512
- eta3 = eta2 * eta
513
-
514
- return (
515
- eta
516
- * (
517
- 0.055974469826360077
518
- + 0.5809510763115132 * eta
519
- - 0.9606726679372312 * eta2
520
- + 3.352411249771192 * eta3
521
- )
522
- * (
1138
+ ) / (
523
1139
  1.0
524
1140
  + (
525
- -0.0030302335878845507
526
- - 2.0066110851351073 * eta
527
- + 7.7050567802399215 * eta2
1141
+ -0.6714403054720589
1142
+ - 1.4756929437702908 * eta
1143
+ + 7.304676214885011 * eta2
528
1144
  )
529
1145
  * s
530
1146
  )
531
- ) / (
532
- 1.0
533
- + (
534
- -0.6714403054720589
535
- - 1.4756929437702908 * eta
536
- + 7.304676214885011 * eta2
537
- )
538
- * s
539
- )
540
-
541
-
542
- def AmpIntColFitCoeff(eta, eta2, xi):
543
- return (
544
- 0.8149838730507785
545
- + 2.5747553517454658 * eta
546
- + (
547
- 1.1610198035496786
548
- - 2.3627771785551537 * eta
549
- + 6.771038707057573 * eta2
550
- + (
551
- 0.7570782938606834
552
- - 2.7256896890432474 * eta
553
- + 7.1140380397149965 * eta2
554
- )
555
- * xi
1147
+
1148
+ def AmpIntColFitCoeff(self, eta, eta2, xi):
1149
+ return (
1150
+ 0.8149838730507785
1151
+ + 2.5747553517454658 * eta
556
1152
  + (
557
- 0.1766934149293479
558
- - 0.7978690983168183 * eta
559
- + 2.1162391502005153 * eta2
1153
+ 1.1610198035496786
1154
+ - 2.3627771785551537 * eta
1155
+ + 6.771038707057573 * eta2
1156
+ + (
1157
+ 0.7570782938606834
1158
+ - 2.7256896890432474 * eta
1159
+ + 7.1140380397149965 * eta2
1160
+ )
1161
+ * xi
1162
+ + (
1163
+ 0.1766934149293479
1164
+ - 0.7978690983168183 * eta
1165
+ + 2.1162391502005153 * eta2
1166
+ )
1167
+ * xi
1168
+ * xi
560
1169
  )
561
1170
  * xi
562
- * xi
563
- )
564
- * xi
565
- )
566
-
567
-
568
- def delta_values(f1, f2, f3, v1, v2, v3, d1, d2):
569
- f12 = f1 * f1
570
- f13 = f1 * f12
571
- f14 = f1 * f13
572
- f15 = f1 * f14
573
- f22 = f2 * f2
574
- f23 = f2 * f22
575
- f24 = f2 * f23
576
- f32 = f3 * f3
577
- f33 = f3 * f32
578
- f34 = f3 * f33
579
- f35 = f3 * f34
580
- delta_0 = -(
581
- (
582
- d2 * f15 * f22 * f3
583
- - 2 * d2 * f14 * f23 * f3
584
- + d2 * f13 * f24 * f3
585
- - d2 * f15 * f2 * f32
586
- + d2 * f14 * f22 * f32
587
- - d1 * f13 * f23 * f32
588
- + d2 * f13 * f23 * f32
589
- + d1 * f12 * f24 * f32
590
- - d2 * f12 * f24 * f32
591
- + d2 * f14 * f2 * f33
592
- + 2 * d1 * f13 * f22 * f33
593
- - 2 * d2 * f13 * f22 * f33
594
- - d1 * f12 * f23 * f33
595
- + d2 * f12 * f23 * f33
596
- - d1 * f1 * f24 * f33
597
- - d1 * f13 * f2 * f34
598
- - d1 * f12 * f22 * f34
599
- + 2 * d1 * f1 * f23 * f34
600
- + d1 * f12 * f2 * f35
601
- - d1 * f1 * f22 * f35
602
- + 4 * f12 * f23 * f32 * v1
603
- - 3 * f1 * f24 * f32 * v1
604
- - 8 * f12 * f22 * f33 * v1
605
- + 4 * f1 * f23 * f33 * v1
606
- + f24 * f33 * v1
607
- + 4 * f12 * f2 * f34 * v1
608
- + f1 * f22 * f34 * v1
609
- - 2 * f23 * f34 * v1
610
- - 2 * f1 * f2 * f35 * v1
611
- + f22 * f35 * v1
612
- - f15 * f32 * v2
613
- + 3 * f14 * f33 * v2
614
- - 3 * f13 * f34 * v2
615
- + f12 * f35 * v2
616
- - f15 * f22 * v3
617
- + 2 * f14 * f23 * v3
618
- - f13 * f24 * v3
619
- + 2 * f15 * f2 * f3 * v3
620
- - f14 * f22 * f3 * v3
621
- - 4 * f13 * f23 * f3 * v3
622
- + 3 * f12 * f24 * f3 * v3
623
- - 4 * f14 * f2 * f32 * v3
624
- + 8 * f13 * f22 * f32 * v3
625
- - 4 * f12 * f23 * f32 * v3
626
- )
627
- / ((f1 - f2) ** 2 * (f1 - f3) ** 3 * (f3 - f2) ** 2)
628
- )
629
-
630
- delta_1 = -(
631
- (
632
- -(d2 * f15 * f22)
633
- + 2 * d2 * f14 * f23
634
- - d2 * f13 * f24
635
- - d2 * f14 * f22 * f3
636
- + 2 * d1 * f13 * f23 * f3
637
- + 2 * d2 * f13 * f23 * f3
638
- - 2 * d1 * f12 * f24 * f3
639
- - d2 * f12 * f24 * f3
640
- + d2 * f15 * f32
641
- - 3 * d1 * f13 * f22 * f32
642
- - d2 * f13 * f22 * f32
643
- + 2 * d1 * f12 * f23 * f32
644
- - 2 * d2 * f12 * f23 * f32
645
- + d1 * f1 * f24 * f32
646
- + 2 * d2 * f1 * f24 * f32
647
- - d2 * f14 * f33
648
- + d1 * f12 * f22 * f33
649
- + 3 * d2 * f12 * f22 * f33
650
- - 2 * d1 * f1 * f23 * f33
651
- - 2 * d2 * f1 * f23 * f33
652
- + d1 * f24 * f33
653
- + d1 * f13 * f34
654
- + d1 * f1 * f22 * f34
655
- - 2 * d1 * f23 * f34
656
- - d1 * f12 * f35
657
- + d1 * f22 * f35
658
- - 8 * f12 * f23 * f3 * v1
659
- + 6 * f1 * f24 * f3 * v1
660
- + 12 * f12 * f22 * f32 * v1
661
- - 8 * f1 * f23 * f32 * v1
662
- - 4 * f12 * f34 * v1
663
- + 2 * f1 * f35 * v1
664
- + 2 * f15 * f3 * v2
665
- - 4 * f14 * f32 * v2
666
- + 4 * f12 * f34 * v2
667
- - 2 * f1 * f35 * v2
668
- - 2 * f15 * f3 * v3
669
- + 8 * f12 * f23 * f3 * v3
670
- - 6 * f1 * f24 * f3 * v3
671
- + 4 * f14 * f32 * v3
672
- - 12 * f12 * f22 * f32 * v3
673
- + 8 * f1 * f23 * f32 * v3
674
- )
675
- / ((f1 - f2) ** 2 * (f1 - f3) ** 3 * (-f2 + f3) ** 2)
676
- )
677
-
678
- delta_2 = -(
679
- (
680
- d2 * f15 * f2
681
- - d1 * f13 * f23
682
- - 3 * d2 * f13 * f23
683
- + d1 * f12 * f24
684
- + 2 * d2 * f12 * f24
685
- - d2 * f15 * f3
686
- + d2 * f14 * f2 * f3
687
- - d1 * f12 * f23 * f3
688
- + d2 * f12 * f23 * f3
689
- + d1 * f1 * f24 * f3
690
- - d2 * f1 * f24 * f3
691
- - d2 * f14 * f32
692
- + 3 * d1 * f13 * f2 * f32
693
- + d2 * f13 * f2 * f32
694
- - d1 * f1 * f23 * f32
695
- + d2 * f1 * f23 * f32
696
- - 2 * d1 * f24 * f32
697
- - d2 * f24 * f32
698
- - 2 * d1 * f13 * f33
699
- + 2 * d2 * f13 * f33
700
- - d1 * f12 * f2 * f33
701
- - 3 * d2 * f12 * f2 * f33
702
- + 3 * d1 * f23 * f33
703
- + d2 * f23 * f33
704
- + d1 * f12 * f34
705
- - d1 * f1 * f2 * f34
706
- + d1 * f1 * f35
707
- - d1 * f2 * f35
708
- + 4 * f12 * f23 * v1
709
- - 3 * f1 * f24 * v1
710
- + 4 * f1 * f23 * f3 * v1
711
- - 3 * f24 * f3 * v1
712
- - 12 * f12 * f2 * f32 * v1
713
- + 4 * f23 * f32 * v1
714
- + 8 * f12 * f33 * v1
715
- - f1 * f34 * v1
716
- - f35 * v1
717
- - f15 * v2
718
- - f14 * f3 * v2
719
- + 8 * f13 * f32 * v2
720
- - 8 * f12 * f33 * v2
721
- + f1 * f34 * v2
722
- + f35 * v2
723
- + f15 * v3
724
- - 4 * f12 * f23 * v3
725
- + 3 * f1 * f24 * v3
726
- + f14 * f3 * v3
727
- - 4 * f1 * f23 * f3 * v3
728
- + 3 * f24 * f3 * v3
729
- - 8 * f13 * f32 * v3
730
- + 12 * f12 * f2 * f32 * v3
731
- - 4 * f23 * f32 * v3
732
1171
  )
733
- / ((f1 - f2) ** 2 * (f1 - f3) ** 3 * (-f2 + f3) ** 2)
734
- )
735
-
736
- delta_3 = -(
737
- (
738
- -2 * d2 * f14 * f2
739
- + d1 * f13 * f22
740
- + 3 * d2 * f13 * f22
741
- - d1 * f1 * f24
742
- - d2 * f1 * f24
743
- + 2 * d2 * f14 * f3
744
- - 2 * d1 * f13 * f2 * f3
745
- - 2 * d2 * f13 * f2 * f3
746
- + d1 * f12 * f22 * f3
747
- - d2 * f12 * f22 * f3
748
- + d1 * f24 * f3
749
- + d2 * f24 * f3
750
- + d1 * f13 * f32
751
- - d2 * f13 * f32
752
- - 2 * d1 * f12 * f2 * f32
753
- + 2 * d2 * f12 * f2 * f32
754
- + d1 * f1 * f22 * f32
755
- - d2 * f1 * f22 * f32
756
- + d1 * f12 * f33
757
- - d2 * f12 * f33
758
- + 2 * d1 * f1 * f2 * f33
759
- + 2 * d2 * f1 * f2 * f33
760
- - 3 * d1 * f22 * f33
761
- - d2 * f22 * f33
762
- - 2 * d1 * f1 * f34
763
- + 2 * d1 * f2 * f34
764
- - 4 * f12 * f22 * v1
765
- + 2 * f24 * v1
766
- + 8 * f12 * f2 * f3 * v1
767
- - 4 * f1 * f22 * f3 * v1
768
- - 4 * f12 * f32 * v1
769
- + 8 * f1 * f2 * f32 * v1
770
- - 4 * f22 * f32 * v1
771
- - 4 * f1 * f33 * v1
772
- + 2 * f34 * v1
773
- + 2 * f14 * v2
774
- - 4 * f13 * f3 * v2
775
- + 4 * f1 * f33 * v2
776
- - 2 * f34 * v2
777
- - 2 * f14 * v3
778
- + 4 * f12 * f22 * v3
779
- - 2 * f24 * v3
780
- + 4 * f13 * f3 * v3
781
- - 8 * f12 * f2 * f3 * v3
782
- + 4 * f1 * f22 * f3 * v3
783
- + 4 * f12 * f32 * v3
784
- - 8 * f1 * f2 * f32 * v3
785
- + 4 * f22 * f32 * v3
786
- )
787
- / ((f1 - f2) ** 2 * (f1 - f3) ** 3 * (-f2 + f3) ** 2)
788
- )
789
-
790
- delta_4 = -(
791
- (
792
- d2 * f13 * f2
793
- - d1 * f12 * f22
794
- - 2 * d2 * f12 * f22
795
- + d1 * f1 * f23
796
- + d2 * f1 * f23
797
- - d2 * f13 * f3
798
- + 2 * d1 * f12 * f2 * f3
799
- + d2 * f12 * f2 * f3
800
- - d1 * f1 * f22 * f3
801
- + d2 * f1 * f22 * f3
802
- - d1 * f23 * f3
803
- - d2 * f23 * f3
804
- - d1 * f12 * f32
805
- + d2 * f12 * f32
806
- - d1 * f1 * f2 * f32
807
- - 2 * d2 * f1 * f2 * f32
808
- + 2 * d1 * f22 * f32
809
- + d2 * f22 * f32
810
- + d1 * f1 * f33
811
- - d1 * f2 * f33
812
- + 3 * f1 * f22 * v1
813
- - 2 * f23 * v1
814
- - 6 * f1 * f2 * f3 * v1
815
- + 3 * f22 * f3 * v1
816
- + 3 * f1 * f32 * v1
817
- - f33 * v1
818
- - f13 * v2
819
- + 3 * f12 * f3 * v2
820
- - 3 * f1 * f32 * v2
821
- + f33 * v2
822
- + f13 * v3
823
- - 3 * f1 * f22 * v3
824
- + 2 * f23 * v3
825
- - 3 * f12 * f3 * v3
826
- + 6 * f1 * f2 * f3 * v3
827
- - 3 * f22 * f3 * v3
828
- )
829
- / ((f1 - f2) ** 2 * (f1 - f3) ** 3 * (-f2 + f3) ** 2)
830
- )
831
-
832
- return delta_0, delta_1, delta_2, delta_3, delta_4
833
-
834
-
835
- def chiPN(Seta, eta, chi1, chi2):
836
- chi_s = chi1 + chi2
837
- chi_a = chi1 - chi2
838
-
839
- return 0.5 * (chi_s * (1.0 - eta * 76.0 / 113.0) + Seta * chi_a)
840
-
841
-
842
- def _linear_interp_finspin(finspin):
843
- # Put QNM data in same device as input
844
- QNMData_a = phenom_d_data.QNMData_a.to(device=finspin.device)
845
- QNMData_fdamp = phenom_d_data.QNMData_fdamp.to(device=finspin.device)
846
- QNMData_fring = phenom_d_data.QNMData_fring.to(device=finspin.device)
847
- # chi is a batch of final spins i.e. torch.Size([n])
848
- right_spin_idx = torch.bucketize(finspin, QNMData_a)
849
- right_spin_val = QNMData_a[right_spin_idx]
850
- # QNMData_a is sorted, hence take the previous index
851
- left_spin_idx = right_spin_idx - 1
852
- left_spin_val = QNMData_a[left_spin_idx]
853
1172
 
854
- if not torch.all(left_spin_val < right_spin_val):
855
- raise RuntimeError(
856
- "Left value in grid should be greater than right. "
857
- "Maybe be caused for extremal spin values."
858
- )
859
- left_fring = QNMData_fring[left_spin_idx]
860
- right_fring = QNMData_fring[right_spin_idx]
861
- slope_fring = right_fring - left_fring
862
- slope_fring /= right_spin_val - left_spin_val
863
-
864
- left_fdamp = QNMData_fdamp[left_spin_idx]
865
- right_fdamp = QNMData_fdamp[right_spin_idx]
866
- slope_fdamp = right_fdamp - left_fdamp
867
- slope_fdamp /= right_spin_val - left_spin_val
868
-
869
- return (
870
- slope_fring * (finspin - left_spin_val) + left_fring,
871
- slope_fdamp * (finspin - left_spin_val) + left_fdamp,
872
- )
873
-
874
-
875
- def fmaxCalc(fRD, fDM, gamma2, gamma3):
876
- res = torch.zeros_like(gamma2)
877
- res = torch.abs(fRD + (-fDM * gamma3) / gamma2) * (gamma2 > 1).to(
878
- torch.int
879
- ) + torch.abs(
880
- fRD + (fDM * (-1 + torch.sqrt(1 - gamma2 * gamma2)) * gamma3) / gamma2
881
- ) * (
882
- gamma2 <= 1
883
- ).to(
884
- torch.int
885
- )
886
- return res
887
-
888
-
889
- def fring_fdamp(eta, eta2, chi1, chi2):
890
- finspin = FinalSpin0815(eta, eta2, chi1, chi2)
891
- Erad = PhenomInternal_EradRational0815(eta, eta2, chi1, chi2)
892
-
893
- fRD, fDM = _linear_interp_finspin(finspin)
894
- fRD /= 1.0 - Erad
895
- fDM /= 1.0 - Erad
896
-
897
- return fRD, fDM
898
-
899
-
900
- def phenom_d_inspiral_phase(Mf, mass_1, mass_2, eta, eta2, xi, chi1, chi2):
901
- ins_phasing, ins_Dphasing = taylorf2_phase(Mf, mass_1, mass_2, chi1, chi2)
902
-
903
- sigma1 = sigma1Fit(eta, eta2, xi)
904
- sigma2 = sigma2Fit(eta, eta2, xi)
905
- sigma3 = sigma3Fit(eta, eta2, xi)
906
- sigma4 = sigma4Fit(eta, eta2, xi)
907
-
908
- ins_phasing += (Mf.mT * sigma1 / eta).mT
909
- ins_phasing += (Mf.mT ** (4.0 / 3.0) * 0.75 * sigma2 / eta).mT
910
- ins_phasing += (Mf.mT ** (5.0 / 3.0) * 0.6 * sigma3 / eta).mT
911
- ins_phasing += (Mf.mT**2.0 * 0.5 * sigma4 / eta).mT
912
-
913
- ins_Dphasing = (ins_Dphasing.T + sigma1 / eta).mT
914
- ins_Dphasing += (Mf.mT ** (1.0 / 3.0) * sigma2 / eta).mT
915
- ins_Dphasing += (Mf.mT ** (2.0 / 3.0) * sigma3 / eta).mT
916
- ins_Dphasing += (Mf.mT * sigma4 / eta).mT
917
-
918
- return ins_phasing, ins_Dphasing
919
-
920
-
921
- def phenom_d_int_phase(Mf, eta, eta2, xi):
922
- beta1 = beta1Fit(eta, eta2, xi)
923
- beta2 = beta2Fit(eta, eta2, xi)
924
- beta3 = beta3Fit(eta, eta2, xi)
925
- # Merger phase
926
- # Leading beta0 is not added here
927
- # overall 1/eta is not multiplied
928
- int_phasing = (Mf.mT * beta1).mT
929
- int_phasing += (torch.log(Mf).mT * beta2).mT
930
- int_phasing -= (Mf.mT ** (-3.0) / 3.0 * beta3).mT
931
-
932
- # overall 1/eta is multiple in derivative of
933
- # intermediate phase
934
- int_Dphasing = (Mf.mT ** (-4.0) * beta3).mT
935
- int_Dphasing += (Mf.mT ** (-1.0) * beta2).mT
936
- int_Dphasing = (int_Dphasing.T + beta1).mT
937
- int_Dphasing = (int_Dphasing.T / eta).mT
938
- return int_phasing, int_Dphasing
939
-
940
-
941
- def phenom_d_mrd_phase(Mf, eta, eta2, chi1, chi2, xi):
942
- alpha1 = alpha1Fit(eta, eta2, xi)
943
- alpha2 = alpha2Fit(eta, eta2, xi)
944
- alpha3 = alpha3Fit(eta, eta2, xi)
945
- alpha4 = alpha4Fit(eta, eta2, xi)
946
- alpha5 = alpha5Fit(eta, eta2, xi)
947
-
948
- # merger ringdown
949
- fRD, fDM = fring_fdamp(eta, eta2, chi1, chi2)
950
- f_minus_alpha5_fRD = (Mf.t() - alpha5 * fRD).t()
951
-
952
- # Leading 1/eta is not multiplied at this stage
953
- mrd_phasing = (Mf.t() * alpha1).t()
954
- mrd_phasing -= (1 / Mf.t() * alpha2).t()
955
- mrd_phasing += (4.0 / 3.0) * (Mf.t() ** (3.0 / 4.0) * alpha3).t()
956
- mrd_phasing += (torch.atan(f_minus_alpha5_fRD.t() / fDM) * alpha4).t()
957
-
958
- mrd_Dphasing = (
959
- alpha4 * fDM / (f_minus_alpha5_fRD.t() ** 2 + fDM**2)
960
- ).t()
961
- mrd_Dphasing += (Mf.t() ** (-1.0 / 4.0) * alpha3).t()
962
- mrd_Dphasing += (Mf.t() ** (-2.0) * alpha2).t()
963
- mrd_Dphasing = (mrd_Dphasing.t() + alpha1).t()
964
- mrd_Dphasing = (mrd_Dphasing.t() / eta).t()
965
-
966
- return mrd_phasing, mrd_Dphasing
967
-
968
-
969
- def phenom_d_phase(Mf, mass_1, mass_2, eta, eta2, chi1, chi2, xi):
970
- ins_phase, ins_Dphase = phenom_d_inspiral_phase(
971
- Mf, mass_1, mass_2, eta, eta2, xi, chi1, chi2
972
- )
973
- int_phase, int_Dphase = phenom_d_int_phase(Mf, eta, eta2, xi)
974
- mrd_phase, mrd_Dphase = phenom_d_mrd_phase(Mf, eta, eta2, chi1, chi2, xi)
975
-
976
- # merger ringdown
977
- fRD, fDM = fring_fdamp(eta, eta2, chi1, chi2)
978
- # definitions in Eq. (35) of arXiv:1508.07253
979
- # PHI_fJoin_INS in header LALSimIMRPhenomD.h
980
- # C1 continuity at intermediate region i.e. f_1
981
- PHI_fJoin_INS = 0.018 * torch.ones_like(Mf)
982
- ins_phase_f1, ins_Dphase_f1 = phenom_d_inspiral_phase(
983
- PHI_fJoin_INS, mass_1, mass_2, eta, eta2, xi, chi1, chi2
984
- )
985
- int_phase_f1, int_Dphase_f1 = phenom_d_int_phase(
986
- PHI_fJoin_INS, eta, eta2, xi
987
- )
988
- C2Int = ins_Dphase_f1 - int_Dphase_f1
989
- C1Int = ins_phase_f1 - (int_phase_f1.T / eta).mT - C2Int * PHI_fJoin_INS
990
- # C1 continuity at ringdown
991
- fRDJoin = (0.5 * torch.ones_like(Mf).mT * fRD).mT
992
- int_phase_rd, int_Dphase_rd = phenom_d_int_phase(fRDJoin, eta, eta2, xi)
993
- mrd_phase_rd, mrd_Dphase_rd = phenom_d_mrd_phase(
994
- fRDJoin, eta, eta2, chi1, chi2, xi
995
- )
996
- PhiIntTempVal = (int_phase_rd.T / eta).mT + C1Int + C2Int * fRDJoin
997
- # C2MRD = int_Dphase_rd - mrd_Dphase_rd
998
- C2MRD = C2Int + int_Dphase_rd - mrd_Dphase_rd
999
- C1MRD = PhiIntTempVal - (mrd_phase_rd.T / eta).mT - C2MRD * fRDJoin
1000
-
1001
- int_phase = (int_phase.T / eta).mT
1002
- int_phase += C1Int
1003
- int_phase += Mf * C2Int
1004
-
1005
- mrd_phase = (mrd_phase.T / eta).mT
1006
- mrd_phase += C1MRD
1007
- mrd_phase += Mf * C2MRD
1008
-
1009
- # construct full IMR phase
1010
- theta_minus_f1 = torch.heaviside(
1011
- PHI_fJoin_INS - Mf, torch.tensor(0.0, device=Mf.device)
1012
- )
1013
- theta_plus_f1 = torch.heaviside(
1014
- Mf - PHI_fJoin_INS, torch.tensor(1.0, device=Mf.device)
1015
- )
1016
- theta_minus_f2 = torch.heaviside(
1017
- fRDJoin - Mf, torch.tensor(0.0, device=Mf.device)
1018
- )
1019
- theta_plus_f2 = torch.heaviside(
1020
- Mf - fRDJoin, torch.tensor(1.0, device=Mf.device)
1021
- )
1022
-
1023
- phasing = theta_minus_f1 * ins_phase
1024
- phasing += theta_plus_f1 * int_phase * theta_minus_f2
1025
- phasing += theta_plus_f2 * mrd_phase
1026
-
1027
- Dphasing = theta_minus_f1 * ins_Dphase
1028
- Dphasing += theta_plus_f1 * int_Dphase * theta_minus_f2
1029
- Dphasing += theta_plus_f2 * mrd_Dphase
1030
-
1031
- return phasing, Dphasing
1032
-
1033
-
1034
- def phenom_d_inspiral_amp(Mf, eta, eta2, Seta, xi, chi1, chi2, chi12, chi22):
1035
- SetaPlus1 = 1 + Seta
1036
-
1037
- Mf_one_third = Mf ** (1.0 / 3.0)
1038
- Mf_two_third = Mf_one_third * Mf_one_third
1039
- Mf_four_third = Mf_two_third * Mf_two_third
1040
- Mf_five_third = Mf_four_third * Mf_one_third
1041
- Mf_seven_third = Mf_five_third * Mf_two_third
1042
- MF_eight_third = Mf_seven_third * Mf_one_third
1043
- Mf_two = Mf * Mf
1044
- Mf_three = Mf_two * Mf
1045
-
1046
- prefactors_two_thirds = ((-969 + 1804 * eta) * PI ** (2.0 / 3.0)) / 672
1047
- prefactors_one = (
1048
- (
1049
- chi1 * (81 * SetaPlus1 - 44 * eta)
1050
- + chi2 * (81 - 81 * Seta - 44 * eta)
1173
+ def delta_values(self, f1, f2, f3, v1, v2, v3, d1, d2):
1174
+ f12 = f1 * f1
1175
+ f13 = f1 * f12
1176
+ f14 = f1 * f13
1177
+ f15 = f1 * f14
1178
+ f22 = f2 * f2
1179
+ f23 = f2 * f22
1180
+ f24 = f2 * f23
1181
+ f32 = f3 * f3
1182
+ f33 = f3 * f32
1183
+ f34 = f3 * f33
1184
+ f35 = f3 * f34
1185
+ delta_0 = -(
1186
+ (
1187
+ d2 * f15 * f22 * f3
1188
+ - 2 * d2 * f14 * f23 * f3
1189
+ + d2 * f13 * f24 * f3
1190
+ - d2 * f15 * f2 * f32
1191
+ + d2 * f14 * f22 * f32
1192
+ - d1 * f13 * f23 * f32
1193
+ + d2 * f13 * f23 * f32
1194
+ + d1 * f12 * f24 * f32
1195
+ - d2 * f12 * f24 * f32
1196
+ + d2 * f14 * f2 * f33
1197
+ + 2 * d1 * f13 * f22 * f33
1198
+ - 2 * d2 * f13 * f22 * f33
1199
+ - d1 * f12 * f23 * f33
1200
+ + d2 * f12 * f23 * f33
1201
+ - d1 * f1 * f24 * f33
1202
+ - d1 * f13 * f2 * f34
1203
+ - d1 * f12 * f22 * f34
1204
+ + 2 * d1 * f1 * f23 * f34
1205
+ + d1 * f12 * f2 * f35
1206
+ - d1 * f1 * f22 * f35
1207
+ + 4 * f12 * f23 * f32 * v1
1208
+ - 3 * f1 * f24 * f32 * v1
1209
+ - 8 * f12 * f22 * f33 * v1
1210
+ + 4 * f1 * f23 * f33 * v1
1211
+ + f24 * f33 * v1
1212
+ + 4 * f12 * f2 * f34 * v1
1213
+ + f1 * f22 * f34 * v1
1214
+ - 2 * f23 * f34 * v1
1215
+ - 2 * f1 * f2 * f35 * v1
1216
+ + f22 * f35 * v1
1217
+ - f15 * f32 * v2
1218
+ + 3 * f14 * f33 * v2
1219
+ - 3 * f13 * f34 * v2
1220
+ + f12 * f35 * v2
1221
+ - f15 * f22 * v3
1222
+ + 2 * f14 * f23 * v3
1223
+ - f13 * f24 * v3
1224
+ + 2 * f15 * f2 * f3 * v3
1225
+ - f14 * f22 * f3 * v3
1226
+ - 4 * f13 * f23 * f3 * v3
1227
+ + 3 * f12 * f24 * f3 * v3
1228
+ - 4 * f14 * f2 * f32 * v3
1229
+ + 8 * f13 * f22 * f32 * v3
1230
+ - 4 * f12 * f23 * f32 * v3
1231
+ )
1232
+ / ((f1 - f2) ** 2 * (f1 - f3) ** 3 * (f3 - f2) ** 2)
1051
1233
  )
1052
- * PI
1053
- ) / 48.0
1054
- prefactors_four_thirds = (
1055
- (
1056
- -27312085.0
1057
- - 10287648 * chi22
1058
- - 10287648 * chi12 * SetaPlus1
1059
- + 10287648 * chi22 * Seta
1060
- + 24
1061
- * (
1062
- -1975055
1063
- + 857304 * chi12
1064
- - 994896 * chi1 * chi2
1065
- + 857304 * chi22
1234
+
1235
+ delta_1 = -(
1236
+ (
1237
+ -(d2 * f15 * f22)
1238
+ + 2 * d2 * f14 * f23
1239
+ - d2 * f13 * f24
1240
+ - d2 * f14 * f22 * f3
1241
+ + 2 * d1 * f13 * f23 * f3
1242
+ + 2 * d2 * f13 * f23 * f3
1243
+ - 2 * d1 * f12 * f24 * f3
1244
+ - d2 * f12 * f24 * f3
1245
+ + d2 * f15 * f32
1246
+ - 3 * d1 * f13 * f22 * f32
1247
+ - d2 * f13 * f22 * f32
1248
+ + 2 * d1 * f12 * f23 * f32
1249
+ - 2 * d2 * f12 * f23 * f32
1250
+ + d1 * f1 * f24 * f32
1251
+ + 2 * d2 * f1 * f24 * f32
1252
+ - d2 * f14 * f33
1253
+ + d1 * f12 * f22 * f33
1254
+ + 3 * d2 * f12 * f22 * f33
1255
+ - 2 * d1 * f1 * f23 * f33
1256
+ - 2 * d2 * f1 * f23 * f33
1257
+ + d1 * f24 * f33
1258
+ + d1 * f13 * f34
1259
+ + d1 * f1 * f22 * f34
1260
+ - 2 * d1 * f23 * f34
1261
+ - d1 * f12 * f35
1262
+ + d1 * f22 * f35
1263
+ - 8 * f12 * f23 * f3 * v1
1264
+ + 6 * f1 * f24 * f3 * v1
1265
+ + 12 * f12 * f22 * f32 * v1
1266
+ - 8 * f1 * f23 * f32 * v1
1267
+ - 4 * f12 * f34 * v1
1268
+ + 2 * f1 * f35 * v1
1269
+ + 2 * f15 * f3 * v2
1270
+ - 4 * f14 * f32 * v2
1271
+ + 4 * f12 * f34 * v2
1272
+ - 2 * f1 * f35 * v2
1273
+ - 2 * f15 * f3 * v3
1274
+ + 8 * f12 * f23 * f3 * v3
1275
+ - 6 * f1 * f24 * f3 * v3
1276
+ + 4 * f14 * f32 * v3
1277
+ - 12 * f12 * f22 * f32 * v3
1278
+ + 8 * f1 * f23 * f32 * v3
1066
1279
  )
1067
- * eta
1068
- + 35371056 * eta2 * PI ** (4.0 / 3.0)
1280
+ / ((f1 - f2) ** 2 * (f1 - f3) ** 3 * (-f2 + f3) ** 2)
1069
1281
  )
1070
- ) / 8.128512e6
1071
- prefactors_five_thirds = (
1072
- PI ** (5.0 / 3.0)
1073
- * (
1074
- chi2
1075
- * (
1076
- -285197 * (-1 + Seta)
1077
- + 4 * (-91902 + 1579 * Seta) * eta
1078
- - 35632 * eta2
1282
+
1283
+ delta_2 = -(
1284
+ (
1285
+ d2 * f15 * f2
1286
+ - d1 * f13 * f23
1287
+ - 3 * d2 * f13 * f23
1288
+ + d1 * f12 * f24
1289
+ + 2 * d2 * f12 * f24
1290
+ - d2 * f15 * f3
1291
+ + d2 * f14 * f2 * f3
1292
+ - d1 * f12 * f23 * f3
1293
+ + d2 * f12 * f23 * f3
1294
+ + d1 * f1 * f24 * f3
1295
+ - d2 * f1 * f24 * f3
1296
+ - d2 * f14 * f32
1297
+ + 3 * d1 * f13 * f2 * f32
1298
+ + d2 * f13 * f2 * f32
1299
+ - d1 * f1 * f23 * f32
1300
+ + d2 * f1 * f23 * f32
1301
+ - 2 * d1 * f24 * f32
1302
+ - d2 * f24 * f32
1303
+ - 2 * d1 * f13 * f33
1304
+ + 2 * d2 * f13 * f33
1305
+ - d1 * f12 * f2 * f33
1306
+ - 3 * d2 * f12 * f2 * f33
1307
+ + 3 * d1 * f23 * f33
1308
+ + d2 * f23 * f33
1309
+ + d1 * f12 * f34
1310
+ - d1 * f1 * f2 * f34
1311
+ + d1 * f1 * f35
1312
+ - d1 * f2 * f35
1313
+ + 4 * f12 * f23 * v1
1314
+ - 3 * f1 * f24 * v1
1315
+ + 4 * f1 * f23 * f3 * v1
1316
+ - 3 * f24 * f3 * v1
1317
+ - 12 * f12 * f2 * f32 * v1
1318
+ + 4 * f23 * f32 * v1
1319
+ + 8 * f12 * f33 * v1
1320
+ - f1 * f34 * v1
1321
+ - f35 * v1
1322
+ - f15 * v2
1323
+ - f14 * f3 * v2
1324
+ + 8 * f13 * f32 * v2
1325
+ - 8 * f12 * f33 * v2
1326
+ + f1 * f34 * v2
1327
+ + f35 * v2
1328
+ + f15 * v3
1329
+ - 4 * f12 * f23 * v3
1330
+ + 3 * f1 * f24 * v3
1331
+ + f14 * f3 * v3
1332
+ - 4 * f1 * f23 * f3 * v3
1333
+ + 3 * f24 * f3 * v3
1334
+ - 8 * f13 * f32 * v3
1335
+ + 12 * f12 * f2 * f32 * v3
1336
+ - 4 * f23 * f32 * v3
1079
1337
  )
1080
- + chi1
1081
- * (
1082
- 285197 * SetaPlus1
1083
- - 4 * (91902 + 1579 * Seta) * eta
1084
- - 35632 * eta2
1338
+ / ((f1 - f2) ** 2 * (f1 - f3) ** 3 * (-f2 + f3) ** 2)
1339
+ )
1340
+
1341
+ delta_3 = -(
1342
+ (
1343
+ -2 * d2 * f14 * f2
1344
+ + d1 * f13 * f22
1345
+ + 3 * d2 * f13 * f22
1346
+ - d1 * f1 * f24
1347
+ - d2 * f1 * f24
1348
+ + 2 * d2 * f14 * f3
1349
+ - 2 * d1 * f13 * f2 * f3
1350
+ - 2 * d2 * f13 * f2 * f3
1351
+ + d1 * f12 * f22 * f3
1352
+ - d2 * f12 * f22 * f3
1353
+ + d1 * f24 * f3
1354
+ + d2 * f24 * f3
1355
+ + d1 * f13 * f32
1356
+ - d2 * f13 * f32
1357
+ - 2 * d1 * f12 * f2 * f32
1358
+ + 2 * d2 * f12 * f2 * f32
1359
+ + d1 * f1 * f22 * f32
1360
+ - d2 * f1 * f22 * f32
1361
+ + d1 * f12 * f33
1362
+ - d2 * f12 * f33
1363
+ + 2 * d1 * f1 * f2 * f33
1364
+ + 2 * d2 * f1 * f2 * f33
1365
+ - 3 * d1 * f22 * f33
1366
+ - d2 * f22 * f33
1367
+ - 2 * d1 * f1 * f34
1368
+ + 2 * d1 * f2 * f34
1369
+ - 4 * f12 * f22 * v1
1370
+ + 2 * f24 * v1
1371
+ + 8 * f12 * f2 * f3 * v1
1372
+ - 4 * f1 * f22 * f3 * v1
1373
+ - 4 * f12 * f32 * v1
1374
+ + 8 * f1 * f2 * f32 * v1
1375
+ - 4 * f22 * f32 * v1
1376
+ - 4 * f1 * f33 * v1
1377
+ + 2 * f34 * v1
1378
+ + 2 * f14 * v2
1379
+ - 4 * f13 * f3 * v2
1380
+ + 4 * f1 * f33 * v2
1381
+ - 2 * f34 * v2
1382
+ - 2 * f14 * v3
1383
+ + 4 * f12 * f22 * v3
1384
+ - 2 * f24 * v3
1385
+ + 4 * f13 * f3 * v3
1386
+ - 8 * f12 * f2 * f3 * v3
1387
+ + 4 * f1 * f22 * f3 * v3
1388
+ + 4 * f12 * f32 * v3
1389
+ - 8 * f1 * f2 * f32 * v3
1390
+ + 4 * f22 * f32 * v3
1085
1391
  )
1086
- + 42840 * (-1.0 + 4 * eta) * PI
1392
+ / ((f1 - f2) ** 2 * (f1 - f3) ** 3 * (-f2 + f3) ** 2)
1087
1393
  )
1088
- ) / 32256.0
1089
- prefactors_two = (
1090
- -(
1091
- PI**2
1092
- * (
1093
- -336
1094
- * (
1095
- -3248849057.0
1096
- + 2943675504 * chi12
1097
- - 3339284256 * chi1 * chi2
1098
- + 2943675504 * chi22
1099
- )
1100
- * eta2
1101
- - 324322727232 * eta2 * eta
1102
- - 7
1103
- * (
1104
- -177520268561
1105
- + 107414046432 * chi22
1106
- + 107414046432 * chi12 * SetaPlus1
1107
- - 107414046432 * chi22 * Seta
1108
- + 11087290368
1109
- * (chi1 + chi2 + chi1 * Seta - chi2 * Seta)
1110
- * PI
1111
- )
1112
- + 12
1113
- * eta
1114
- * (
1115
- -545384828789
1116
- - 176491177632 * chi1 * chi2
1117
- + 202603761360 * chi22
1118
- + 77616 * chi12 * (2610335 + 995766 * Seta)
1119
- - 77287373856 * chi22 * Seta
1120
- + 5841690624 * (chi1 + chi2) * PI
1121
- + 21384760320 * PI**2
1122
- )
1394
+
1395
+ delta_4 = -(
1396
+ (
1397
+ d2 * f13 * f2
1398
+ - d1 * f12 * f22
1399
+ - 2 * d2 * f12 * f22
1400
+ + d1 * f1 * f23
1401
+ + d2 * f1 * f23
1402
+ - d2 * f13 * f3
1403
+ + 2 * d1 * f12 * f2 * f3
1404
+ + d2 * f12 * f2 * f3
1405
+ - d1 * f1 * f22 * f3
1406
+ + d2 * f1 * f22 * f3
1407
+ - d1 * f23 * f3
1408
+ - d2 * f23 * f3
1409
+ - d1 * f12 * f32
1410
+ + d2 * f12 * f32
1411
+ - d1 * f1 * f2 * f32
1412
+ - 2 * d2 * f1 * f2 * f32
1413
+ + 2 * d1 * f22 * f32
1414
+ + d2 * f22 * f32
1415
+ + d1 * f1 * f33
1416
+ - d1 * f2 * f33
1417
+ + 3 * f1 * f22 * v1
1418
+ - 2 * f23 * v1
1419
+ - 6 * f1 * f2 * f3 * v1
1420
+ + 3 * f22 * f3 * v1
1421
+ + 3 * f1 * f32 * v1
1422
+ - f33 * v1
1423
+ - f13 * v2
1424
+ + 3 * f12 * f3 * v2
1425
+ - 3 * f1 * f32 * v2
1426
+ + f33 * v2
1427
+ + f13 * v3
1428
+ - 3 * f1 * f22 * v3
1429
+ + 2 * f23 * v3
1430
+ - 3 * f12 * f3 * v3
1431
+ + 6 * f1 * f2 * f3 * v3
1432
+ - 3 * f22 * f3 * v3
1123
1433
  )
1434
+ / ((f1 - f2) ** 2 * (f1 - f3) ** 3 * (-f2 + f3) ** 2)
1124
1435
  )
1125
- / 6.0085960704e10
1126
- )
1127
- prefactors_seven_thirds = rho1_fun(eta, eta2, xi)
1128
- prefactors_eight_thirds = rho2_fun(eta, eta2, xi)
1129
- prefactors_three = rho3_fun(eta, eta2, xi)
1130
-
1131
- amp = torch.ones_like(Mf)
1132
- amp += (
1133
- Mf_two_third.T * prefactors_two_thirds
1134
- + Mf_four_third.T * prefactors_four_thirds
1135
- + Mf_five_third.T * prefactors_five_thirds
1136
- + Mf_seven_third.T * prefactors_seven_thirds
1137
- + MF_eight_third.T * prefactors_eight_thirds
1138
- + Mf.mT * prefactors_one
1139
- + Mf_two.T * prefactors_two
1140
- + Mf_three.T * prefactors_three
1141
- ).mT
1142
-
1143
- Damp = (
1144
- (2.0 / 3.0) / Mf_one_third.T * prefactors_two_thirds
1145
- + (4.0 / 3.0) * Mf_one_third.T * prefactors_four_thirds
1146
- + (5.0 / 3.0) * Mf_two_third.T * prefactors_five_thirds
1147
- + (7.0 / 3.0) * Mf_four_third.T * prefactors_seven_thirds
1148
- + (8.0 / 3.0) * Mf_five_third.T * prefactors_eight_thirds
1149
- + prefactors_one
1150
- + 2.0 * Mf.mT * prefactors_two
1151
- + 3.0 * Mf_two.T * prefactors_three
1152
- ).mT
1153
-
1154
- return amp, Damp
1155
-
1156
-
1157
- def phenom_d_mrd_amp(Mf, eta, eta2, chi1, chi2, xi):
1158
- # merger ringdown
1159
- fRD, fDM = fring_fdamp(eta, eta2, chi1, chi2)
1160
-
1161
- gamma1 = gamma1_fun(eta, eta2, xi)
1162
- gamma2 = gamma2_fun(eta, eta2, xi)
1163
- gamma3 = gamma3_fun(eta, eta2, xi)
1164
- fDMgamma3 = fDM * gamma3
1165
- pow2_fDMgamma3 = (torch.ones_like(Mf).mT * fDMgamma3 * fDMgamma3).mT
1166
- fminfRD = Mf - (torch.ones_like(Mf).mT * fRD).mT
1167
- exp_times_lorentzian = torch.exp(fminfRD.mT * gamma2 / fDMgamma3).mT
1168
- exp_times_lorentzian *= fminfRD**2 + pow2_fDMgamma3
1169
-
1170
- amp = (1 / exp_times_lorentzian.T * gamma1 * gamma3 * fDM).mT
1171
- Damp = (fminfRD.mT * -2 * fDM * gamma1 * gamma3) / (
1172
- fminfRD * fminfRD + pow2_fDMgamma3
1173
- ).mT - (gamma2 * gamma1)
1174
- Damp = Damp.T / exp_times_lorentzian
1175
- return amp, Damp
1176
-
1177
-
1178
- def phenom_d_int_amp(Mf, eta, eta2, Seta, chi1, chi2, chi12, chi22, xi):
1179
- # merger ringdown
1180
- fRD, fDM = fring_fdamp(eta, eta2, chi1, chi2)
1181
- # Geometric frequency definition from PhenomD header file
1182
- AMP_fJoin_INS = 0.014
1183
-
1184
- Mf1 = AMP_fJoin_INS * torch.ones_like(Mf)
1185
- gamma2 = gamma2_fun(eta, eta2, xi)
1186
- gamma3 = gamma3_fun(eta, eta2, xi)
1187
-
1188
- fpeak = fmaxCalc(fRD, fDM, gamma2, gamma3)
1189
- Mf3 = (torch.ones_like(Mf).mT * fpeak).mT
1190
- dfx = 0.5 * (Mf3 - Mf1)
1191
- Mf2 = Mf1 + dfx
1192
-
1193
- v1, d1 = phenom_d_inspiral_amp(
1194
- Mf1, eta, eta2, Seta, xi, chi1, chi2, chi12, chi22
1195
- )
1196
- v3, d2 = phenom_d_mrd_amp(Mf3, eta, eta2, chi1, chi2, xi)
1197
- v2 = (torch.ones_like(Mf).mT * AmpIntColFitCoeff(eta, eta2, xi)).mT
1198
-
1199
- delta_0, delta_1, delta_2, delta_3, delta_4 = delta_values(
1200
- f1=Mf1, f2=Mf2, f3=Mf3, v1=v1, v2=v2, v3=v3, d1=d1, d2=d2
1201
- )
1202
-
1203
- amp = (
1204
- delta_0
1205
- + Mf * delta_1
1206
- + Mf**2 * (delta_2 + Mf * delta_3 + Mf**2 * delta_4)
1207
- )
1208
- Damp = delta_1 + Mf * (
1209
- 2 * delta_2 + 3 * Mf * delta_3 + 4 * Mf**2 * delta_4
1210
- )
1211
- return amp, Damp
1212
-
1213
-
1214
- def phenom_d_amp(
1215
- Mf, mass_1, mass_2, eta, eta2, Seta, chi1, chi2, chi12, chi22, xi, distance
1216
- ):
1217
- ins_amp, ins_Damp = phenom_d_inspiral_amp(
1218
- Mf, eta, eta2, Seta, xi, chi1, chi2, chi12, chi22
1219
- )
1220
- int_amp, int_Damp = phenom_d_int_amp(
1221
- Mf, eta, eta2, Seta, chi1, chi2, chi12, chi22, xi
1222
- )
1223
- mrd_amp, mrd_Damp = phenom_d_mrd_amp(Mf, eta, eta2, chi1, chi2, xi)
1224
-
1225
- gamma2 = gamma2_fun(eta, eta2, xi)
1226
- gamma3 = gamma3_fun(eta, eta2, xi)
1227
- fRD, fDM = fring_fdamp(eta, eta2, chi1, chi2)
1228
- Mf_peak = fmaxCalc(fRD, fDM, gamma2, gamma3)
1229
- # Geometric peak and joining frequencies
1230
- Mf_peak = (torch.ones_like(Mf).mT * Mf_peak).mT
1231
- Mf_join_ins = 0.014 * torch.ones_like(Mf)
1232
-
1233
- # construct full IMR Amp
1234
- theta_minus_f1 = torch.heaviside(
1235
- Mf_join_ins - Mf, torch.tensor(0.0, device=Mf.device)
1236
- )
1237
- theta_plus_f1 = torch.heaviside(
1238
- Mf - Mf_join_ins, torch.tensor(1.0, device=Mf.device)
1239
- )
1240
- theta_minus_f2 = torch.heaviside(
1241
- Mf_peak - Mf, torch.tensor(0.0, device=Mf.device)
1242
- )
1243
- theta_plus_f2 = torch.heaviside(
1244
- Mf - Mf_peak, torch.tensor(1.0, device=Mf.device)
1245
- )
1246
-
1247
- amp = theta_minus_f1 * ins_amp
1248
- amp += theta_plus_f1 * int_amp * theta_minus_f2
1249
- amp += theta_plus_f2 * mrd_amp
1250
-
1251
- Damp = theta_minus_f1 * ins_Damp
1252
- Damp += theta_plus_f1 * int_Damp * theta_minus_f2
1253
- Damp += theta_plus_f2 * mrd_Damp
1254
-
1255
- return amp, Damp
1256
-
1257
-
1258
- def phenom_d_htilde(
1259
- f: TensorType,
1260
- chirp_mass: TensorType,
1261
- mass_ratio: TensorType,
1262
- chi1: TensorType,
1263
- chi2: TensorType,
1264
- distance: TensorType,
1265
- phic: TensorType,
1266
- f_ref: float,
1267
- ):
1268
- total_mass = chirp_mass * (1 + mass_ratio) ** 1.2 / mass_ratio**0.6
1269
- mass_1 = total_mass / (1 + mass_ratio)
1270
- mass_2 = mass_1 * mass_ratio
1271
- eta = (chirp_mass / total_mass) ** (5 / 3)
1272
- eta2 = eta * eta
1273
- Seta = torch.sqrt(1.0 - 4.0 * eta)
1274
- chi = chiPN(Seta, eta, chi1, chi2)
1275
- chi22 = chi2 * chi2
1276
- chi12 = chi1 * chi1
1277
- xi = -1.0 + chi
1278
- M_s = total_mass * MTSUN_SI
1279
-
1280
- gamma2 = gamma2_fun(eta, eta2, xi)
1281
- gamma3 = gamma3_fun(eta, eta2, xi)
1282
-
1283
- fRD, fDM = fring_fdamp(eta, eta2, chi1, chi2)
1284
- Mf_peak = fmaxCalc(fRD, fDM, gamma2, gamma3)
1285
- _, t0 = phenom_d_mrd_phase(Mf_peak, eta, eta2, chi1, chi2, xi)
1286
-
1287
- Mf = torch.outer(M_s, f)
1288
- Mf_ref = torch.outer(M_s, f_ref * torch.ones_like(f))
1289
-
1290
- Psi, _ = phenom_d_phase(Mf, mass_1, mass_2, eta, eta2, chi1, chi2, xi)
1291
- Psi_ref, _ = phenom_d_phase(
1292
- Mf_ref, mass_1, mass_2, eta, eta2, chi1, chi2, xi
1293
- )
1294
-
1295
- Psi = (Psi.T - 2 * phic).mT
1296
- Psi -= Psi_ref
1297
- Psi -= ((Mf - Mf_ref).mT * t0).mT
1298
-
1299
- amp, _ = phenom_d_amp(
1300
- Mf,
1301
- mass_1,
1302
- mass_2,
1303
- eta,
1304
- eta2,
1305
- Seta,
1306
- chi1,
1307
- chi2,
1308
- chi12,
1309
- chi22,
1310
- xi,
1311
- distance,
1312
- )
1313
-
1314
- amp_0 = taylorf2_amplitude(
1315
- Mf, mass_1, mass_2, eta, distance
1316
- ) # this includes f^(-7/6) dependence
1317
-
1318
- h0 = -amp_0 * amp * torch.exp(-1j * Psi)
1319
-
1320
- return h0
1321
-
1322
-
1323
- def IMRPhenomD(
1324
- f: TensorType,
1325
- chirp_mass: TensorType,
1326
- mass_ratio: TensorType,
1327
- chi1: TensorType,
1328
- chi2: TensorType,
1329
- distance: TensorType,
1330
- phic: TensorType,
1331
- inclination: TensorType,
1332
- f_ref: float,
1333
- ):
1334
- """
1335
- IMRPhenomD waveform
1336
-
1337
- Returns:
1338
- --------
1339
- hp, hc
1340
- """
1341
- # shape assumed (n_batch, params)
1342
- if (
1343
- chirp_mass.shape[0] != mass_ratio.shape[0]
1344
- or mass_ratio.shape[0] != chi1.shape[0]
1345
- or chi1.shape[0] != chi2.shape[0]
1346
- or chi2.shape[0] != distance.shape[0]
1347
- or distance.shape[0] != phic.shape[0]
1348
- or phic.shape[0] != inclination.shape[0]
1349
- ):
1350
- raise RuntimeError("Tensors should have same batch size")
1351
- cfac = torch.cos(inclination)
1352
- pfac = 0.5 * (1.0 + cfac * cfac)
1353
1436
 
1354
- htilde = phenom_d_htilde(
1355
- f, chirp_mass, mass_ratio, chi1, chi2, distance, phic, f_ref
1356
- )
1437
+ return delta_0, delta_1, delta_2, delta_3, delta_4
1357
1438
 
1358
- hp = (htilde.mT * pfac).mT
1359
- hc = -1j * (htilde.mT * cfac).mT
1439
+ def chiPN(self, Seta, eta, chi1, chi2):
1440
+ chi_s = chi1 + chi2
1441
+ chi_a = chi1 - chi2
1360
1442
 
1361
- return hp, hc
1443
+ return 0.5 * (chi_s * (1.0 - eta * 76.0 / 113.0) + Seta * chi_a)