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