@@ -252,8 +252,10 @@ class Scatter2to3MC:
252
252
"""
253
253
2 -> 3 scattering for general masses in fixed target frame
254
254
Based on Byckling, Kajantie ch. V.4
255
+
256
+ ATTN: assumes particle A is at rest.
255
257
"""
256
- def __init__ (self , mtrx2 : MatrixElement2to3 , p1 = LorentzVector (), p2 = LorentzVector (), n_samples = 1000 ):
258
+ def __init__ (self , mtrx2 : MatrixElement2to3 , p1 = LorentzVector (), p2 = LorentzVector (), n_samples = 100 ):
257
259
self .mtrx2 = mtrx2
258
260
259
261
self .ma = mtrx2 .ma
@@ -274,6 +276,7 @@ def __init__(self, mtrx2: MatrixElement2to3, p1=LorentzVector(), p2=LorentzVecto
274
276
275
277
def cayley_det (self , x , y , z , u , v , w ):
276
278
# Gramm-Schmidt det but with invariants
279
+ # Eq. 5.24 of Byckling, Kajantie
277
280
return - 0.5 * np .linalg .det ([[0 , 1 , 1 , 1 , 1 ],
278
281
[1 , 0 , v , x , z ],
279
282
[1 , v , 0 , u , y ],
@@ -283,6 +286,9 @@ def cayley_det(self, x, y, z, u, v, w):
283
286
def kallen (self , x , y , z ):
284
287
return np .power ((x - y - z ), 2 ) - 4 * y * z
285
288
289
+ def flux_factor (self , s ):
290
+ return power (2 * sqrt (self .kallen (s , self .ma ** 2 , self .mb ** 2 ))* (2 * pi )** 5 , - 1 )
291
+
286
292
def s2MaxMin (self , s ):
287
293
return (sqrt (s ) - self .m1 )** 2 , (self .m2 + self .m3 )** 2
288
294
@@ -293,7 +299,7 @@ def t1MaxMin(self, s, s2):
293
299
+ np .nan_to_num (sqrt (self .kallen (s , self .ma ** 2 , self .mb ** 2 )* self .kallen (s , s2 , self .m1 ** 2 ))))/ (2 * s )
294
300
295
301
def phase_space_heaviside (self , s , t1 , s2 ):
296
- return np .heaviside (- np .nan_to_num (self .cayley_det (s , t1 , s2 , self .ma ** 2 , self .mb ** 2 , self .m1 ** 2 )), 0.0 ) \
302
+ return np .heaviside (np .nan_to_num (- self .cayley_det (s , t1 , s2 , self .ma ** 2 , self .mb ** 2 , self .m1 ** 2 )), 0.0 ) \
297
303
* np .heaviside (self .kallen (s , self .m1 ** 2 , s2 ), 0.0 ) \
298
304
* np .heaviside (self .kallen (s2 , self .m2 ** 2 , self .m3 ** 2 ), 0.0 )
299
305
@@ -310,11 +316,30 @@ def s1_from_angle(self, phib, s, t1, s2, t2):
310
316
[s - self .ma ** 2 + self .mb ** 2 , s + s2 - self .m1 ** 2 , 0.0 ]]) \
311
317
+ 2 * np .nan_to_num (sqrt (self .cayley_det (s ,t1 ,s2 ,self .ma ** 2 ,self .mb ** 2 ,self .m1 ** 2 )* self .cayley_det (s2 ,t2 ,self .m3 ** 2 ,t1 ,self .mb ** 2 ,self .m2 ** 2 )))* cos (phib ))
312
318
319
+ def paR23 (self , s , t1 , s2 ):
320
+ return sqrt (((s + t1 - self .mb ** 2 - self .m1 ** 2 )/ (2 * sqrt (s2 )))** 2 - self .ma ** 2 )
321
+
322
+ def pbR23 (self , s2 , t1 ):
323
+ return sqrt (self .kallen (s2 , self .mb ** 2 , t1 )/ s2 ) / 2
324
+
325
+ def p1R23 (self , s , s2 ):
326
+ e1_cm = (s + self .m1 ** 2 - s2 )/ (2 * sqrt (s ))
327
+ return np .sqrt (e1_cm ** 2 - self .m1 ** 2 )
328
+
329
+ def sinTheta_b1 (self , s , t1 , s2 ):
330
+ # R23 frame
331
+ return - 4 * s2 * self .cayley_det (s , t1 , s2 , self .ma ** 2 , self .mb ** 2 , self .m1 ** 2 ) \
332
+ / (self .kallen (s2 , self .mb ** 2 , t1 )* self .kallen (s , s2 , self .m1 ** 2 ))
333
+
334
+ def cosTheta_ab (self , s , s2 , t1 ):
335
+ sinTheta_b1 = self .sinTheta_b1 (s , t1 , s2 )
336
+ cosTheta_b1 = sqrt (1 - sinTheta_b1 ** 2 )
337
+ return (self .p1R23 (s , s2 )* self .pbR23 (s2 , t1 )* cosTheta_b1 - self .pbR23 (s2 , t1 )** 2 ) / (self .pbR23 (s2 , t1 )* self .paR23 (s , t1 , s2 ))
338
+
313
339
def dsigma_ds2dt1dOmega3 (self , s , s2 , t1 , cosThetab3 , phib ):
314
340
t2 = self .t2_from_angle (cosThetab3 , t1 , s2 )
315
341
s1 = self .s1_from_angle (phib , s , t1 , s2 , t2 )
316
- return pi * self .phase_space_heaviside (s , t1 , s2 ) * self .mtrx2 (s , s2 , t1 , s1 , t2 ) \
317
- * power (2 * sqrt ((s - (self .ma + self .mb )** 2 )* (s - (self .ma - self .mb )** 2 )), - 1 ) \
342
+ return pi * self .phase_space_heaviside (s , t1 , s2 ) * self .mtrx2 (s , s2 , t1 , s1 , t2 ) * self .flux_factor (s ) \
318
343
* np .nan_to_num (sqrt (self .kallen (s , self .ma ** 2 , self .mb ** 2 )/ self .kallen (s2 , self .m2 ** 2 , self .m3 ** 2 )))/ (16 * s2 )
319
344
320
345
def r23_velocity (self , s2 , t1 ):
@@ -364,23 +389,76 @@ def simulate_particle1(self, s):
364
389
t1_rnd = np .random .uniform (t1Min , t1Max , self .n_samples )
365
390
cos_rnd = np .random .uniform (- 1 , 1 , self .n_samples )
366
391
phi_rnd = np .random .uniform (0.0 , 2 * pi , self .n_samples )
392
+
393
+ print ("t1 min, max = " , t1Min , t1Max )
394
+ print ("s2 min, max = " , s2Min , s2Max )
367
395
368
396
mc_volume = (t1Max - t1Min )* (s2Max - s2Min )* 4 * pi / self .n_samples
369
397
370
398
# Get particle 1's CM spectra
371
399
for i in range (self .n_samples ):
400
+ if self .phase_space_heaviside (s , t1_rnd [i ], s2_rnd [i ]) < 1.0 :
401
+ continue
402
+
372
403
weights = self .dsigma_ds2dt1dOmega3 (s , s2_rnd [i ], t1_rnd [i ], cos_rnd [i ], phi_rnd [i ])
373
404
e1_cm = (s + self .m1 ** 2 - s2_rnd [i ])/ (2 * sqrt (s ))
374
405
p1_cm = np .sqrt (e1_cm ** 2 - self .m1 ** 2 )
375
406
theta_b1_cm = arcsin (sqrt (- 4 * s2_rnd [i ]* self .cayley_det (s , t1_rnd [i ], s2_rnd [i ], self .ma ** 2 , self .mb ** 2 , self .m1 ** 2 ) \
376
407
/ (self .kallen (s2_rnd [i ], self .mb ** 2 , t1_rnd [i ])* self .kallen (s , s2_rnd [i ], self .m1 ** 2 ))))
377
408
lorentz_vector_p1_cm = LorentzVector (e1_cm , p1_cm * sin (theta_b1_cm ), 0.0 , p1_cm * cos (theta_b1_cm ))
378
- v_cm_to_lab = self .r23_velocity (s2_rnd [i ], t1_rnd [i ])
379
- lorentz_vector_p1_lab = lorentz_boost (lorentz_vector_p1_cm , v_cm_to_lab )
409
+
410
+ # Boost to lab frame: use pa velocity assuming pa is at rest
411
+ pa_R23 = self .paR23 (s , t1_rnd [i ], s2_rnd [i ])
412
+ ea_R23 = sqrt (pa_R23 ** 2 + self .ma ** 2 )
413
+ cosTheta_ab_R23 = self .cosTheta_ab (s , s2_rnd [i ], t1_rnd [i ])
414
+ va_R23_3vec = Vector3 (- pa_R23 * sqrt (1 - cosTheta_ab_R23 ** 2 )/ ea_R23 , 0.0 , - pa_R23 * cosTheta_ab_R23 / ea_R23 )
415
+
416
+ #v_cm_to_lab = self.r23_velocity(s2_rnd[i], t1_rnd[i])
417
+ lorentz_vector_p1_lab = lorentz_boost (lorentz_vector_p1_cm , va_R23_3vec )
380
418
self .p1_lab_4vectors .append (lorentz_vector_p1_lab )
381
419
self .p1_lab_energies .append (lorentz_vector_p1_lab .p0 )
420
+ #print("dsigma = {}, CM energy = {}, Lab energy = {}".format(weights, lorentz_vector_p1_cm.p0, lorentz_vector_p1_lab.p0))
382
421
self .p1_lab_angles .append (lorentz_vector_p1_lab .theta ())
383
422
self .dsigma .append (weights * mc_volume )
423
+
424
+ def simulate_particle1_phase_space_sampled (self , s ):
425
+ s2Max , s2Min = self .s2MaxMin (s )
426
+
427
+ s2_grid = np .linspace (s2Min , s2Max , self .n_samples )
428
+ s2_points = (s2_grid [1 :] + s2_grid [:- 1 ])/ 2
429
+ delta_s2 = s2_grid [1 ] - s2_grid [0 ]
430
+
431
+ cos_rnd = np .random .uniform (- 1 , 1 , self .n_samples )
432
+ phi_rnd = np .random .uniform (0.0 , 2 * pi , self .n_samples )
433
+
434
+ # Get particle 1's CM spectra
435
+ for s2 in s2_points :
436
+ t1Max , t1Min = self .t1MaxMin (s , s2 )
437
+ t1_rnd = np .random .uniform (t1Min , t1Max , self .n_samples )
438
+ mc_volume = (t1Max - t1Min )* delta_s2 * 4 * pi / self .n_samples
439
+ for i , t1 in enumerate (t1_rnd ):
440
+ if self .phase_space_heaviside (s , t1 , s2 ) < 1.0 :
441
+ continue
442
+
443
+ weights = self .dsigma_ds2dt1dOmega3 (s , s2 , t1 , cos_rnd [i ], phi_rnd [i ])
444
+ e1_cm = (s + self .m1 ** 2 - s2 )/ (2 * sqrt (s ))
445
+ p1_cm = np .sqrt (e1_cm ** 2 - self .m1 ** 2 )
446
+ theta_b1_cm = arcsin (sqrt (- 4 * s2 * self .cayley_det (s , t1 , s2 , self .ma ** 2 , self .mb ** 2 , self .m1 ** 2 ) \
447
+ / (self .kallen (s2 , self .mb ** 2 , t1 )* self .kallen (s , s2 , self .m1 ** 2 ))))
448
+ lorentz_vector_p1_cm = LorentzVector (e1_cm , p1_cm * sin (theta_b1_cm ), 0.0 , p1_cm * cos (theta_b1_cm ))
449
+
450
+ # Boost to lab frame: use pa velocity assuming pa is at rest
451
+ pa_R23 = self .paR23 (s , t1 , s2 )
452
+ ea_R23 = sqrt (pa_R23 ** 2 + self .ma ** 2 )
453
+ cosTheta_ab_R23 = self .cosTheta_ab (s , s2 , t1 )
454
+ va_R23_3vec = Vector3 (- pa_R23 * sqrt (1 - cosTheta_ab_R23 ** 2 )/ ea_R23 , 0.0 , - pa_R23 * cosTheta_ab_R23 / ea_R23 )
455
+
456
+ lorentz_vector_p1_lab = lorentz_boost (lorentz_vector_p1_cm , va_R23_3vec )
457
+ self .p1_lab_4vectors .append (lorentz_vector_p1_lab )
458
+ self .p1_lab_energies .append (lorentz_vector_p1_lab .p0 )
459
+ self .p1_lab_angles .append (lorentz_vector_p1_lab .theta ())
460
+ self .dsigma .append (weights * mc_volume )
461
+
384
462
385
463
386
464
0 commit comments