GooFit  v2.1.3
EventWeightedAddPdf.cu
Go to the documentation of this file.
1 #include <goofit/Error.h>
2 #include <goofit/Log.h>
3 #include <goofit/PDFs/combine/EventWeightedAddPdf.h>
4 
5 namespace GooFit {
6 
7 __device__ fptype device_EventWeightedAddPdfs(fptype *evt, fptype *p, unsigned int *indices) {
8  int numParameters = RO_CACHE(indices[0]);
9  fptype ret = 0;
10  fptype totalWeight = 0;
11 
12  for(int i = 0; i < numParameters / 2 - 1; ++i) {
13  fptype weight = RO_CACHE(evt[RO_CACHE(indices[2 + numParameters + i])]);
14  totalWeight += weight;
15  fptype curr = callFunction(evt, RO_CACHE(indices[2 * i + 1]), RO_CACHE(indices[2 * (i + 1)]));
16  ret += weight * curr * normalisationFactors[RO_CACHE(indices[2 * (i + 1)])];
17  }
18 
19  // numParameters does not count itself. So the array structure for two functions is
20  // nP | F P | F P | nO | o1
21  // in which nP = 4. and nO = 1. Therefore the parameter index for the last function pointer is nP, and the function
22  // index is nP-1.
23  // fptype last = (*(reinterpret_cast<device_function_ptr>(device_function_table[indices[numParameters-1]])))(evt, p,
24  // paramIndices + indices[numParameters]);
25  fptype last = callFunction(evt, RO_CACHE(indices[numParameters - 1]), RO_CACHE(indices[numParameters]));
26  ret += (1 - totalWeight) * last * normalisationFactors[RO_CACHE(indices[numParameters])];
27 
28  return ret;
29 }
30 
31 __device__ fptype device_EventWeightedAddPdfsExt(fptype *evt, fptype *p, unsigned int *indices) {
32  // numParameters does not count itself. So the array structure for two functions is
33  // nP | F P | F P | nO | o1 o2
34  // in which nP = 4, nO = 2.
35 
36  int numParameters = RO_CACHE(indices[0]);
37  fptype ret = 0;
38  fptype totalWeight = 0;
39 
40  for(int i = 0; i < numParameters / 2; ++i) {
41  fptype curr = callFunction(evt, RO_CACHE(indices[2 * i + 1]), RO_CACHE(indices[2 * (i + 1)]));
42  // if ((0 == BLOCKIDX) && (THREADIDX < 5) && (isnan(curr))) printf("NaN component %i %i\n", i, THREADIDX);
43  fptype weight = RO_CACHE(evt[RO_CACHE(indices[2 + numParameters + i])]);
44  ret += weight * curr * normalisationFactors[RO_CACHE(indices[2 * (i + 1)])];
45  totalWeight += weight;
46 
47  // if ((gpuDebug & 1) && (0 == THREADIDX))
48  // if ((gpuDebug & 1) && (1 > evt[8]))
49  // if ((gpuDebug & 1) && (0 == THREADIDX) && (0 == BLOCKIDX))
50  // printf("EventWeightedExt: %i %f %f | %f %f %f %f %f %f %f\n", i, curr, weight, evt[0], evt[1], evt[2],
51  // evt[3], evt[4], evt[5], evt[6]);
52  // printf("EventWeightedExt: %i %f %f | %f %f \n", i, curr, weight, normalisationFactors[indices[2*(i+1)]], curr
53  // * normalisationFactors[indices[2*(i+1)]]);
54  // printf("EventWeightedExt: %i : %i %.10f %.10f %.10f %f %f %f\n", (int) floor(0.5 + evt[8]), i, curr, weight,
55  // ret, normalisationFactors[indices[2*(i+1)]], evt[6], evt[7]);
56  }
57 
58  ret /= totalWeight;
59 
60  // if (0 >= ret) printf("Zero sum %f %f %f %f %f %f %f %f %f %f\n", evt[0], evt[1], evt[2], evt[3], evt[4], evt[5],
61  // evt[6], evt[7], evt[8], evt[9]);
62 
63  return ret;
64 }
65 
66 __device__ device_function_ptr ptr_to_EventWeightedAddPdfs = device_EventWeightedAddPdfs;
67 __device__ device_function_ptr ptr_to_EventWeightedAddPdfsExt = device_EventWeightedAddPdfsExt;
68 
69 EventWeightedAddPdf::EventWeightedAddPdf(std::string n, std::vector<Observable> weights, std::vector<PdfBase *> comps)
70  : GooPdf(n) {
71  if(weights.size() != comps.size() && (weights.size() + 1) != comps.size())
72  throw GooFit::GeneralError("Size of weights {} (+1) != comps {}", weights.size(), comps.size());
73 
74  // Indices stores (function index)(function parameter index) doublet for each component.
75  // Last component has no weight index unless function is extended. Notice that in this case, unlike
76  // AddPdf, weight indices are into the event, not the parameter vector, hence they
77  // are not added to the pindices array at this stage, although 'initialize' will reserve space
78  // for them.
79  for(PdfBase *p : comps) {
80  GOOFIT_TRACE("EventWeighted component: {}", p->getName());
81  components.push_back(p);
82  if(components.back() == nullptr)
83  throw GooFit::GeneralError("Invalid component");
84  }
85 
86  bool extended = true;
87  std::vector<unsigned int> pindices;
88 
89  for(unsigned int w = 0; w < weights.size(); ++w) {
90  if(components[w] == nullptr)
91  throw GooFit::GeneralError("Invalid component");
92  pindices.push_back(components[w]->getFunctionIndex());
93  pindices.push_back(components[w]->getParameterIndex());
94  registerObservable(weights[w]);
95  }
96 
97  if(components.back() == nullptr)
98  throw GooFit::GeneralError("Invalid component");
99 
100  if(weights.size() < components.size()) {
101  pindices.push_back(components.back()->getFunctionIndex());
102  pindices.push_back(components.back()->getParameterIndex());
103  extended = false;
104  }
105 
106  // This must occur after registering weights, or the indices will be off - the device functions assume that the
107  // weights are first.
108  observables = getObservables();
109 
110  if(extended) {
111  GET_FUNCTION_ADDR(ptr_to_EventWeightedAddPdfsExt);
112  } else {
113  GET_FUNCTION_ADDR(ptr_to_EventWeightedAddPdfs);
114  }
115 
116  initialize(pindices);
117 }
118 
119 __host__ fptype EventWeightedAddPdf::normalize() const {
120  // if (cpuDebug & 1) std::cout << "Normalising EventWeightedAddPdf " << getName() << " " << components.size() <<
121  // std::endl;
122 
123  // Here the PDFs have per-event weights, so there is no per-PDF weight
124  // to keep track of. All we can do is normalize the components.
125  for(PdfBase *comp : components)
126  comp->normalize();
127 
128  host_normalisation[parameters] = 1.0;
129 
130  return 1.0;
131 }
132 
133 } // namespace GooFit