evtgen is hosted by Hepforge, IPPP Durham
EvtGen  2.0.0
Monte Carlo generator of particle decays, in particular the weak decays of heavy flavour particles such as B mesons.
EvtPto3PAmpFactory.cpp
Go to the documentation of this file.
1 
2 /***********************************************************************
3 * Copyright 1998-2020 CERN for the benefit of the EvtGen authors *
4 * *
5 * This file is part of EvtGen. *
6 * *
7 * EvtGen is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * EvtGen is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with EvtGen. If not, see <https://www.gnu.org/licenses/>. *
19 ***********************************************************************/
20 
22 
23 #include "EvtGenBase/EvtComplex.hh"
24 #include "EvtGenBase/EvtConst.hh"
25 #include "EvtGenBase/EvtCyclic3.hh"
28 #include "EvtGenBase/EvtFlatAmp.hh"
29 #include "EvtGenBase/EvtId.hh"
30 #include "EvtGenBase/EvtLASSAmp.hh"
32 #include "EvtGenBase/EvtPDL.hh"
33 #include "EvtGenBase/EvtPatches.hh"
39 
40 #include <assert.h>
41 #include <math.h>
42 #include <memory>
43 #include <stdio.h>
44 #include <stdlib.h>
45 
46 using namespace EvtCyclic3;
47 #include <iostream>
48 
49 void EvtPto3PAmpFactory::processAmp( EvtComplex c, std::vector<std::string> vv,
50  bool conj )
51 {
52  if ( _verbose ) {
53  printf( "Make %samplitude\n", conj ? "CP conjugate" : "" );
54  unsigned i;
55  for ( i = 0; i < vv.size(); i++ )
56  printf( "%s\n", vv[i].c_str() );
57  printf( "\n" );
58  }
59 
60  std::unique_ptr<EvtAmplitude<EvtDalitzPoint>> amp;
61  std::unique_ptr<EvtPdf<EvtDalitzPoint>> pdf;
62  std::string name;
63  Pair pairRes = AB;
64 
65  size_t i;
66  /*
67  Experimental amplitudes
68  */
69  if ( vv[0] == "PHASESPACE" ) {
70  pdf = std::make_unique<EvtDalitzFlatPdf>( _dp );
71  amp = std::make_unique<EvtFlatAmp<EvtDalitzPoint>>();
72  name = "NR";
73  } else if ( !vv[0].find( "NONRES" ) ) {
74  double alpha = 0;
76  if ( vv[0] == "NONRES_LIN" ) {
77  typeNRes = EvtPto3PAmp::NONRES_LIN;
78  pairRes = strToPair( vv[1].c_str() );
79  } else if ( vv[0] == "NONRES_EXP" ) {
80  typeNRes = EvtPto3PAmp::NONRES_EXP;
81  pairRes = strToPair( vv[1].c_str() );
82  alpha = strtod( vv[2].c_str(), 0 );
83  } else
84  assert( 0 );
85  pdf = std::make_unique<EvtDalitzFlatPdf>( _dp );
86  amp = std::make_unique<EvtNonresonantAmp>( &_dp, typeNRes, pairRes,
87  alpha );
88  } else if ( vv[0] == "LASS" || vv[0] == "LASS_ELASTIC" ||
89  vv[0] == "LASS_RESONANT" ) {
90  pairRes = strToPair( vv[1].c_str() );
91  double m0 = strtod( vv[2].c_str(), 0 );
92  double g0 = strtod( vv[3].c_str(), 0 );
93  double a = strtod( vv[4].c_str(), 0 );
94  double r = strtod( vv[5].c_str(), 0 );
95  double cutoff = strtod( vv[6].c_str(), 0 );
96  pdf = std::make_unique<EvtDalitzResPdf>( _dp, m0, g0, pairRes );
97  amp = std::make_unique<EvtLASSAmp>( &_dp, pairRes, m0, g0, a, r, cutoff,
98  vv[0] );
99  }
100 
101  /*
102  Resonant amplitudes
103  */
104  else if ( vv[0] == "RESONANCE" ) {
105  std::unique_ptr<EvtPto3PAmp> partAmp;
106 
107  // RESONANCE stanza
108 
109  pairRes = strToPair( vv[1].c_str() );
111  double mR, gR;
112  name = vv[2];
113  EvtId resId = EvtPDL::getId( vv[2] );
114  if ( _verbose )
115  printf( "Particles %s form %sresonance %s\n", vv[1].c_str(),
116  vv[2].c_str(), conj ? "(conj) " : "" );
117 
118  // If no valid particle name is given, assume that
119  // it is the spin, the mass and the width of the particle.
120 
121  if ( resId.getId() == -1 ) {
122  switch ( atoi( vv[2].c_str() ) ) {
123  case 0: {
124  spinR = EvtSpinType::SCALAR;
125  break;
126  }
127  case 1: {
128  spinR = EvtSpinType::VECTOR;
129  break;
130  }
131  case 2: {
132  spinR = EvtSpinType::TENSOR;
133  break;
134  }
135  case 3: {
136  spinR = EvtSpinType::SPIN3;
137  break;
138  }
139  case 4: {
140  spinR = EvtSpinType::SPIN4;
141  break;
142  }
143  default: {
144  assert( 0 );
145  break;
146  }
147  }
148 
149  mR = strtod( vv[3].c_str(), 0 );
150  gR = strtod( vv[4].c_str(), 0 );
151  i = 4;
152  } else {
153  // For a valid particle get spin, mass and width
154 
155  spinR = EvtPDL::getSpinType( resId );
156  mR = EvtPDL::getMeanMass( resId );
157  gR = EvtPDL::getWidth( resId );
158  i = 2;
159 
160  // It's possible to specify mass and width of a particle
161  // explicitly
162 
163  if ( vv[3] != "ANGULAR" ) {
164  if ( _verbose )
165  printf( "Setting m(%s)=%s g(%s)=%s\n", vv[2].c_str(),
166  vv[3].c_str(), vv[2].c_str(), vv[4].c_str() );
167 
168  mR = strtod( vv[3].c_str(), 0 );
169  gR = strtod( vv[4].c_str(), 0 );
170  i = 4;
171  }
172  }
173 
174  // ANGULAR stanza
175 
176  if ( vv[++i] != "ANGULAR" ) {
177  printf( "%s instead of ANGULAR\n", vv[i].c_str() );
178  exit( 0 );
179  }
180  Pair pairAng = strToPair( vv[++i].c_str() );
181  if ( _verbose )
182  printf( "Angle is measured between particles %s\n", vv[i].c_str() );
183 
184  // TYPE stanza
185 
186  std::string typeName = vv[++i];
187  assert( typeName == "TYPE" );
188  std::string type = vv[++i];
189  if ( _verbose )
190  printf( "Propagator type %s\n", vv[i].c_str() );
191 
192  if ( type == "NBW" ) {
193  EvtPropBreitWigner prop( mR, gR );
194  partAmp = std::make_unique<EvtPto3PAmp>( _dp, pairAng, pairRes, spinR,
195  prop, EvtPto3PAmp::NBW );
196  } else if ( type == "RBW_ZEMACH" ) {
197  EvtPropBreitWignerRel prop( mR, gR );
198  partAmp = std::make_unique<EvtPto3PAmp>( _dp, pairAng, pairRes,
199  spinR, prop,
201  } else if ( type == "RBW_KUEHN" ) {
202  EvtPropBreitWignerRel prop( mR, gR );
203  partAmp = std::make_unique<EvtPto3PAmp>( _dp, pairAng, pairRes,
204  spinR, prop,
206  } else if ( type == "RBW_CLEO" ) {
207  EvtPropBreitWignerRel prop( mR, gR );
208  partAmp = std::make_unique<EvtPto3PAmp>( _dp, pairAng, pairRes,
209  spinR, prop,
211  } else if ( type == "FLATTE" ) {
212  double m1a = _dp.m( first( pairRes ) );
213  double m1b = _dp.m( second( pairRes ) );
214  // 2nd channel
215  double g2 = strtod( vv[++i].c_str(), 0 );
216  double m2a = strtod( vv[++i].c_str(), 0 );
217  double m2b = strtod( vv[++i].c_str(), 0 );
218  EvtPropFlatte prop( mR, gR, m1a, m1b, g2, m2a, m2b );
219  partAmp = std::make_unique<EvtPto3PAmp>( _dp, pairAng, pairRes, spinR,
220  prop, EvtPto3PAmp::FLATTE );
221  } else
222  assert( 0 );
223 
224  // Optional DVFF, BVFF stanzas
225 
226  if ( i < vv.size() - 1 ) {
227  if ( vv[i + 1] == "DVFF" ) {
228  i++;
229  if ( vv[++i] == "BLATTWEISSKOPF" ) {
230  double R = strtod( vv[++i].c_str(), 0 );
231  partAmp->set_fd( R );
232  } else
233  assert( 0 );
234  }
235  }
236 
237  if ( i < vv.size() - 1 ) {
238  if ( vv[i + 1] == "BVFF" ) {
239  i++;
240  if ( vv[++i] == "BLATTWEISSKOPF" ) {
241  if ( _verbose )
242  printf( "BVFF=%s\n", vv[i].c_str() );
243  double R = strtod( vv[++i].c_str(), 0 );
244  partAmp->set_fb( R );
245  } else
246  assert( 0 );
247  }
248  }
249 
250  const int minwidths = 5;
251  //Optional resonance minimum and maximum
252  if ( i < vv.size() - 1 ) {
253  if ( vv[i + 1] == "CUTOFF" ) {
254  i++;
255  if ( vv[i + 1] == "MIN" ) {
256  i++;
257  double min = strtod( vv[++i].c_str(), 0 );
258  if ( _verbose )
259  std::cout << "CUTOFF MIN = " << min << " " << minwidths
260  << std::endl;
261  //ensure against cutting off too close to the resonance
262  assert( min < ( mR - minwidths * gR ) );
263  partAmp->setmin( min );
264  } else if ( vv[i + 1] == "MAX" ) {
265  i++;
266  double max = strtod( vv[++i].c_str(), 0 );
267  if ( _verbose )
268  std::cout << "CUTOFF MAX = " << max << " " << minwidths
269  << std::endl;
270  //ensure against cutting off too close to the resonance
271  assert( max > ( mR + minwidths * gR ) );
272  partAmp->setmax( max );
273  } else
274  assert( 0 );
275  }
276  }
277 
278  //2nd iteration in case min and max are both specified
279  if ( i < vv.size() - 1 ) {
280  if ( vv[i + 1] == "CUTOFF" ) {
281  i++;
282  if ( vv[i + 1] == "MIN" ) {
283  i++;
284  double min = strtod( vv[++i].c_str(), 0 );
285  if ( _verbose )
286  std::cout << "CUTOFF MIN = " << min << std::endl;
287  //ensure against cutting off too close to the resonance
288  assert( min < ( mR - minwidths * gR ) );
289  partAmp->setmin( min );
290  } else if ( vv[i + 1] == "MAX" ) {
291  i++;
292  double max = strtod( vv[++i].c_str(), 0 );
293  if ( _verbose )
294  std::cout << "CUTOFF MAX = " << max << std::endl;
295  //ensure against cutting off too close to the resonance
296  assert( max > ( mR + minwidths * gR ) );
297  partAmp->setmax( max );
298  } else
299  assert( 0 );
300  }
301  }
302 
303  i++;
304 
305  pdf = std::make_unique<EvtDalitzResPdf>( _dp, mR, gR, pairRes );
306  amp = std::move( partAmp );
307  }
308 
309  assert( amp );
310  assert( pdf );
311 
312  double scale = matchIsobarCoef( *_amp, *pdf, pairRes );
313 
314  if ( !conj ) {
315  _amp->addOwnedTerm( c, std::move( amp ) );
316  } else {
317  _ampConj->addOwnedTerm( c, std::move( amp ) );
318  }
319  _pc->addOwnedTerm( abs2( c ) * scale, std::move( pdf ) );
320 
321  _names.push_back( name );
322 }
323 
326  EvtCyclic3::Pair ipair )
327 {
328  // account for differences in the definition of amplitudes by matching
329  // Integral( c'*pdf ) = Integral( c*|A|^2 )
330  // to improve generation efficiency ...
331 
332  double Ipdf = pdf.compute_integral( 10000 ).value();
333  double Iamp2 = 0;
334 
335  EvtCyclic3::Pair jpair = EvtCyclic3::next( ipair );
336  EvtCyclic3::Pair kpair = EvtCyclic3::next( jpair );
337 
338  // Trapezoidal integral
339  int N = 10000;
340 
341  double di = ( _dp.qAbsMax( ipair ) - _dp.qAbsMin( ipair ) ) / ( (double)N );
342 
343  double siMin = _dp.qAbsMin( ipair );
344 
345  double s[3]; // playing with fire
346  for ( int i = 1; i < N; i++ ) {
347  s[ipair] = siMin + di * i;
348  s[jpair] = _dp.q( jpair, 0.9999, ipair, s[ipair] );
349  s[kpair] = _dp.bigM() * _dp.bigM() - s[ipair] - s[jpair] +
350  _dp.mA() * _dp.mA() + _dp.mB() * _dp.mB() +
351  _dp.mC() * _dp.mC();
352 
353  EvtDalitzPoint point( _dp.mA(), _dp.mB(), _dp.mC(), s[EvtCyclic3::AB],
355 
356  if ( !point.isValid() )
357  continue;
358 
359  double p = point.p( other( ipair ), ipair );
360  double q = point.p( first( ipair ), ipair );
361 
362  double itg = abs2( amp.evaluate( point ) ) * di * 4 * q * p;
363  Iamp2 += itg;
364  }
365  if ( _verbose )
366  std::cout << "integral = " << Iamp2 << " pdf=" << Ipdf << std::endl;
367 
368  assert( Ipdf > 0 && Iamp2 > 0 );
369 
370  return Iamp2 / Ipdf;
371 }
const char * c_str(Index i)
Definition: EvtCyclic3.cpp:323
static EvtSpinType::spintype getSpinType(EvtId i)
Definition: EvtPDL.cpp:377
EvtComplex evaluate(const T &p) const
Definition: EvtAmplitude.hh:40
Evt3Rank3C conj(const Evt3Rank3C &t2)
Definition: Evt3Rank3C.cpp:172
double matchIsobarCoef(EvtAmplitude< EvtDalitzPoint > &amp, EvtPdf< EvtDalitzPoint > &pdf, EvtCyclic3::Pair i)
static double getMeanMass(EvtId i)
Definition: EvtPDL.cpp:314
double abs2(const EvtComplex &c)
Definition: EvtComplex.hh:209
Definition: EvtId.hh:27
virtual EvtValError compute_integral() const
Definition: EvtPdf.hh:113
double value() const
Definition: EvtValError.hh:39
Index next(Index i)
Definition: EvtCyclic3.cpp:142
static EvtId getId(const std::string &name)
Definition: EvtPDL.cpp:287
Index second(Pair i)
Definition: EvtCyclic3.cpp:264
int getId() const
Definition: EvtId.hh:42
Index first(Pair i)
Definition: EvtCyclic3.cpp:250
static double getWidth(EvtId i)
Definition: EvtPDL.cpp:352
Pair strToPair(const char *str)
Definition: EvtCyclic3.cpp:310
void processAmp(EvtComplex c, std::vector< std::string > vv, bool conj) override
double p(EvtCyclic3::Index i, EvtCyclic3::Pair j) const
Index other(Index i, Index j)
Definition: EvtCyclic3.cpp:156