GooFit  v2.1.3
ResonancePdf.cu
Go to the documentation of this file.
1 #include <goofit/PDFs/detail/ComplexUtils.h>
2 #include <goofit/PDFs/physics/DalitzPlotHelpers.h>
3 #include <goofit/PDFs/physics/ResonancePdf.h>
4 
5 namespace GooFit {
6 
7 __device__ fptype cDeriatives[2 * MAXNKNOBS];
8 
9 __device__ fptype twoBodyCMmom(double rMassSq, fptype d1m, fptype d2m) {
10  // For A -> B + C, calculate momentum of B and C in rest frame of A.
11  // PDG 38.16.
12 
13  fptype kin1 = 1 - POW2(d1m + d2m) / rMassSq;
14 
15  kin1 = kin1 >= 0 ? sqrt(kin1) : 1;
16 
17  fptype kin2 = 1 - POW2(d1m - d2m) / rMassSq;
18  kin2 = kin2 >= 0 ? sqrt(kin2) : 1;
19 
20  return 0.5 * sqrt(rMassSq) * kin1 * kin2;
21 }
22 
23 __device__ fptype dampingFactorSquare(const fptype &cmmom, const int &spin, const fptype &mRadius) {
24  fptype square = mRadius * mRadius * cmmom * cmmom;
25  fptype dfsq = 1 + square; // This accounts for spin 1
26  // if (2 == spin) dfsq += 8 + 2*square + square*square; // Coefficients are 9, 3, 1.
27  fptype dfsqres = dfsq + 8 + 2 * square + square * square;
28 
29  // Spin 3 and up not accounted for.
30  // return dfsq;
31  return (spin == 2) ? dfsqres : dfsq;
32 }
33 
34 __device__ fptype spinFactor(unsigned int spin,
35  fptype motherMass,
36  fptype daug1Mass,
37  fptype daug2Mass,
38  fptype daug3Mass,
39  fptype m12,
40  fptype m13,
41  fptype m23,
42  unsigned int cyclic_index) {
43  if(0 == spin)
44  return 1; // Should not cause branching since every thread evaluates the same resonance at the same time.
45 
46  /*
47  // Copied from BdkDMixDalitzAmp
48 
49  fptype _mA = (PAIR_12 == cyclic_index ? daug1Mass : (PAIR_13 == cyclic_index ? daug1Mass : daug3Mass));
50  fptype _mB = (PAIR_12 == cyclic_index ? daug2Mass : (PAIR_13 == cyclic_index ? daug3Mass : daug3Mass));
51  fptype _mC = (PAIR_12 == cyclic_index ? daug3Mass : (PAIR_13 == cyclic_index ? daug2Mass : daug1Mass));
52 
53  fptype _mAC = (PAIR_12 == cyclic_index ? m13 : (PAIR_13 == cyclic_index ? m12 : m12));
54  fptype _mBC = (PAIR_12 == cyclic_index ? m23 : (PAIR_13 == cyclic_index ? m23 : m13));
55  fptype _mAB = (PAIR_12 == cyclic_index ? m12 : (PAIR_13 == cyclic_index ? m13 : m23));
56 
57  // The above, collapsed into single tests where possible.
58  fptype _mA = (PAIR_13 == cyclic_index ? daug3Mass : daug2Mass);
59  fptype _mB = (PAIR_23 == cyclic_index ? daug2Mass : daug1Mass);
60  fptype _mC = (PAIR_12 == cyclic_index ? daug3Mass : (PAIR_13 == cyclic_index ? daug2Mass : daug1Mass));
61 
62  fptype _mAC = (PAIR_23 == cyclic_index ? m13 : m23);
63  fptype _mBC = (PAIR_12 == cyclic_index ? m13 : m12);
64  fptype _mAB = (PAIR_12 == cyclic_index ? m12 : (PAIR_13 == cyclic_index ? m13 : m23));
65  */
66 
67  // Copied from EvtDalitzReso, with assumption that pairAng convention matches pipipi0 from EvtD0mixDalitz.
68  // Again, all threads should get the same branch.
69  fptype _mA = (PAIR_12 == cyclic_index ? daug1Mass : (PAIR_13 == cyclic_index ? daug3Mass : daug2Mass));
70  fptype _mB = (PAIR_12 == cyclic_index ? daug2Mass : (PAIR_13 == cyclic_index ? daug1Mass : daug3Mass));
71  fptype _mC = (PAIR_12 == cyclic_index ? daug3Mass : (PAIR_13 == cyclic_index ? daug2Mass : daug1Mass));
72  fptype _mAC = (PAIR_12 == cyclic_index ? m13 : (PAIR_13 == cyclic_index ? m23 : m12));
73  fptype _mBC = (PAIR_12 == cyclic_index ? m23 : (PAIR_13 == cyclic_index ? m12 : m13));
74  fptype _mAB = (PAIR_12 == cyclic_index ? m12 : (PAIR_13 == cyclic_index ? m13 : m23));
75 
76  fptype massFactor = 1.0 / _mAB;
77  fptype sFactor = -1;
78  sFactor *= ((_mBC - _mAC) + (massFactor * (motherMass * motherMass - _mC * _mC) * (_mA * _mA - _mB * _mB)));
79 
80  if(2 == spin) {
81  sFactor *= sFactor;
82  fptype extraterm = ((_mAB - (2 * motherMass * motherMass) - (2 * _mC * _mC))
83  + massFactor * POW2(motherMass * motherMass - _mC * _mC));
84  extraterm *= ((_mAB - (2 * _mA * _mA) - (2 * _mB * _mB)) + massFactor * POW2(_mA * _mA - _mB * _mB));
85  extraterm /= 3;
86  sFactor -= extraterm;
87  }
88 
89  return sFactor;
90 }
91 
92 template <int I>
93 __device__ fpcomplex plainBW(fptype m12, fptype m13, fptype m23, unsigned int *indices) {
94  fptype motherMass = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 0]);
95  fptype daug1Mass = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 1]);
96  fptype daug2Mass = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 2]);
97  fptype daug3Mass = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 3]);
98  fptype meson_radius = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 4]);
99 
100  fptype resmass = RO_CACHE(cudaArray[RO_CACHE(indices[2])]);
101  fptype reswidth = RO_CACHE(cudaArray[RO_CACHE(indices[3])]);
102  unsigned int spin = RO_CACHE(indices[4]);
103  unsigned int cyclic_index = RO_CACHE(indices[5]);
104 
105  fpcomplex result{0.0, 0.0};
106  fptype resmass2 = POW2(resmass);
107 
108 #pragma unroll
109  for(size_t i = 0; i < I; i++) {
110  fptype rMassSq = (PAIR_12 == cyclic_index ? m12 : (PAIR_13 == cyclic_index ? m13 : m23));
111  fptype mass_daug1 = (PAIR_23 == cyclic_index ? daug2Mass : daug1Mass);
112  fptype mass_daug2 = (PAIR_12 == cyclic_index ? daug2Mass : daug3Mass);
113 
114  fptype frFactor = 1;
115 
116  // Calculate momentum of the two daughters in the resonance rest frame
117  // Note symmetry under interchange (dm1 <-> dm2)
118 
119  fptype measureDaughterMoms = twoBodyCMmom(rMassSq, mass_daug1, mass_daug2);
120  fptype nominalDaughterMoms = twoBodyCMmom(resmass2, mass_daug1, mass_daug2);
121 
122  if(0 != spin) {
123  frFactor = dampingFactorSquare(nominalDaughterMoms, spin, meson_radius)
124  / dampingFactorSquare(measureDaughterMoms, spin, meson_radius);
125  }
126 
127  // RBW evaluation
128  fptype A = (resmass2 - rMassSq);
129  fptype B = resmass2 * reswidth * pow(measureDaughterMoms / nominalDaughterMoms, 2.0 * spin + 1) * frFactor
130  / sqrt(rMassSq);
131  fptype C = 1.0 / (POW2(A) + POW2(B));
132 
133  fpcomplex ret(A * C, B * C); // Dropping F_D=1
134 
135  ret *= sqrt(frFactor);
136  ret *= spinFactor(spin, motherMass, daug1Mass, daug2Mass, daug3Mass, m12, m13, m23, cyclic_index);
137 
138  result += ret;
139 
140  if(I > 1) {
141  cyclic_index = cyclic_index + 1 % 3;
142  }
143  }
144  return result;
145 }
146 
147 __device__ fpcomplex gaussian(fptype m12, fptype m13, fptype m23, unsigned int *indices) {
148  // indices[1] is unused constant index, for consistency with other function types.
149  fptype resmass = RO_CACHE(cudaArray[RO_CACHE(indices[2])]);
150  fptype reswidth = RO_CACHE(cudaArray[RO_CACHE(indices[3])]);
151  unsigned int cyclic_index = indices[4];
152 
153  // Notice sqrt - this function uses mass, not mass-squared like the other resonance types.
154  fptype massToUse = sqrt(PAIR_12 == cyclic_index ? m12 : (PAIR_13 == cyclic_index ? m13 : m23));
155  massToUse -= resmass;
156  massToUse /= reswidth;
157  massToUse *= massToUse;
158  fptype ret = exp(-0.5 * massToUse);
159 
160  // Ignore factor 1/sqrt(2pi).
161  ret /= reswidth;
162 
163  return {ret, 0};
164 }
165 
166 __device__ fptype hFun(double s, double daug2Mass, double daug3Mass) {
167  // Last helper function
168  const fptype _pi = 3.14159265359;
169  double sm = daug2Mass + daug3Mass;
170  double sqrt_s = sqrt(s);
171  double k_s = twoBodyCMmom(s, daug2Mass, daug3Mass);
172 
173  return ((2 / _pi) * (k_s / sqrt_s) * log((sqrt_s + 2 * k_s) / (sm)));
174 }
175 
176 __device__ fptype dh_dsFun(double s, double daug2Mass, double daug3Mass) {
177  // Yet another helper function
178  const fptype _pi = 3.14159265359;
179  double k_s = twoBodyCMmom(s, daug2Mass, daug3Mass);
180 
181  return hFun(s, daug2Mass, daug3Mass) * (1.0 / (8.0 * POW2(k_s)) - 1.0 / (2.0 * s)) + 1.0 / (2.0 * _pi * s);
182 }
183 
184 __device__ fptype dFun(double s, double daug2Mass, double daug3Mass) {
185  // Helper function used in Gronau-Sakurai
186  const fptype _pi = 3.14159265359;
187  double sm = daug2Mass + daug3Mass;
188  double sm24 = sm * sm / 4.0;
189  double m = sqrt(s);
190  double k_m2 = twoBodyCMmom(s, daug2Mass, daug3Mass);
191 
192  return 3.0 / _pi * sm24 / POW2(k_m2) * log((m + 2 * k_m2) / sm) + m / (2 * _pi * k_m2)
193  - sm24 * m / (_pi * POW3(k_m2));
194 }
195 
196 __device__ fptype fsFun(double s, double m2, double gam, double daug2Mass, double daug3Mass) {
197  // Another G-S helper function
198 
199  double k_s = twoBodyCMmom(s, daug2Mass, daug3Mass);
200  double k_Am2 = twoBodyCMmom(m2, daug2Mass, daug3Mass);
201 
202  double f = gam * m2 / POW3(k_Am2);
203  f *= (POW2(k_s) * (hFun(s, daug2Mass, daug3Mass) - hFun(m2, daug2Mass, daug3Mass))
204  + (m2 - s) * POW2(k_Am2) * dh_dsFun(m2, daug2Mass, daug3Mass));
205 
206  return f;
207 }
208 
209 __device__ fpcomplex gouSak(fptype m12, fptype m13, fptype m23, unsigned int *indices) {
210  fptype motherMass = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 0]);
211  fptype daug1Mass = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 1]);
212  fptype daug2Mass = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 2]);
213  fptype daug3Mass = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 3]);
214  fptype meson_radius = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 4]);
215 
216  fptype resmass = RO_CACHE(cudaArray[RO_CACHE(indices[2])]);
217  fptype reswidth = RO_CACHE(cudaArray[RO_CACHE(indices[3])]);
218  unsigned int spin = RO_CACHE(indices[4]);
219  unsigned int cyclic_index = RO_CACHE(indices[5]);
220 
221  fptype rMassSq = (PAIR_12 == cyclic_index ? m12 : (PAIR_13 == cyclic_index ? m13 : m23));
222  fptype frFactor = 1;
223 
224  resmass *= resmass;
225  // Calculate momentum of the two daughters in the resonance rest frame; note symmetry under interchange (dm1 <->
226  // dm2).
227  fptype measureDaughterMoms = twoBodyCMmom(
228  rMassSq, (PAIR_23 == cyclic_index ? daug2Mass : daug1Mass), (PAIR_12 == cyclic_index ? daug2Mass : daug3Mass));
229  fptype nominalDaughterMoms = twoBodyCMmom(
230  resmass, (PAIR_23 == cyclic_index ? daug2Mass : daug1Mass), (PAIR_12 == cyclic_index ? daug2Mass : daug3Mass));
231 
232  if(0 != spin) {
233  frFactor = dampingFactorSquare(nominalDaughterMoms, spin, meson_radius);
234  frFactor /= dampingFactorSquare(measureDaughterMoms, spin, meson_radius);
235  }
236 
237  // Implement Gou-Sak:
238 
239  fptype D = (1.0 + dFun(resmass, daug2Mass, daug3Mass) * reswidth / sqrt(resmass));
240  fptype E = resmass - rMassSq + fsFun(rMassSq, resmass, reswidth, daug2Mass, daug3Mass);
241  fptype F = sqrt(resmass) * reswidth * pow(measureDaughterMoms / nominalDaughterMoms, 2.0 * spin + 1) * frFactor;
242 
243  D /= (E * E + F * F);
244  fpcomplex retur(D * E, D * F); // Dropping F_D=1
245  retur *= sqrt(frFactor);
246  retur *= spinFactor(spin, motherMass, daug1Mass, daug2Mass, daug3Mass, m12, m13, m23, cyclic_index);
247 
248  return retur;
249 }
250 
251 __device__ fpcomplex lass(fptype m12, fptype m13, fptype m23, unsigned int *indices) {
252  fptype motherMass = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 0]);
253  fptype daug1Mass = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 1]);
254  fptype daug2Mass = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 2]);
255  fptype daug3Mass = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 3]);
256  fptype meson_radius = RO_CACHE(functorConstants[RO_CACHE(indices[1]) + 4]);
257 
258  fptype resmass = RO_CACHE(cudaArray[RO_CACHE(indices[2])]);
259  fptype reswidth = RO_CACHE(cudaArray[RO_CACHE(indices[3])]);
260  unsigned int spin = RO_CACHE(indices[4]);
261  unsigned int cyclic_index = RO_CACHE(indices[5]);
262 
263  fptype rMassSq = (PAIR_12 == cyclic_index ? m12 : (PAIR_13 == cyclic_index ? m13 : m23));
264  fptype frFactor = 1;
265 
266  resmass *= resmass;
267  // Calculate momentum of the two daughters in the resonance rest frame; note symmetry under interchange (dm1 <->
268  // dm2).
269 
270  fptype measureDaughterMoms = twoBodyCMmom(
271  rMassSq, (PAIR_23 == cyclic_index ? daug2Mass : daug1Mass), (PAIR_23 == cyclic_index ? daug3Mass : daug2Mass));
272  fptype nominalDaughterMoms = twoBodyCMmom(
273  resmass, (PAIR_23 == cyclic_index ? daug2Mass : daug1Mass), (PAIR_23 == cyclic_index ? daug3Mass : daug2Mass));
274 
275  if(0 != spin) {
276  frFactor = dampingFactorSquare(nominalDaughterMoms, spin, meson_radius);
277  frFactor /= dampingFactorSquare(measureDaughterMoms, spin, meson_radius);
278  }
279 
280  // Implement LASS:
281  /*
282  fptype s = kinematics(m12, m13, _trackinfo[i]);
283  fptype q = twoBodyCMmom(s, _trackinfo[i]);
284  fptype m0 = _massRes[i]->getValFast();
285  fptype _g0 = _gammaRes[i]->getValFast();
286  int spin = _spinRes[i];
287  fptype g = runningWidthFast(s, m0, _g0, spin, _trackinfo[i], FrEval(s, m0, _trackinfo[i], spin));
288  */
289 
290  fptype q = measureDaughterMoms;
291  fptype g = reswidth * pow(measureDaughterMoms / nominalDaughterMoms, 2.0 * spin + 1) * frFactor / sqrt(rMassSq);
292 
293  fptype _a = 0.22357;
294  fptype _r = -15.042;
295  fptype _R = 1; // ?
296  fptype _phiR = 1.10644;
297  fptype _B = 0.614463;
298  fptype _phiB = -0.0981907;
299 
300  // background phase motion
301  fptype cot_deltaB = (1.0 / (_a * q)) + 0.5 * _r * q;
302  fptype qcot_deltaB = (1.0 / _a) + 0.5 * _r * q * q;
303 
304  // calculate resonant part
305  fpcomplex expi2deltaB = fpcomplex(qcot_deltaB, q) / fpcomplex(qcot_deltaB, -q);
306  fpcomplex resT = fpcomplex(cos(_phiR + 2 * _phiB), sin(_phiR + 2 * _phiB)) * _R;
307 
308  fpcomplex prop = fpcomplex(1, 0) / fpcomplex(resmass - rMassSq, sqrt(resmass) * g);
309  // resT *= prop*m0*_g0*m0/twoBodyCMmom(m0*m0, _trackinfo[i])*expi2deltaB;
310  resT *= prop * (resmass * reswidth / nominalDaughterMoms) * expi2deltaB;
311 
312  // calculate bkg part
313  resT += fpcomplex(cos(_phiB), sin(_phiB)) * _B * (cos(_phiB) + cot_deltaB * sin(_phiB)) * sqrt(rMassSq)
314  / fpcomplex(qcot_deltaB, -q);
315 
316  resT *= sqrt(frFactor);
317  resT *= spinFactor(spin, motherMass, daug1Mass, daug2Mass, daug3Mass, m12, m13, m23, cyclic_index);
318 
319  return resT;
320 }
321 
322 __device__ fpcomplex nonres(fptype m12, fptype m13, fptype m23, unsigned int *indices) { return {1., 0.}; }
323 
324 __device__ void
325 getAmplitudeCoefficients(fpcomplex a1, fpcomplex a2, fptype &a1sq, fptype &a2sq, fptype &a1a2real, fptype &a1a2imag) {
326  // Returns A_1^2, A_2^2, real and imaginary parts of A_1A_2^*
327  a1sq = thrust::norm(a1);
328  a2sq = thrust::norm(a2);
329  a1 *= conj(a2);
330  a1a2real = a1.real();
331  a1a2imag = a1.imag();
332 }
333 
334 __device__ fpcomplex flatte(fptype m12, fptype m13, fptype m23, unsigned int *indices) {
335  // indices[1] is unused constant index, for consistency with other function types.
336  fptype resmass = cudaArray[indices[2]];
337  fptype g1 = cudaArray[indices[3]];
338  fptype g2 = cudaArray[indices[4]] * g1;
339  unsigned int cyclic_index = indices[5];
340  unsigned int doSwap = indices[6];
341 
342  fptype pipmass = 0.13957018;
343  fptype pi0mass = 0.1349766;
344  fptype kpmass = 0.493677;
345  fptype k0mass = 0.497614;
346 
347  fptype twopimasssq = 4 * pipmass * pipmass;
348  fptype twopi0masssq = 4 * pi0mass * pi0mass;
349  fptype twokmasssq = 4 * kpmass * kpmass;
350  fptype twok0masssq = 4 * k0mass * k0mass;
351 
352  fpcomplex ret(0., 0.);
353  for(int i = 0; i < 1 + doSwap; i++) {
354  fptype rhopipi_real = 0, rhopipi_imag = 0;
355  fptype rhokk_real = 0, rhokk_imag = 0;
356 
357  fptype s = (PAIR_12 == cyclic_index ? m12 : (PAIR_13 == cyclic_index ? m13 : m23));
358 
359  if(s >= twopimasssq)
360  rhopipi_real += (2. / 3) * sqrt(1 - twopimasssq / s); // Above pi+pi- threshold
361  else
362  rhopipi_imag += (2. / 3) * sqrt(-1 + twopimasssq / s);
363  if(s >= twopi0masssq)
364  rhopipi_real += (1. / 3) * sqrt(1 - twopi0masssq / s); // Above pi0pi0 threshold
365  else
366  rhopipi_imag += (1. / 3) * sqrt(-1 + twopi0masssq / s);
367  if(s >= twokmasssq)
368  rhokk_real += 0.5 * sqrt(1 - twokmasssq / s); // Above K+K- threshold
369  else
370  rhokk_imag += 0.5 * sqrt(-1 + twokmasssq / s);
371  if(s >= twok0masssq)
372  rhokk_real += 0.5 * sqrt(1 - twok0masssq / s); // Above K0K0 threshold
373  else
374  rhokk_imag += 0.5 * sqrt(-1 + twok0masssq / s);
375  fptype A = (resmass * resmass - s) + resmass * (rhopipi_imag * g1 + rhokk_imag * g2);
376  fptype B = resmass * (rhopipi_real * g1 + rhokk_real * g2);
377  fptype C = 1.0 / (A * A + B * B);
378  fpcomplex retur(A * C, B * C);
379  ret += retur;
380  if(doSwap) {
381  fptype swpmass = m12;
382  m12 = m13;
383  m13 = swpmass;
384  }
385  }
386 
387  return ret;
388 }
389 
390 __device__ fpcomplex cubicspline(fptype m12, fptype m13, fptype m23, unsigned int *indices) {
391  fpcomplex ret(0, 0);
392  unsigned int cyclic_index = indices[2];
393  unsigned int doSwap = indices[3];
394  const unsigned int nKnobs = indices[4];
395  unsigned int idx = 5; // Next index
396  unsigned int i = 0;
397  const unsigned int pwa_coefs_idx = idx;
398  idx += 2 * nKnobs;
399  const fptype *mKKlimits = &(functorConstants[indices[idx]]);
400  fptype mAB = m12, mAC = m13;
401  switch(cyclic_index) {
402  case PAIR_13:
403  mAB = m13;
404  mAC = m12;
405  break;
406  case PAIR_23:
407  mAB = m23;
408  mAC = m12;
409  break;
410  }
411 
412  int khiAB = 0, khiAC = 0;
413  fptype dmKK, aa, bb, aa3, bb3;
414  unsigned int timestorun = 1 + doSwap;
415  while(khiAB < nKnobs) {
416  if(mAB < mKKlimits[khiAB])
417  break;
418  khiAB++;
419  }
420 
421  if(khiAB <= 0 || khiAB == nKnobs)
422  timestorun = 0;
423  while(khiAC < nKnobs) {
424  if(mAC < mKKlimits[khiAC])
425  break;
426  khiAC++;
427  }
428 
429  if(khiAC <= 0 || khiAC == nKnobs)
430  timestorun = 0;
431 
432  for(i = 0; i < timestorun; i++) {
433  unsigned int kloAB = khiAB - 1; //, kloAC = khiAC -1;
434  unsigned int twokloAB = kloAB + kloAB;
435  unsigned int twokhiAB = khiAB + khiAB;
436  fptype pwa_coefs_real_kloAB = cudaArray[indices[pwa_coefs_idx + twokloAB]];
437  fptype pwa_coefs_real_khiAB = cudaArray[indices[pwa_coefs_idx + twokhiAB]];
438  fptype pwa_coefs_imag_kloAB = cudaArray[indices[pwa_coefs_idx + twokloAB + 1]];
439  fptype pwa_coefs_imag_khiAB = cudaArray[indices[pwa_coefs_idx + twokhiAB + 1]];
440  fptype pwa_coefs_prime_real_kloAB = cDeriatives[twokloAB];
441  fptype pwa_coefs_prime_real_khiAB = cDeriatives[twokhiAB];
442  fptype pwa_coefs_prime_imag_kloAB = cDeriatives[twokloAB + 1];
443  fptype pwa_coefs_prime_imag_khiAB = cDeriatives[twokhiAB + 1];
444  // printf("m12: %f: %f %f %f %f %f %f %d %d %d\n", mAB, mKKlimits[0], mKKlimits[nKnobs-1],
445  // pwa_coefs_real_khiAB, pwa_coefs_imag_khiAB, pwa_coefs_prime_real_khiAB, pwa_coefs_prime_imag_khiAB, khiAB,
446  // khiAC, timestorun );
447 
448  dmKK = mKKlimits[khiAB] - mKKlimits[kloAB];
449  aa = (mKKlimits[khiAB] - mAB) / dmKK;
450  bb = 1 - aa;
451  aa3 = aa * aa * aa;
452  bb3 = bb * bb * bb;
453  // ret += aa * pwa_coefs[kloAB] + bb * pwa_coefs[khiAB] + ((aa3 - aa)*pwa_coefs_prime[kloAB] + (bb3 - bb) *
454  // pwa_coefs_prime[khiAB]) * (dmKK*dmKK)/6.0;
455  ret.real(ret.real() + aa * pwa_coefs_real_kloAB + bb * pwa_coefs_real_khiAB
456  + ((aa3 - aa) * pwa_coefs_prime_real_kloAB + (bb3 - bb) * pwa_coefs_prime_real_khiAB) * (dmKK * dmKK)
457  / 6.0);
458  ret.imag(ret.imag() + aa * pwa_coefs_imag_kloAB + bb * pwa_coefs_imag_khiAB
459  + ((aa3 - aa) * pwa_coefs_prime_imag_kloAB + (bb3 - bb) * pwa_coefs_prime_imag_khiAB) * (dmKK * dmKK)
460  / 6.0);
461  khiAB = khiAC;
462  mAB = mAC;
463  }
464  return ret;
465 }
466 
467 __device__ resonance_function_ptr ptr_to_RBW = plainBW<1>;
468 __device__ resonance_function_ptr ptr_to_RBW_Sym = plainBW<2>;
469 __device__ resonance_function_ptr ptr_to_GOUSAK = gouSak;
470 __device__ resonance_function_ptr ptr_to_GAUSSIAN = gaussian;
471 __device__ resonance_function_ptr ptr_to_NONRES = nonres;
472 __device__ resonance_function_ptr ptr_to_LASS = lass;
473 __device__ resonance_function_ptr ptr_to_FLATTE = flatte;
474 __device__ resonance_function_ptr ptr_to_SPLINE = cubicspline;
475 
476 namespace Resonances {
477 
478 RBW::RBW(std::string name,
479  Variable ar,
480  Variable ai,
481  Variable mass,
482  Variable width,
483  unsigned int sp,
484  unsigned int cyc,
485  bool sym)
486  : ResonancePdf(name, ar, ai) {
487  pindices.push_back(registerParameter(mass));
488  pindices.push_back(registerParameter(width));
489  pindices.push_back(sp);
490  pindices.push_back(cyc);
491 
492  if(sym) {
493  GET_FUNCTION_ADDR(ptr_to_RBW_Sym);
494  } else {
495  GET_FUNCTION_ADDR(ptr_to_RBW);
496  }
497 
498  initialize(pindices);
499 }
500 
501 GS::GS(std::string name, Variable ar, Variable ai, Variable mass, Variable width, unsigned int sp, unsigned int cyc)
502  : ResonancePdf(name, ar, ai) {
503  pindices.push_back(registerParameter(mass));
504  pindices.push_back(registerParameter(width));
505  pindices.push_back(sp);
506  pindices.push_back(cyc);
507 
508  GET_FUNCTION_ADDR(ptr_to_GOUSAK);
509 
510  initialize(pindices);
511 }
512 
513 LASS::LASS(std::string name, Variable ar, Variable ai, Variable mass, Variable width, unsigned int sp, unsigned int cyc)
514  : ResonancePdf(name, ar, ai) {
515  pindices.push_back(registerParameter(mass));
516  pindices.push_back(registerParameter(width));
517  pindices.push_back(sp);
518  pindices.push_back(cyc);
519 
520  GET_FUNCTION_ADDR(ptr_to_LASS);
521 
522  initialize(pindices);
523 }
524 
525 // Constructor for regular BW,Gounaris-Sakurai,LASS
526 Gauss::Gauss(std::string name, Variable ar, Variable ai, Variable mass, Variable width, unsigned int cyc)
527  : ResonancePdf(name, ar, ai) {
528  // Making room for index of decay-related constants. Assumption:
529  // These are mother mass and three daughter masses in that order.
530  // They will be registered by the object that uses this resonance,
531  // which will tell this object where to find them by calling setConstantIndex.
532 
533  std::vector<unsigned int> pindices;
534  pindices.push_back(0);
535  pindices.push_back(registerParameter(mass));
536  pindices.push_back(registerParameter(width));
537  pindices.push_back(cyc);
538 
539  GET_FUNCTION_ADDR(ptr_to_GAUSSIAN);
540 
541  initialize(pindices);
542 }
543 
544 NonRes::NonRes(std::string name, Variable ar, Variable ai)
545  : ResonancePdf(name, ar, ai) {
546  GET_FUNCTION_ADDR(ptr_to_NONRES);
547 
548  initialize(pindices);
549 }
550 
551 FLATTE::FLATTE(std::string name,
552  Variable ar,
553  Variable ai,
554  Variable mean,
555  Variable g1,
556  Variable rg2og1,
557  unsigned int cyc,
558  bool symmDP)
559  : ResonancePdf(name, ar, ai) {
560  pindices.push_back(registerParameter(mean));
561  pindices.push_back(registerParameter(g1));
562  pindices.push_back(registerParameter(rg2og1));
563  pindices.push_back(cyc);
564  pindices.push_back((unsigned int)symmDP);
565 
566  GET_FUNCTION_ADDR(ptr_to_FLATTE);
567 
568  initialize(pindices);
569 }
570 
571 Spline::Spline(std::string name,
572  Variable ar,
573  Variable ai,
574  std::vector<fptype> &HH_bin_limits,
575  std::vector<Variable> &pwa_coefs_reals,
576  std::vector<Variable> &pwa_coefs_imags,
577  unsigned int cyc,
578  bool symmDP)
579  : ResonancePdf(name, ar, ai) {
580  std::vector<unsigned int> pindices;
581  const unsigned int nKnobs = HH_bin_limits.size();
582  host_constants.resize(nKnobs);
583 
584  pindices.push_back(0);
585  pindices.push_back(cyc);
586  pindices.push_back((unsigned int)symmDP);
587  pindices.push_back(nKnobs);
588 
589  for(int i = 0; i < pwa_coefs_reals.size(); i++) {
590  host_constants[i] = HH_bin_limits[i];
591  pindices.push_back(registerParameter(pwa_coefs_reals[i]));
592  pindices.push_back(registerParameter(pwa_coefs_imags[i]));
593  }
594  pindices.push_back(registerConstants(nKnobs));
595 
596  MEMCPY_TO_SYMBOL(functorConstants,
597  host_constants.data(),
598  nKnobs * sizeof(fptype),
599  cIndex * sizeof(fptype),
600  cudaMemcpyHostToDevice);
601 
602  GET_FUNCTION_ADDR(ptr_to_SPLINE);
603 
604  initialize(pindices);
605 }
606 
607 __host__ void Spline::recalculateCache() const {
608  auto params = getParameters();
609  const unsigned nKnobs = params.size() / 2;
610  std::vector<fpcomplex> y(nKnobs);
611  unsigned int i = 0;
612  for(auto v = params.begin(); v != params.end(); ++v, ++i) {
613  unsigned int idx = i / 2;
614  fptype value = host_params[v->getIndex()];
615  if(i % 2 == 0)
616  y[idx].real(value);
617  else
618  y[idx].imag(value);
619  }
620  std::vector<fptype> y2_flat = flatten(complex_derivative(host_constants, y));
621 
622  MEMCPY_TO_SYMBOL(cDeriatives, y2_flat.data(), 2 * nKnobs * sizeof(fptype), 0, cudaMemcpyHostToDevice);
623 }
624 
625 } // namespace Resonances
626 
627 } // namespace GooFit