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.
EvtSpinAmp.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 
21 #include "EvtGenBase/EvtSpinAmp.hh"
22 
23 #include "EvtGenBase/EvtPatches.hh"
24 #include "EvtGenBase/EvtReport.hh"
25 
26 #include <stdlib.h>
27 
28 using std::endl;
29 
30 std::ostream& operator<<( std::ostream& os, const EvtSpinAmp& amp )
31 {
32  vector<int> index = amp.iterinit();
33 
34  os << ":";
35  do {
36  os << "<";
37  for ( size_t i = 0; i < index.size() - 1; ++i ) {
38  os << index[i];
39  }
40  os << index[index.size() - 1] << ">" << amp( index ) << ":";
41  } while ( amp.iterate( index ) );
42 
43  return os;
44 }
45 
47 {
48  EvtSpinAmp ret( cont );
49 
50  for ( size_t i = 0; i < ret._elem.size(); ++i ) {
51  ret._elem[i] *= real;
52  }
53 
54  return ret;
55 }
56 
58 {
59  return real * cont;
60 }
61 
63 {
64  EvtSpinAmp ret( cont );
65 
66  for ( size_t i = 0; i < ret._elem.size(); ++i ) {
67  ret._elem[i] /= real;
68  }
69 
70  return ret;
71 }
72 
73 vector<unsigned int> EvtSpinAmp::calctwospin(
74  const vector<EvtSpinType::spintype>& type ) const
75 {
76  vector<unsigned int> twospin;
77 
78  for ( size_t i = 0; i < type.size(); ++i ) {
79  twospin.push_back( EvtSpinType::getSpin2( type[i] ) );
80  }
81 
82  return twospin;
83 }
84 
85 EvtSpinAmp::EvtSpinAmp( const vector<EvtSpinType::spintype>& type )
86 {
87  int num = 1;
88  _type = type;
89  _twospin = calctwospin( type );
90 
91  for ( size_t i = 0; i < _twospin.size(); ++i )
92  num *= _twospin[i] + 1;
93 
94  _elem = vector<EvtComplex>( num );
95 }
96 
97 EvtSpinAmp::EvtSpinAmp( const vector<EvtSpinType::spintype>& type,
98  const EvtComplex& val )
99 {
100  int num = 1;
101  _type = type;
102  _twospin = calctwospin( type );
103 
104  for ( size_t i = 0; i < _twospin.size(); ++i )
105  num *= _twospin[i] + 1;
106 
107  _elem = vector<EvtComplex>( num, val );
108 }
109 
110 EvtSpinAmp::EvtSpinAmp( const vector<EvtSpinType::spintype>& type,
111  const vector<EvtComplex>& elem )
112 {
113  size_t num = 1;
114 
115  _type = type;
116  _twospin = calctwospin( type );
117  _elem = elem;
118 
119  for ( size_t i = 0; i < _twospin.size(); ++i ) {
120  num *= ( _twospin[i] + 1 );
121  }
122 
123  if ( _elem.size() != num ) {
124  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
125  << "Wrong number of elements input:" << _elem.size() << " vs. "
126  << num << endl;
127  ::abort();
128  }
129 }
130 
132 {
133  _twospin = copy._twospin;
134  _elem = copy._elem;
135  _type = copy._type;
136 }
137 
138 void EvtSpinAmp::checktwospin( const vector<unsigned int>& twospin ) const
139 {
140  if ( _twospin == twospin )
141  return;
142 
143  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
144  << "Dimension or order of tensors being operated on does not match"
145  << endl;
146  ::abort();
147 }
148 
149 void EvtSpinAmp::checkindexargs( const vector<int>& index ) const
150 {
151  if ( index.size() == 0 ) {
152  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
153  << "EvtSpinAmp can't handle no indices" << endl;
154  ::abort();
155  }
156 
157  if ( index.size() != _twospin.size() ) {
158  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
159  << "Rank of EvtSpinAmp index does not match: " << _twospin.size()
160  << " expected " << index.size() << " input." << endl;
161  ::abort();
162  }
163 
164  for ( size_t i = 0; i < _twospin.size(); ++i ) {
165  if ( static_cast<int>( _twospin[i] ) >= abs( index[i] ) &&
166  static_cast<int>( _twospin[i] ) % 2 == index[i] % 2 )
167  continue;
168  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
169  << "EvtSpinAmp index out of range" << endl;
170  EvtGenReport( EVTGEN_ERROR, "EvtGen" ) << " Index: ";
171  for ( size_t j = 0; j < _twospin.size(); ++j )
172  EvtGenReport( EVTGEN_ERROR, " " ) << _twospin[j];
173 
174  EvtGenReport( EVTGEN_ERROR, " " ) << endl << " Index: ";
175  for ( size_t j = 0; j < index.size(); ++j )
176  EvtGenReport( EVTGEN_ERROR, " " ) << index[j];
177  EvtGenReport( EVTGEN_ERROR, " " ) << endl;
178  ::abort();
179  }
180 }
181 
182 int EvtSpinAmp::findtrueindex( const vector<int>& index ) const
183 {
184  int trueindex = 0;
185 
186  for ( size_t i = index.size() - 1; i > 0; --i ) {
187  trueindex += ( index[i] + _twospin[i] ) / 2;
188  trueindex *= _twospin[i - 1] + 1;
189  }
190 
191  trueindex += ( index[0] + _twospin[0] ) / 2;
192 
193  return trueindex;
194 }
195 
196 EvtComplex& EvtSpinAmp::operator()( const vector<int>& index )
197 {
198  checkindexargs( index );
199 
200  size_t trueindex = findtrueindex( index );
201  if ( trueindex >= _elem.size() ) {
202  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
203  << "indexing error " << trueindex << " " << _elem.size() << endl;
204  for ( size_t i = 0; i < _twospin.size(); ++i ) {
205  EvtGenReport( EVTGEN_ERROR, "" ) << _twospin[i] << " ";
206  }
207  EvtGenReport( EVTGEN_ERROR, "" ) << endl;
208 
209  for ( size_t i = 0; i < index.size(); ++i ) {
210  EvtGenReport( EVTGEN_ERROR, "" ) << index[i] << " ";
211  }
212  EvtGenReport( EVTGEN_ERROR, "" ) << endl;
213 
214  ::abort();
215  }
216 
217  return _elem[trueindex];
218 }
219 
220 const EvtComplex& EvtSpinAmp::operator()( const vector<int>& index ) const
221 {
222  checkindexargs( index );
223 
224  size_t trueindex = findtrueindex( index );
225  if ( trueindex >= _elem.size() ) {
226  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
227  << "indexing error " << trueindex << " " << _elem.size() << endl;
228  for ( size_t i = 0; i < _twospin.size(); ++i ) {
229  EvtGenReport( EVTGEN_ERROR, "" ) << _twospin[i] << " ";
230  }
231  EvtGenReport( EVTGEN_ERROR, "" ) << endl;
232 
233  for ( size_t i = 0; i < index.size(); ++i ) {
234  EvtGenReport( EVTGEN_ERROR, "" ) << index[i] << " ";
235  }
236  EvtGenReport( EVTGEN_ERROR, "" ) << endl;
237 
238  ::abort();
239  }
240 
241  return _elem[trueindex];
242 }
243 
245 {
246  va_list ap;
247  vector<int> index( _twospin.size() );
248 
249  va_start( ap, i );
250 
251  index[0] = i;
252  for ( size_t n = 1; n < _twospin.size(); ++n )
253  index[n] = va_arg( ap, int );
254 
255  va_end( ap );
256 
257  return ( *this )( index );
258 }
259 
260 const EvtComplex& EvtSpinAmp::operator()( int i, ... ) const
261 {
262  vector<int> index( _twospin.size() );
263  va_list ap;
264 
265  va_start( ap, i );
266 
267  index[0] = i;
268  for ( size_t n = 1; n < _twospin.size(); ++n )
269  index[n] = va_arg( ap, int );
270 
271  va_end( ap );
272 
273  return ( *this )( index );
274 }
275 
277 {
278  _twospin = cont._twospin;
279  _elem = cont._elem;
280  _type = cont._type;
281 
282  return *this;
283 }
284 
286 {
287  checktwospin( cont._twospin );
288 
289  EvtSpinAmp ret( cont );
290  for ( size_t i = 0; i < ret._elem.size(); ++i ) {
291  ret._elem[i] += _elem[i];
292  }
293 
294  return ret;
295 }
296 
298 {
299  checktwospin( cont._twospin );
300 
301  for ( size_t i = 0; i < _elem.size(); ++i )
302  _elem[i] += cont._elem[i];
303 
304  return *this;
305 }
306 
308 {
309  checktwospin( cont._twospin );
310 
311  EvtSpinAmp ret( *this );
312  for ( size_t i = 0; i < ret._elem.size(); ++i )
313  ret._elem[i] -= cont._elem[i];
314 
315  return ret;
316 }
317 
319 {
320  checktwospin( cont._twospin );
321 
322  for ( size_t i = 0; i < _elem.size(); ++i )
323  _elem[i] -= cont._elem[i];
324 
325  return *this;
326 }
327 
328 // amp = amp1 * amp2
330 {
331  vector<int> index( rank() + amp2.rank() );
332  vector<int> index1( rank() ), index2( amp2.rank() );
333  EvtSpinAmp amp;
334 
335  amp._twospin = _twospin;
336  amp._type = _type;
337 
338  for ( size_t i = 0; i < amp2._twospin.size(); ++i ) {
339  amp._twospin.push_back( amp2._twospin[i] );
340  amp._type.push_back( amp2._type[i] );
341  }
342 
343  amp._elem = vector<EvtComplex>( _elem.size() * amp2._elem.size() );
344 
345  for ( size_t i = 0; i < index1.size(); ++i )
346  index[i] = index1[i] = -_twospin[i];
347 
348  for ( size_t i = 0; i < index2.size(); ++i )
349  index[i + rank()] = index2[i] = -amp2._twospin[i];
350 
351  while ( true ) {
352  amp( index ) = ( *this )(index1)*amp2( index2 );
353  if ( !amp.iterate( index ) )
354  break;
355 
356  for ( size_t i = 0; i < index1.size(); ++i )
357  index1[i] = index[i];
358 
359  for ( size_t i = 0; i < index2.size(); ++i )
360  index2[i] = index[i + rank()];
361  }
362 
363  return amp;
364 }
365 
367 {
368  EvtSpinAmp ret = ( *this ) * cont;
369  *this = ret;
370  return *this;
371 }
372 
374 {
375  for ( size_t i = 0; i < _elem.size(); ++i )
376  _elem[i] *= real;
377 
378  return *this;
379 }
380 
382 {
383  for ( size_t i = 0; i < _elem.size(); ++i )
384  _elem[i] /= real;
385 
386  return *this;
387 }
388 
389 vector<int> EvtSpinAmp::iterinit() const
390 {
391  vector<int> init( _twospin.size() );
392 
393  for ( size_t i = 0; i < _twospin.size(); ++i )
394  init[i] = -_twospin[i];
395 
396  return init;
397 }
398 
399 bool EvtSpinAmp::iterate( vector<int>& index ) const
400 {
401  int last = _twospin.size() - 1;
402 
403  index[0] += 2;
404  for ( size_t j = 0; static_cast<int>( j ) < last; ++j ) {
405  if ( index[j] > static_cast<int>( _twospin[j] ) ) {
406  index[j] = -_twospin[j];
407  index[j + 1] += 2;
408  }
409  }
410 
411  return ( abs( index[last] ) ) <= ( (int)_twospin[last] );
412 }
413 
414 // Test whether a particular index is an allowed one (specifically to deal with
415 // photons and possibly neutrinos)
416 bool EvtSpinAmp::allowed( const vector<int>& index ) const
417 {
418  if ( index.size() != _type.size() ) {
419  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
420  << "Wrong dimensino index input to allowed." << endl;
421  ::abort();
422  }
423 
424  for ( size_t i = 0; i < index.size(); ++i ) {
425  switch ( _type[i] ) {
426  case EvtSpinType::PHOTON:
427  if ( abs( index[i] ) != 2 )
428  return false;
429  break;
431  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
432  << "EvMultibody currently cannot handle neutrinos." << endl;
433  ::abort();
434  default:
435  break;
436  }
437  }
438 
439  return true;
440 }
441 
442 bool EvtSpinAmp::iterateallowed( vector<int>& index ) const
443 {
444  while ( true ) {
445  if ( !iterate( index ) )
446  return false;
447  if ( allowed( index ) )
448  return true;
449  }
450 }
451 
452 vector<int> EvtSpinAmp::iterallowedinit() const
453 {
454  vector<int> init = iterinit();
455  while ( !allowed( init ) ) {
456  iterate( init );
457  }
458 
459  return init;
460 }
461 
462 void EvtSpinAmp::intcont( size_t a, size_t b )
463 {
464  if ( rank() <= 2 ) {
465  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
466  << "EvtSpinAmp can't handle no indices" << endl;
467  ::abort();
468  }
469 
470  size_t newrank = rank() - 2;
471 
472  if ( _twospin[a] != _twospin[b] ) {
473  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
474  << "Contaction called on indices of different dimension" << endl;
475  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
476  << "Called on " << _twospin[a] << " and " << _twospin[b] << endl;
477  ::abort();
478  }
479 
480  vector<int> newtwospin( newrank );
481  vector<EvtSpinType::spintype> newtype( newrank );
482 
483  for ( size_t i = 0, j = 0; i < _twospin.size(); ++i ) {
484  if ( i == a || i == b )
485  continue;
486 
487  newtwospin[j] = _twospin[i];
488  newtype[j] = _type[i];
489  ++j;
490  }
491 
492  EvtSpinAmp newamp( newtype );
493  vector<int> index( rank() ), newindex = newamp.iterinit();
494 
495  for ( size_t i = 0; i < newrank; ++i )
496  newindex[i] = -newtwospin[i];
497 
498  while ( true ) {
499  for ( size_t i = 0, j = 0; i < rank(); ++i ) {
500  if ( i == a || i == b )
501  continue;
502  index[i] = newindex[j];
503  ++j;
504  }
505 
506  index[b] = index[a] = -_twospin[a];
507  newamp( newindex ) = ( *this )( index );
508  for ( size_t i = -_twospin[a] + 2; i <= _twospin[a]; i += 2 ) {
509  index[b] = index[a] = i;
510  newamp( newindex ) += ( *this )( index );
511  }
512 
513  if ( !newamp.iterate( newindex ) )
514  break;
515  }
516 
517  *this = newamp;
518 }
519 
520 // In A.extcont(B), a is the index in A and b is the index in B - note that this
521 // routine can be extremely improved!
522 void EvtSpinAmp::extcont( const EvtSpinAmp& cont, int a, int b )
523 {
524  EvtSpinAmp ret = ( *this ) * cont;
525  ret.intcont( a, rank() + b );
526 
527  *this = ret;
528 }
size_t rank() const
Definition: EvtSpinAmp.hh:81
EvtSpinAmp operator/(const EvtSpinAmp &cont, const EvtComplex &real)
Definition: EvtSpinAmp.cpp:62
EvtSpinAmp & operator/=(const EvtComplex &)
Definition: EvtSpinAmp.cpp:381
bool iterateallowed(vector< int > &index) const
Definition: EvtSpinAmp.cpp:442
EvtComplex & operator()(const vector< int > &)
Definition: EvtSpinAmp.cpp:196
void extcont(const EvtSpinAmp &, int, int)
Definition: EvtSpinAmp.cpp:522
void checktwospin(const vector< unsigned int > &twospin) const
Definition: EvtSpinAmp.cpp:138
vector< int > iterallowedinit() const
Definition: EvtSpinAmp.cpp:452
std::ostream & EvtGenReport(EvtGenSeverity severity, const char *facility=0)
Definition: EvtReport.cpp:33
void checkindexargs(const vector< int > &index) const
Definition: EvtSpinAmp.cpp:149
EvtComplex cont(const EvtTensor4C &t1, const EvtTensor4C &t2)
EvtSpinAmp & operator+=(const EvtSpinAmp &)
Definition: EvtSpinAmp.cpp:297
int findtrueindex(const vector< int > &index) const
Definition: EvtSpinAmp.cpp:182
EvtSpinAmp & operator=(const EvtSpinAmp &)
Definition: EvtSpinAmp.cpp:276
vector< unsigned int > _twospin
Definition: EvtSpinAmp.hh:106
std::ostream & operator<<(std::ostream &os, const EvtSpinAmp &amp)
Definition: EvtSpinAmp.cpp:30
vector< unsigned int > calctwospin(const vector< EvtSpinType::spintype > &type) const
Definition: EvtSpinAmp.cpp:73
bool allowed(const vector< int > &index) const
Definition: EvtSpinAmp.cpp:416
EvtSpinAmp & operator-=(const EvtSpinAmp &)
Definition: EvtSpinAmp.cpp:318
vector< int > iterinit() const
Definition: EvtSpinAmp.cpp:389
EvtSpinAmp operator *(const EvtComplex &real, const EvtSpinAmp &cont)
Definition: EvtSpinAmp.cpp:46
double abs(const EvtComplex &c)
Definition: EvtComplex.hh:201
EvtSpinAmp & operator *=(const EvtSpinAmp &)
Definition: EvtSpinAmp.cpp:366
bool iterate(vector< int > &index) const
Definition: EvtSpinAmp.cpp:399
static int getSpin2(spintype stype)
Definition: EvtSpinType.cpp:26
friend EvtSpinAmp operator *(const EvtComplex &, const EvtSpinAmp &)
Definition: EvtSpinAmp.cpp:46
EvtSpinAmp operator+(const EvtSpinAmp &) const
Definition: EvtSpinAmp.cpp:285
EvtSpinAmp operator-(const EvtSpinAmp &) const
Definition: EvtSpinAmp.cpp:307
void intcont(size_t, size_t)
Definition: EvtSpinAmp.cpp:462
double real(const EvtComplex &c)
Definition: EvtComplex.hh:230
vector< EvtSpinType::spintype > _type
Definition: EvtSpinAmp.hh:105
vector< EvtComplex > _elem
Definition: EvtSpinAmp.hh:107