MCBooster  1.0.1
Tool to generate MC phase space samples in parallel.
DecayMother.h
Go to the documentation of this file.
1 /*
2  * DecayMother.cuh
3  *
4  * Copyright 2016 Antonio Augusto Alves Junior
5  *
6  * Created on : Feb 25, 2016
7  * Author: Antonio Augusto Alves Junior
8  */
9 
10 /*
11  * This file is part of MCBooster.
12  *
13  * MCBooster is free software: you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation, either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * MCBooster is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with MCBooster. If not, see <http://www.gnu.org/licenses/>.
25  */
26 
27 #ifndef DECAYMOTHER_H_
28 #define DECAYMOTHER_H_
29 
30 #include <mcbooster/Config.h>
31 #include <mcbooster/GTypes.h>
32 #include <mcbooster/GContainers.h>
33 #include <mcbooster/Vector3R.h>
34 #include <mcbooster/Vector4R.h>
35 #include <thrust/tuple.h>
36 #include <thrust/iterator/zip_iterator.h>
37 #include <thrust/random.h>
38 
39 using namespace std;
40 
41 namespace MCBooster
42 {
43 
45 {
46  const GInt_t fSeed;
53 
54 
55  const GReal_t* __restrict__ fMasses;
56 
57  //constructor
58  DecayMother(const Vector4R mother,
59  const mc_device_vector<GReal_t>& _masses,
60  const GInt_t _ndaughters, const GInt_t _seed):
61  fMasses(thrust::raw_pointer_cast(_masses.data())),
62  fNDaughters(_ndaughters),
63  fSeed(_seed)
64 
65  {
66 
67  GReal_t _fTeCmTm = mother.mass(); // total energy in C.M. minus the sum of the masses
68 
69  for (size_t n = 0; n < fNDaughters; n++)
70  {
71  _fTeCmTm -= _masses.data()[n];
72  }
73 
74  GReal_t emmax = _fTeCmTm + _masses.data()[0];
75  GReal_t emmin = 0.0;
76  GReal_t wtmax = 1.0;
77  for (size_t n = 1; n < fNDaughters; n++)
78  {
79  emmin += _masses.data()[n - 1];
80  emmax += _masses.data()[n];
81  wtmax *= pdk(emmax, emmin, _masses.data()[n]);
82  }
83  GReal_t _fWtMax = 1.0 / wtmax;
84 
85  GReal_t _beta = mother.d3mag() / mother.get(0);
86 
87  if (_beta)
88  {
89  GReal_t w = _beta / mother.d3mag();
90  fBeta0 = mother.get(0) * w;
91  fBeta1 = mother.get(1) * w;
92  fBeta2 = mother.get(2) * w;
93  }
94  else
95  fBeta0 = fBeta1 = fBeta2 = 0.0;
96 
97  fTeCmTm = _fTeCmTm;
98  fWtMax = _fWtMax;
99 
100 
101  }
102 
103  __host__ __device__ GReal_t pdk(const GReal_t a, const GReal_t b,
104  const GReal_t c) const
105  {
106  //the PDK function
107  GReal_t x = (a - b - c) * (a + b + c) * (a - b + c) * (a + b - c);
108  x = sqrt(x) / (2 * a);
109  return x;
110  }
111 
112  __host__ __device__ void bbsort( GReal_t *array, GInt_t n)
113  {
114  // Improved bubble sort
115 
116  for (GInt_t c = 0; c < n; c++)
117  {
118  GInt_t nswap = 0;
119 
120  for (GInt_t d = 0; d < n - c - 1; d++)
121  {
122  if (array[d] > array[d + 1]) /* For decreasing order use < */
123  {
124  GReal_t swap = array[d];
125  array[d] = array[d + 1];
126  array[d + 1] = swap;
127  nswap++;
128  }
129  }
130  if (nswap == 0)
131  break;
132  }
133 
134  }
135 
136  __host__ __device__ GUInt_t hash(GUInt_t a)
137  {
138  a = (a + 0x7ed55d16) + (a << 12);
139  a = (a ^ 0xc761c23c) ^ (a >> 19);
140  a = (a + 0x165667b1) + (a << 5);
141  a = (a + 0xd3a2646c) ^ (a << 9);
142  a = (a + 0xfd7046c5) + (a << 3);
143  a = (a ^ 0xb55a4f09) ^ (a >> 16);
144  return a;
145  }
146 
147  __host__ __device__ GReal_t process(const GInt_t evt, Vector4R** daugters)
148  {
149 
150  thrust::random::default_random_engine randEng( hash(evt)*fSeed);
151  thrust::uniform_real_distribution<GReal_t> uniDist(0.0, 1.0);
152 
153  GReal_t rno[kMAXP];
154  rno[0] = 0.0;
155  rno[fNDaughters - 1] = 1.0;
156 
157  if (fNDaughters > 2)
158  {
159  #pragma unroll 9
160  for (GInt_t n = 1; n < fNDaughters - 1; n++)
161  {
162  rno[n] = uniDist(randEng) ;
163 
164  }
165 
166  bbsort(&rno[1], fNDaughters -2);
167 
168  }
169 
170 
171  GReal_t invMas[kMAXP], sum = 0.0;
172 
173  #pragma unroll 9
174  for (size_t n = 0; n < fNDaughters; n++)
175  {
176  sum += fMasses[n];
177  invMas[n] = rno[n] * fTeCmTm + sum;
178  }
179 
180  //
181  //-----> compute the weight of the current event
182  //
183 
184  GReal_t wt = fWtMax;
185 
186  GReal_t pd[kMAXP];
187 
188  #pragma unroll 9
189  for (size_t n = 0; n < fNDaughters - 1; n++)
190  {
191  pd[n] = pdk(invMas[n + 1], invMas[n], fMasses[n + 1]);
192  wt *= pd[n];
193  }
194 
195  //
196  //-----> complete specification of event (Raubold-Lynch method)
197  //
198 
199  daugters[0]->set(sqrt((GReal_t) pd[0] * pd[0] + fMasses[0] * fMasses[0]), 0.0,
200  pd[0], 0.0);
201 
202  #pragma unroll 9
203  for (size_t i = 1; i < fNDaughters; i++)
204  {
205 
206  daugters[i]->set(
207  sqrt(pd[i - 1] * pd[i - 1] + fMasses[i] * fMasses[i]), 0.0,
208  -pd[i - 1], 0.0);
209 
210  GReal_t cZ = 2 * uniDist(randEng) -1 ;
211  GReal_t sZ = sqrt(1 - cZ * cZ);
212  GReal_t angY = 2 * PI* uniDist(randEng);
213  GReal_t cY = cos(angY);
214  GReal_t sY = sin(angY);
215  for (size_t j = 0; j <= i; j++)
216  {
217 
218  GReal_t x = daugters[j]->get(1);
219  GReal_t y = daugters[j]->get(2);
220  daugters[j]->set(1, cZ * x - sZ * y);
221  daugters[j]->set(2, sZ * x + cZ * y); // rotation around Z
222 
223  x = daugters[j]->get(1);
224  GReal_t z = daugters[j]->get(3);
225  daugters[j]->set(1, cY * x - sY * z);
226  daugters[j]->set(3, sY * x + cY * z); // rotation around Y
227  }
228 
229  if (i == (fNDaughters - 1))
230  break;
231 
232  GReal_t beta = pd[i] / sqrt(pd[i] * pd[i] + invMas[i] * invMas[i]);
233  for (size_t j = 0; j <= i; j++)
234  {
235 
236  daugters[j]->applyBoostTo(Vector3R(0, beta, 0));
237  }
238 
239  }
240 
241  //
242  //---> final boost of all particles to the mother's frame
243  //
244  #pragma unroll 9
245  for (size_t n = 0; n < fNDaughters; n++)
246  {
247 
248  daugters[n]->applyBoostTo(Vector3R(fBeta0, fBeta1, fBeta2));
249 
250  }
251 
252  //
253  //---> return the weight of event
254  //
255 
256  return wt;
257 
258  }
259 
260  __host__ __device__ GReal_t operator()(const GInt_t evt, GT2 &particles)
261  {
262  Vector4R* _Particles[2];
263 
264  _Particles[0] = &thrust::get<0>(particles);
265  _Particles[1] = &thrust::get<1>(particles);
266 
267  return process(evt, _Particles);
268 
269  }
270 
271  __host__ __device__ GReal_t operator()(const GInt_t evt, GT3 &particles)
272  {
273  Vector4R* _Particles[3];
274 
275  _Particles[0] = &thrust::get<0>(particles);
276  _Particles[1] = &thrust::get<1>(particles);
277  _Particles[2] = &thrust::get<2>(particles);
278 
279  return process(evt, _Particles);
280 
281  }
282 
283  __host__ __device__ GReal_t operator()(const GInt_t evt, GT4 &particles)
284  {
285 
286  Vector4R* _Particles[4];
287 
288  _Particles[0] = &thrust::get<0>(particles);
289  _Particles[1] = &thrust::get<1>(particles);
290  _Particles[2] = &thrust::get<2>(particles);
291  _Particles[3] = &thrust::get<3>(particles);
292 
293  return process(evt, _Particles);
294 
295  }
296 
297  __host__ __device__ GReal_t operator()(const GInt_t evt, GT5 &particles)
298  {
299  Vector4R* _Particles[5];
300 
301  _Particles[0] = &thrust::get<0>(particles);
302  _Particles[1] = &thrust::get<1>(particles);
303  _Particles[2] = &thrust::get<2>(particles);
304  _Particles[3] = &thrust::get<3>(particles);
305  _Particles[4] = &thrust::get<4>(particles);
306 
307  return process(evt, _Particles);
308 
309  }
310 
311  __host__ __device__ GReal_t operator()(const GInt_t evt, GT6 &particles)
312  {
313  Vector4R* _Particles[6];
314 
315  _Particles[0] = &thrust::get<0>(particles);
316  _Particles[1] = &thrust::get<1>(particles);
317  _Particles[2] = &thrust::get<2>(particles);
318  _Particles[3] = &thrust::get<3>(particles);
319  _Particles[4] = &thrust::get<4>(particles);
320  _Particles[5] = &thrust::get<5>(particles);
321 
322  return process(evt, _Particles);
323 
324  }
325 
326  __host__ __device__ GReal_t operator()(const GInt_t evt, GT7 &particles)
327  {
328  Vector4R* _Particles[7];
329 
330  _Particles[0] = &thrust::get<0>(particles);
331  _Particles[1] = &thrust::get<1>(particles);
332  _Particles[2] = &thrust::get<2>(particles);
333  _Particles[3] = &thrust::get<3>(particles);
334  _Particles[4] = &thrust::get<4>(particles);
335  _Particles[5] = &thrust::get<5>(particles);
336  _Particles[6] = &thrust::get<6>(particles);
337 
338  return process(evt, _Particles);
339 
340  }
341 
342  __host__ __device__ GReal_t operator()(const GInt_t evt, GT8 &particles)
343  {
344  Vector4R* _Particles[8];
345 
346  _Particles[0] = &thrust::get<0>(particles);
347  _Particles[1] = &thrust::get<1>(particles);
348  _Particles[2] = &thrust::get<2>(particles);
349  _Particles[3] = &thrust::get<3>(particles);
350  _Particles[4] = &thrust::get<4>(particles);
351  _Particles[5] = &thrust::get<5>(particles);
352  _Particles[6] = &thrust::get<6>(particles);
353  _Particles[7] = &thrust::get<7>(particles);
354 
355  return process(evt, _Particles);
356 
357  }
358 
359  __host__ __device__ GReal_t operator()(const GInt_t evt, GT9 &particles)
360  {
361  Vector4R* _Particles[9];
362 
363  _Particles[0] = &thrust::get<0>(particles);
364  _Particles[1] = &thrust::get<1>(particles);
365  _Particles[2] = &thrust::get<2>(particles);
366  _Particles[3] = &thrust::get<3>(particles);
367  _Particles[4] = &thrust::get<4>(particles);
368  _Particles[5] = &thrust::get<5>(particles);
369  _Particles[6] = &thrust::get<6>(particles);
370  _Particles[7] = &thrust::get<7>(particles);
371  _Particles[8] = &thrust::get<8>(particles);
372 
373  return process(evt, _Particles);
374 
375  }
376 
377  __host__ __device__ GReal_t operator()(const GInt_t evt, GT10 &particles)
378  {
379  Vector4R* _Particles[10];
380 
381  _Particles[0] = &thrust::get<0>(particles);
382  _Particles[1] = &thrust::get<1>(particles);
383  _Particles[2] = &thrust::get<2>(particles);
384  _Particles[3] = &thrust::get<3>(particles);
385  _Particles[4] = &thrust::get<4>(particles);
386  _Particles[5] = &thrust::get<5>(particles);
387  _Particles[6] = &thrust::get<6>(particles);
388  _Particles[7] = &thrust::get<7>(particles);
389  _Particles[8] = &thrust::get<8>(particles);
390  _Particles[9] = &thrust::get<9>(particles);
391 
392  return process(evt, _Particles);
393 
394  }
395 };
396 
397 }
398 
399 #endif /* DECAYMOTHER_H_ */
thrust::detail::tuple_of_iterator_references< Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type > GT5
GT5 iterator is a typedef for thrust::detail::tuple_of_iterator_references
Definition: GContainers.h:148
__host__ __device__ GReal_t get(GInt_t i) const
Definition: Vector4R.h:231
thrust::detail::tuple_of_iterator_references< Vector4R &, Vector4R &, Vector4R &, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type > GT3
GT3 iterator is a typedef for thrust::detail::tuple_of_iterator_references
Definition: GContainers.h:136
const GInt_t fNDaughters
Definition: DecayMother.h:47
__host__ __device__ GReal_t process(const GInt_t evt, Vector4R **daugters)
Definition: DecayMother.h:147
unsigned int GUInt_t
Unsigned integer 4 bytes (unsigned int)
Definition: GTypes.h:38
__host__ __device__ GReal_t operator()(const GInt_t evt, GT7 &particles)
Definition: DecayMother.h:326
__host__ __device__ GReal_t d3mag() const
Definition: Vector4R.h:504
STL namespace.
Typedef for useful container classes used in MCBooster.
__host__ __device__ GReal_t operator()(const GInt_t evt, GT9 &particles)
Definition: DecayMother.h:359
thrust::detail::tuple_of_iterator_references< Vector4R &, Vector4R &, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type > GT2
GT2 iterator is a typedef for thrust::detail::tuple_of_iterator_references
Definition: GContainers.h:130
thrust::detail::tuple_of_iterator_references< Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, thrust::null_type > GT9
GT9 iterator is a typedef for thrust::detail::tuple_of_iterator_references
Definition: GContainers.h:170
#define kMAXP
Definition: GTypes.h:65
__host__ __device__ GReal_t operator()(const GInt_t evt, GT6 &particles)
Definition: DecayMother.h:311
__host__ __device__ GReal_t operator()(const GInt_t evt, GT2 &particles)
Definition: DecayMother.h:260
thrust::detail::tuple_of_iterator_references< Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R & > GT10
GT10 iterator is a typedef for thrust::detail::tuple_of_iterator_references
Definition: GContainers.h:175
__host__ __device__ GReal_t operator()(const GInt_t evt, GT8 &particles)
Definition: DecayMother.h:342
const GInt_t fSeed
Definition: DecayMother.h:46
#define PI
Definition: GTypes.h:66
__host__ __device__ void set(GInt_t i, GReal_t d)
Definition: Vector4R.h:236
thrust::detail::tuple_of_iterator_references< Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, thrust::null_type, thrust::null_type, thrust::null_type > GT7
GT7 iterator is a typedef for thrust::detail::tuple_of_iterator_references
Definition: GContainers.h:159
__host__ __device__ GReal_t operator()(const GInt_t evt, GT4 &particles)
Definition: DecayMother.h:283
double GReal_t
Double 8 bytes or float 4 bytes.
Definition: GTypes.h:52
__host__ __device__ void applyBoostTo(const Vector4R &p4, bool inverse=false)
Definition: Vector4R.h:355
thrust::detail::tuple_of_iterator_references< Vector4R &, Vector4R &, Vector4R &, Vector4R &, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type > GT4
GT4 iterator is a typedef for thrust::detail::tuple_of_iterator_references
Definition: GContainers.h:142
__host__ __device__ GReal_t operator()(const GInt_t evt, GT3 &particles)
Definition: DecayMother.h:271
int GInt_t
Signed integer 4 bytes (int)
Definition: GTypes.h:37
thrust::host_vector< T > mc_device_vector
Generic template typedef for thrust::host_vector.
Definition: GContainers.h:60
__host__ __device__ GReal_t operator()(const GInt_t evt, GT10 &particles)
Definition: DecayMother.h:377
__host__ __device__ GUInt_t hash(GUInt_t a)
Definition: DecayMother.h:136
DecayMother(const Vector4R mother, const mc_device_vector< GReal_t > &_masses, const GInt_t _ndaughters, const GInt_t _seed)
Definition: DecayMother.h:58
__host__ __device__ GReal_t operator()(const GInt_t evt, GT5 &particles)
Definition: DecayMother.h:297
const GReal_t *__restrict__ fMasses
Definition: DecayMother.h:55
__host__ __device__ GReal_t mass() const
Definition: Vector4R.h:280
thrust::detail::tuple_of_iterator_references< Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, thrust::null_type, thrust::null_type, thrust::null_type, thrust::null_type > GT6
GT6 iterator is a typedef for thrust::detail::tuple_of_iterator_references
Definition: GContainers.h:154
thrust::detail::tuple_of_iterator_references< Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, Vector4R &, thrust::null_type, thrust::null_type > GT8
GT8 iterator is a typedef for thrust::detail::tuple_of_iterator_references
Definition: GContainers.h:164
__host__ __device__ GReal_t pdk(const GReal_t a, const GReal_t b, const GReal_t c) const
Definition: DecayMother.h:103
__host__ __device__ void bbsort(GReal_t *array, GInt_t n)
Definition: DecayMother.h:112