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
EvtVSSBMixCPT.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
25#include "EvtGenBase/EvtId.hh"
26#include "EvtGenBase/EvtPDL.hh"
31
32#include <stdlib.h>
33#include <string>
34using std::endl;
35
36std::string EvtVSSBMixCPT::getName() const
37{
38 return "VSS_BMIX";
39}
40
42{
43 return new EvtVSSBMixCPT;
44}
45
47{
48 if ( getNArg() > 4 )
49 checkNArg( 14, 12, 8 );
50
51 if ( getNArg() < 1 ) {
52 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
53 << "EvtVSSBMix generator expected "
54 << " at least 1 argument (deltam) but found:" << getNArg() << endl;
55 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
56 << "Will terminate execution!" << endl;
57 ::abort();
58 }
59 // check that we are asked to produced exactly 2 daughters
60 //4 are allowed if they are aliased..
61 checkNDaug( 2, 4 );
62
63 if ( getNDaug() == 4 ) {
64 if ( getDaug( 0 ) != getDaug( 2 ) || getDaug( 1 ) != getDaug( 3 ) ) {
65 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
66 << "EvtVSSBMixCPT generator allows "
67 << " 4 daughters only if 1=3 and 2=4"
68 << " (but 3 and 4 are aliased " << endl;
69 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
70 << "Will terminate execution!" << endl;
71 ::abort();
72 }
73 }
74 // check that we are asked to decay a vector particle into a pair
75 // of scalar particles
76
78
81
82 // check that our daughter particles are charge conjugates of each other
83 if ( !( EvtPDL::chargeConj( getDaug( 0 ) ) == getDaug( 1 ) ) ) {
84 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
85 << "EvtVSSBMixCPT generator expected daughters "
86 << "to be charge conjugate." << endl
87 << " Found " << EvtPDL::name( getDaug( 0 ) ).c_str() << " and "
88 << EvtPDL::name( getDaug( 1 ) ).c_str() << endl;
89 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
90 << "Will terminate execution!" << endl;
91 ::abort();
92 }
93 // check that both daughter particles have the same lifetime
94 if ( EvtPDL::getctau( getDaug( 0 ) ) != EvtPDL::getctau( getDaug( 1 ) ) ) {
95 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
96 << "EvtVSSBMixCPT generator expected daughters "
97 << "to have the same lifetime." << endl
98 << " Found ctau = " << EvtPDL::getctau( getDaug( 0 ) )
99 << " mm and " << EvtPDL::getctau( getDaug( 1 ) ) << " mm" << endl;
100 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
101 << "Will terminate execution!" << endl;
102 ::abort();
103 }
104 // precompute quantities that will be used to generate events
105 // and print out a summary of parameters for this decay
106
107 // mixing frequency in hbar/mm
108 m_freq = getArg( 0 ) / EvtConst::c;
109
110 // deltaG
111 double gamma = 1 / EvtPDL::getctau( getDaug( 0 ) ); // gamma/c (1/mm)
112 m_dGamma = 0.0;
113 double dgog = 0.0;
114 if ( getNArg() > 1 ) {
115 dgog = getArg( 1 );
116 m_dGamma = dgog * gamma;
117 }
118 // q/p
119 m_qoverp = EvtComplex( 1.0, 0.0 );
120 if ( getNArg() > 2 ) {
121 m_qoverp = EvtComplex( getArg( 2 ), 0.0 );
122 }
123 if ( getNArg() > 3 ) {
124 m_qoverp = getArg( 2 ) *
125 EvtComplex( cos( getArg( 3 ) ), sin( getArg( 3 ) ) );
126 }
127 m_poverq = 1.0 / m_qoverp;
128
129 // decay amplitudes
130 m_A_f = EvtComplex( 1.0, 0.0 );
131 m_Abar_f = EvtComplex( 0.0, 0.0 );
132 m_A_fbar = m_Abar_f; // CPT conservation
133 m_Abar_fbar = m_A_f; // CPT conservation
134 if ( getNArg() > 4 ) {
135 m_A_f = getArg( 4 ) *
136 EvtComplex( cos( getArg( 5 ) ),
137 sin( getArg( 5 ) ) ); // this allows for DCSD
138 m_Abar_f = getArg( 6 ) *
139 EvtComplex( cos( getArg( 7 ) ),
140 sin( getArg( 7 ) ) ); // this allows for DCSD
141 if ( getNArg() > 8 ) {
142 // CPT violation in decay
143 m_A_fbar = getArg( 8 ) *
144 EvtComplex( cos( getArg( 9 ) ), sin( getArg( 9 ) ) );
145 m_Abar_fbar = getArg( 10 ) * EvtComplex( cos( getArg( 11 ) ),
146 sin( getArg( 11 ) ) );
147 } else {
148 // CPT conservation in decay
151 }
152 }
153
154 // CPT violation in mixing
155 m_z = EvtComplex( 0.0, 0.0 );
156 if ( getNArg() > 12 ) {
157 m_z = EvtComplex( getArg( 12 ), getArg( 13 ) );
158 }
159
160 // some printout
161 double tau = 1e12 * EvtPDL::getctau( getDaug( 0 ) ) / EvtConst::c; // in ps
162 double dm = 1e-12 * getArg( 0 ); // B0/anti-B0 mass difference in hbar/ps
163 double x = dm * tau;
164 double y = dgog * 0.5; //y=dgamma/(2*gamma)
165 double qop2 = abs( m_qoverp * m_qoverp );
166 m_chib0_b0bar = qop2 * ( x * x + y * y ) /
167 ( qop2 * ( x * x + y * y ) + 2 + x * x -
168 y * y ); // does not include CPT in mixing
169 m_chib0bar_b0 = ( 1 / qop2 ) * ( x * x + y * y ) /
170 ( ( 1 / qop2 ) * ( x * x + y * y ) + 2 + x * x -
171 y * y ); // does not include CPT in mixing
172
173 if ( verbose() ) {
174 EvtGenReport( EVTGEN_INFO, "EvtGen" )
175 << "VSS_BMIXCPT will generate mixing and CPT/CP effects in mixing:"
176 << endl
177 << endl
178 << " " << EvtPDL::name( getParentId() ).c_str() << " --> "
179 << EvtPDL::name( getDaug( 0 ) ).c_str() << " + "
180 << EvtPDL::name( getDaug( 1 ) ).c_str() << endl
181 << endl
182 << "using parameters:" << endl
183 << endl
184 << " delta(m) = " << dm << " hbar/ps" << endl
185 << " freq = " << m_freq << " hbar/mm" << endl
186 << " dgog = " << dgog << endl
187 << " dGamma = " << m_dGamma << " hbar/mm" << endl
188 << " q/p = " << m_qoverp << endl
189 << " z = " << m_z << endl
190 << " tau = " << tau << " ps" << endl
191 << " x = " << x << endl
192 << " chi(B0->B0bar) = " << m_chib0_b0bar << endl
193 << " chi(B0bar->B0) = " << m_chib0bar_b0 << endl
194 << " Af = " << m_A_f << endl
195 << " Abarf = " << m_Abar_f << endl
196 << " Afbar = " << m_A_fbar << endl
197 << " Abarfbar = " << m_Abar_fbar << endl
198 << endl;
199 }
200}
201
203{
204 // this value is ok for reasonable values of all the parameters
205 setProbMax( 4.0 );
206}
207
209{
210 static const EvtId B0 = EvtPDL::getId( "B0" );
211 static const EvtId B0B = EvtPDL::getId( "anti-B0" );
212
213 // generate a final state according to phase space
214
215 double rndm = EvtRandom::random();
216
217 if ( getNDaug() == 4 ) {
218 EvtId tempDaug[2];
219
220 if ( rndm < 0.5 ) {
221 tempDaug[0] = getDaug( 0 );
222 tempDaug[1] = getDaug( 3 );
223 } else {
224 tempDaug[0] = getDaug( 2 );
225 tempDaug[1] = getDaug( 1 );
226 }
227
228 p->initializePhaseSpace( 2, tempDaug );
229 } else { //nominal case.
231 }
232
233 EvtParticle *s1, *s2;
234
235 s1 = p->getDaug( 0 );
236 s2 = p->getDaug( 1 );
237 //delete any daughters - if there are daughters, they
238 //are from the initialization and will be redone later
239 if ( s1->getNDaug() > 0 ) {
240 s1->deleteDaughters();
241 }
242 if ( s2->getNDaug() > 0 ) {
243 s2->deleteDaughters();
244 }
245
246 EvtVector4R p1 = s1->getP4();
247 EvtVector4R p2 = s2->getP4();
248
249 // throw a random number to decide if this final state should be mixed
250 rndm = EvtRandom::random();
251 int mixed = ( rndm < 0.5 ) ? 1 : 0;
252
253 // if this decay is mixed, choose one of the 2 possible final states
254 // with equal probability (re-using the same random number)
255 if ( mixed == 1 ) {
256 EvtId mixedId = ( rndm < 0.25 ) ? getDaug( 0 ) : getDaug( 1 );
257 EvtId mixedId2 = mixedId;
258 if ( getNDaug() == 4 && rndm < 0.25 )
259 mixedId2 = getDaug( 2 );
260 if ( getNDaug() == 4 && rndm > 0.25 )
261 mixedId2 = getDaug( 3 );
262 s1->init( mixedId, p1 );
263 s2->init( mixedId2, p2 );
264 }
265
266 // if this decay is unmixed, choose one of the 2 possible final states
267 // with equal probability (re-using the same random number)
268 if ( mixed == 0 ) {
269 EvtId unmixedId = ( rndm < 0.75 ) ? getDaug( 0 ) : getDaug( 1 );
270 EvtId unmixedId2 = ( rndm < 0.75 ) ? getDaug( 1 ) : getDaug( 0 );
271 if ( getNDaug() == 4 && rndm < 0.75 )
272 unmixedId2 = getDaug( 3 );
273 if ( getNDaug() == 4 && rndm > 0.75 )
274 unmixedId2 = getDaug( 2 );
275 s1->init( unmixedId, p1 );
276 s2->init( unmixedId2, p2 );
277 }
278
279 // choose a decay time for each final state particle using the
280 // lifetime (which must be the same for both particles) in pdt.table
281 // and calculate the lifetime difference for this event
282 s1->setLifetime();
283 s2->setLifetime();
284 double dct = s1->getLifetime() - s2->getLifetime(); // in mm
285
286 // Convention: m_dGamma=GammaLight-GammaHeavy
287 EvtComplex exp1( -0.25 * m_dGamma * dct, 0.5 * m_freq * dct );
288
289 /*
290 //Find the flavor of the B that decayed first.
291 EvtId firstDec = (dct > 0 ) ? s2->getId() : s1->getId();
292
293 //This tags the flavor of the other particle at that time.
294 EvtId stateAtDeltaTeq0 = ( firstDec==B0 ) ? B0B : B0;
295 */
296 EvtId stateAtDeltaTeq0 = ( s2->getId() == B0 ) ? B0B : B0;
297
298 // calculate the oscillation amplitude, based on wether this event is mixed or not
299 EvtComplex osc_amp;
300
301 //define some useful functions: (see BAD #188 eq. 39 for ref.)
302 EvtComplex gp = 0.5 * ( exp( -1.0 * exp1 ) + exp( exp1 ) );
303 EvtComplex gm = 0.5 * ( exp( -1.0 * exp1 ) - exp( exp1 ) );
304 EvtComplex sqz = sqrt( abs( 1 - m_z * m_z ) ) *
305 exp( EvtComplex( 0, arg( 1 - m_z * m_z ) / 2 ) );
306
307 EvtComplex BB = gp + m_z * gm; // <B0|B0(t)>
308 EvtComplex barBB = -sqz * m_qoverp * gm; // <B0bar|B0(t)>
309 EvtComplex BbarB = -sqz * m_poverq * gm; // <B0|B0bar(t)>
310 EvtComplex barBbarB = gp - m_z * gm; // <B0bar|B0bar(t)>
311
312 //
313 if ( !mixed && stateAtDeltaTeq0 == B0 ) {
314 osc_amp = BB * m_A_f + barBB * m_Abar_f;
315 }
316 if ( !mixed && stateAtDeltaTeq0 == B0B ) {
317 osc_amp = barBbarB * m_Abar_fbar + BbarB * m_A_fbar;
318 }
319
320 if ( mixed && stateAtDeltaTeq0 == B0 ) {
321 osc_amp = barBB * m_Abar_fbar + BB * m_A_fbar;
322 }
323 if ( mixed && stateAtDeltaTeq0 == B0B ) {
324 osc_amp = BbarB * m_A_f + barBbarB * m_Abar_f;
325 }
326
327 // store the amplitudes for each parent spin basis state
328 double norm = 1.0 / p1.d3mag();
329 vertex( 0, norm * osc_amp * p1 * ( p->eps( 0 ) ) );
330 vertex( 1, norm * osc_amp * p1 * ( p->eps( 1 ) ) );
331 vertex( 2, norm * osc_amp * p1 * ( p->eps( 2 ) ) );
332
333 return;
334}
335
336std::string EvtVSSBMixCPT::getParamName( int i )
337{
338 switch ( i ) {
339 case 0:
340 return "deltaM";
341 case 1:
342 return "deltaGammaOverGamma";
343 case 2:
344 return "qOverP";
345 case 3:
346 return "qOverPPhase";
347 case 4:
348 return "Af";
349 case 5:
350 return "AfPhase";
351 case 6:
352 return "Abarf";
353 case 7:
354 return "AbarfPhase";
355 case 8:
356 return "Afbar";
357 case 9:
358 return "AfbarPhase";
359 case 10:
360 return "Abarfbar";
361 case 11:
362 return "AbarfbarPhase";
363 case 12:
364 return "Z";
365 case 13:
366 return "ZPhase";
367 default:
368 return "";
369 }
370}
371
373{
374 switch ( i ) {
375 case 3:
376 return "0.0";
377 case 4:
378 return "1.0";
379 case 5:
380 return "0.0";
381 case 6:
382 return "1.0";
383 case 7:
384 return "0.0";
385 default:
386 return "";
387 }
388}
EvtComplex exp(const EvtComplex &c)
double arg(const EvtComplex &c)
double abs(const EvtComplex &c)
std::ostream & EvtGenReport(EvtGenSeverity severity, const char *facility=nullptr)
Definition EvtReport.cpp:32
@ EVTGEN_INFO
Definition EvtReport.hh:52
@ EVTGEN_ERROR
Definition EvtReport.hh:49
static const double c
Definition EvtConst.hh:30
void vertex(const EvtComplex &amp)
void checkSpinDaughter(int d1, EvtSpinType::spintype sp)
EvtDecayBase()=default
int getNDaug() const
void checkSpinParent(EvtSpinType::spintype sp)
int getNArg() const
double getArg(unsigned int j)
void setProbMax(double prbmx)
EvtId getParentId() const
bool verbose() const
EvtId getDaug(int i) const
void checkNDaug(int d1, int d2=-1)
void checkNArg(int a1, int a2=-1, int a3=-1, int a4=-1)
const EvtId * getDaugs() const
Definition EvtId.hh:27
static std::string name(EvtId i)
Definition EvtPDL.cpp:376
static EvtId chargeConj(EvtId id)
Definition EvtPDL.cpp:201
static double getctau(EvtId i)
Definition EvtPDL.cpp:351
static EvtId getId(const std::string &name)
Definition EvtPDL.cpp:283
virtual void init(EvtId part_n, const EvtVector4R &p4)=0
double initializePhaseSpace(size_t numdaughter, const EvtId *daughters, bool forceResetMasses=false, double poleSize=-1., int whichTwo1=0, int whichTwo2=1)
EvtId getId() const
const EvtVector4R & getP4() const
void setLifetime(double tau)
EvtParticle * getDaug(const int i)
void deleteDaughters(bool keepChannel=false)
double getLifetime() const
size_t getNDaug() const
virtual EvtVector4C eps(int i) const
static double random()
Definition EvtRandom.cpp:41
EvtDecayBase * clone() const override
EvtComplex m_A_f
void decay(EvtParticle *p) override
std::string getName() const override
std::string getParamName(int i) override
std::string getParamDefault(int i) override
EvtComplex m_z
EvtComplex m_Abar_fbar
EvtComplex m_poverq
EvtComplex m_qoverp
EvtComplex m_Abar_f
void init() override
EvtComplex m_A_fbar
void initProbMax() override
double d3mag() const