BOSS 8.0.0
BESIII Offline Software System
Loading...
Searching...
No Matches
EvtSpinAmp.cc
Go to the documentation of this file.
1#include "EvtSpinAmp.hh"
2#include "EvtPatches.hh"
3#include "EvtReport.hh"
4#include <cstdlib>
5
6using std::endl;
7
8std::ostream& operator<<( std::ostream& os, const EvtSpinAmp& amp ) {
9 vector<int> index = amp.iterinit();
10
11 os << ":";
12 do {
13 os << "<";
14 for ( int i = 0; i < index.size() - 1; ++i ) { os << index[i]; }
15 os << index[index.size() - 1] << ">" << amp( index ) << ":";
16 } while ( amp.iterate( index ) );
17
18 return os;
22 EvtSpinAmp ret( cont );
23
24 for ( int i = 0; i < ret._elem.size(); ++i ) { ret._elem[i] *= real; }
25
26 return ret;
27}
28
29EvtSpinAmp operator*( const EvtSpinAmp& cont, const EvtComplex& real ) { return real * cont; }
30
32 EvtSpinAmp ret( cont );
33
34 for ( int i = 0; i < ret._elem.size(); ++i ) { ret._elem[i] /= real; }
35
36 return ret;
37}
38
39vector<int> EvtSpinAmp::calctwospin( const vector<EvtSpinType::spintype>& type ) const {
40 vector<int> twospin;
41
42 for ( int i = 0; i < type.size(); ++i )
43 { twospin.push_back( EvtSpinType::getSpin2( type[i] ) ); }
44
45 return twospin;
46}
47
48EvtSpinAmp::EvtSpinAmp( const vector<EvtSpinType::spintype>& type ) {
49 int num = 1;
50 _type = type;
51 _twospin = calctwospin( type );
52
53 for ( int i = 0; i < _twospin.size(); ++i ) num *= _twospin[i] + 1;
54
55 _elem = vector<EvtComplex>( num );
56}
57
58EvtSpinAmp::EvtSpinAmp( const vector<EvtSpinType::spintype>& type, const EvtComplex& val ) {
59 int num = 1;
60 _type = type;
61 _twospin = calctwospin( type );
62
63 for ( int i = 0; i < _twospin.size(); ++i ) num *= _twospin[i] + 1;
64
65 _elem = vector<EvtComplex>( num, val );
66}
67
68EvtSpinAmp::EvtSpinAmp( const vector<EvtSpinType::spintype>& type,
69 const vector<EvtComplex>& elem ) {
70 int num = 1;
71
72 _type = type;
73 _twospin = calctwospin( type );
74 _elem = elem;
75
76 for ( int i = 0; i < _twospin.size(); ++i ) num *= _twospin[i] + 1;
77
78 if ( _elem.size() != num )
79 {
80 report( ERROR, "EvtGen" ) << "Wrong number of elements input:" << _elem.size() << " vs. "
81 << num << endl;
82 ::abort();
83 }
84}
85
87 _twospin = copy._twospin;
88 _elem = copy._elem;
89 _type = copy._type;
90}
91
92void EvtSpinAmp::checktwospin( const vector<int>& twospin ) const {
93 if ( _twospin == twospin ) return;
94
95 report( ERROR, "EvtGen" ) << "Dimension or order of tensors being operated on does not match"
96 << endl;
97 ::abort();
98}
99
100void EvtSpinAmp::checkindexargs( const vector<int>& index ) const {
101 if ( index.size() == 0 )
102 {
103 report( ERROR, "EvtGen" ) << "EvtSpinAmp can't handle no indices" << endl;
104 ::abort();
105 }
106
107 if ( index.size() != _twospin.size() )
108 {
109 report( ERROR, "EvtGen" ) << "Rank of EvtSpinAmp index does not match: " << _twospin.size()
110 << " expected " << index.size() << " input." << endl;
111 ::abort();
112 }
113
114 for ( int i = 0; i < _twospin.size(); ++i )
115 {
116 if ( _twospin[i] >= abs( index[i] ) && _twospin[i] % 2 == index[i] % 2 ) continue;
117 report( ERROR, "EvtGen" ) << "EvtSpinAmp index out of range" << endl;
118 report( ERROR, "EvtGen" ) << " Index: ";
119 for ( int j = 0; j < _twospin.size(); ++j ) report( ERROR, " " ) << _twospin[j];
120
121 report( ERROR, " " ) << endl << " Index: ";
122 for ( int j = 0; j < index.size(); ++j ) report( ERROR, " " ) << index[j];
123 report( ERROR, " " ) << endl;
124 ::abort();
125 }
126}
127
128int EvtSpinAmp::findtrueindex( const vector<int>& index ) const {
129 int trueindex = 0;
130
131 for ( int i = index.size() - 1; i > 0; --i )
132 {
133 trueindex += ( index[i] + _twospin[i] ) / 2;
134 trueindex *= _twospin[i - 1] + 1;
135 }
136
137 trueindex += ( index[0] + _twospin[0] ) / 2;
138
139 return trueindex;
140}
141
142EvtComplex& EvtSpinAmp::operator()( const vector<int>& index ) {
143 checkindexargs( index );
144
145 int trueindex = findtrueindex( index );
146 if ( trueindex >= _elem.size() )
147 {
148 report( ERROR, "EvtGen" ) << "indexing error " << trueindex << " " << _elem.size() << endl;
149 for ( int i = 0; i < _twospin.size(); ++i ) { report( ERROR, "" ) << _twospin[i] << " "; }
150 report( ERROR, "" ) << endl;
151
152 for ( int i = 0; i < index.size(); ++i ) { report( ERROR, "" ) << index[i] << " "; }
153 report( ERROR, "" ) << endl;
154
155 ::abort();
156 }
157
158 return _elem[trueindex];
159}
160
161const EvtComplex& EvtSpinAmp::operator()( const vector<int>& index ) const {
162 checkindexargs( index );
163
164 int trueindex = findtrueindex( index );
165 if ( trueindex >= _elem.size() )
166 {
167 report( ERROR, "EvtGen" ) << "indexing error " << trueindex << " " << _elem.size() << endl;
168 for ( int i = 0; i < _twospin.size(); ++i ) { report( ERROR, "" ) << _twospin[i] << " "; }
169 report( ERROR, "" ) << endl;
170
171 for ( int i = 0; i < index.size(); ++i ) { report( ERROR, "" ) << index[i] << " "; }
172 report( ERROR, "" ) << endl;
173
174 ::abort();
175 }
176
177 return _elem[trueindex];
178}
179
181 va_list ap;
182 vector<int> index( _twospin.size() );
183
184 va_start( ap, i );
185
186 index[0] = i;
187 for ( int n = 1; n < _twospin.size(); ++n ) index[n] = va_arg( ap, int );
188
189 va_end( ap );
190
191 return ( *this )( index );
192}
193
194const EvtComplex& EvtSpinAmp::operator()( int i, ... ) const {
195 vector<int> index( _twospin.size() );
196 va_list ap;
197
198 va_start( ap, i );
199
200 index[0] = i;
201 for ( int n = 1; n < _twospin.size(); ++n ) index[n] = va_arg( ap, int );
202
203 va_end( ap );
204
205 return ( *this )( index );
206}
207
209 _twospin = cont._twospin;
210 _elem = cont._elem;
211 _type = cont._type;
212
213 return *this;
214}
215
217 checktwospin( cont._twospin );
218
219 EvtSpinAmp ret( cont );
220 for ( int i = 0; i < ret._elem.size(); ++i ) { ret._elem[i] += _elem[i]; }
221
222 return ret;
223}
224
226 checktwospin( cont._twospin );
227
228 for ( int i = 0; i < _elem.size(); ++i ) _elem[i] += cont._elem[i];
229
230 return *this;
231}
232
234 checktwospin( cont._twospin );
235
236 EvtSpinAmp ret( *this );
237 for ( int i = 0; i < ret._elem.size(); ++i ) ret._elem[i] -= cont._elem[i];
238
239 return ret;
240}
241
243 checktwospin( cont._twospin );
244
245 for ( int i = 0; i < _elem.size(); ++i ) _elem[i] -= cont._elem[i];
246
247 return *this;
248}
249
250// amp = amp1 * amp2
252 vector<int> index( rank() + amp2.rank() );
253 vector<int> index1( rank() ), index2( amp2.rank() );
254 EvtSpinAmp amp;
255
256 amp._twospin = _twospin;
257 amp._type = _type;
258
259 for ( int i = 0; i < amp2._twospin.size(); ++i )
260 {
261 amp._twospin.push_back( amp2._twospin[i] );
262 amp._type.push_back( amp2._type[i] );
263 }
264
265 amp._elem = vector<EvtComplex>( _elem.size() * amp2._elem.size() );
266
267 for ( int i = 0; i < index1.size(); ++i ) index[i] = index1[i] = -_twospin[i];
268
269 for ( int i = 0; i < index2.size(); ++i ) index[i + rank()] = index2[i] = -amp2._twospin[i];
270
271 while ( true )
272 {
273 amp( index ) = ( *this )(index1)*amp2( index2 );
274 if ( !amp.iterate( index ) ) break;
275
276 for ( int i = 0; i < index1.size(); ++i ) index1[i] = index[i];
277
278 for ( int i = 0; i < index2.size(); ++i ) index2[i] = index[i + rank()];
279 }
280
281 return amp;
282}
283
285 EvtSpinAmp ret = ( *this ) * cont;
286 *this = ret;
287 return *this;
288}
289
291 for ( int i = 0; i < _elem.size(); ++i ) _elem[i] *= real;
292
293 return *this;
294}
295
297 for ( int i = 0; i < _elem.size(); ++i ) _elem[i] /= real;
298
299 return *this;
300}
301
302vector<int> EvtSpinAmp::iterinit() const {
303 vector<int> init( _twospin.size() );
304
305 for ( int i = 0; i < _twospin.size(); ++i ) init[i] = -_twospin[i];
306
307 return init;
308}
309
310bool EvtSpinAmp::iterate( vector<int>& index ) const {
311 int last = _twospin.size() - 1;
312
313 index[0] += 2;
314 for ( int j = 0; j < last; ++j )
315 {
316 if ( index[j] > _twospin[j] )
317 {
318 index[j] = -_twospin[j];
319 index[j + 1] += 2;
320 }
321 }
322
323 return abs( index[last] ) <= _twospin[last];
324}
325
326// Test whether a particular index is an allowed one (specifically to deal with
327// photons and possibly neutrinos)
328bool EvtSpinAmp::allowed( const vector<int>& index ) const {
329 if ( index.size() != _type.size() )
330 {
331 report( ERROR, "EvtGen" ) << "Wrong dimensino index input to allowed." << endl;
332 ::abort();
333 }
334
335 for ( int i = 0; i < index.size(); ++i )
336 {
337 switch ( _type[i] )
338 {
340 if ( abs( index[i] ) != 2 ) return false;
341 break;
343 report( ERROR, "EvtGen" ) << "EvMultibody currently cannot handle neutrinos." << endl;
344 ::abort();
345 default: break;
346 }
347 }
348
349 return true;
350}
351
352bool EvtSpinAmp::iterateallowed( vector<int>& index ) const {
353 while ( true )
354 {
355 if ( !iterate( index ) ) return false;
356 if ( allowed( index ) ) return true;
357 }
358}
359
360vector<int> EvtSpinAmp::iterallowedinit() const {
361 vector<int> init = iterinit();
362 while ( !allowed( init ) ) { iterate( init ); }
363
364 return init;
365}
366
367void EvtSpinAmp::intcont( int a, int b ) {
368 int newrank = rank() - 2;
369 if ( newrank <= 0 )
370 {
371 report( ERROR, "EvtGen" ) << "EvtSpinAmp can't handle no indices" << endl;
372 ::abort();
373 }
374
375 if ( _twospin[a] != _twospin[b] )
376 {
377 report( ERROR, "EvtGen" ) << "Contaction called on indices of different dimension" << endl;
378 report( ERROR, "EvtGen" ) << "Called on " << _twospin[a] << " and " << _twospin[b] << endl;
379 ::abort();
380 }
381
382 vector<int> newtwospin( newrank );
383 vector<EvtSpinType::spintype> newtype( newrank );
384
385 for ( int i = 0, j = 0; i < _twospin.size(); ++i )
386 {
387 if ( i == a || i == b ) continue;
388
389 newtwospin[j] = _twospin[i];
390 newtype[j] = _type[i];
391 ++j;
392 }
393
394 EvtSpinAmp newamp( newtype );
395 vector<int> index( rank() ), newindex = newamp.iterinit();
396
397 for ( int i = 0; i < newrank; ++i ) newindex[i] = -newtwospin[i];
398
399 while ( true )
400 {
401
402 for ( int i = 0, j = 0; i < rank(); ++i )
403 {
404 if ( i == a || i == b ) continue;
405 index[i] = newindex[j];
406 ++j;
407 }
408
409 index[b] = index[a] = -_twospin[a];
410 newamp( newindex ) = ( *this )( index );
411 for ( int i = -_twospin[a] + 2; i <= _twospin[a]; i += 2 )
412 {
413 index[b] = index[a] = i;
414 newamp( newindex ) += ( *this )( index );
415 }
416
417 if ( !newamp.iterate( newindex ) ) break;
418 }
419
420 *this = newamp;
421}
422
423// In A.extcont(B), a is the index in A and b is the index in B - note that this
424// routine can be extremely improved!
425void EvtSpinAmp::extcont( const EvtSpinAmp& cont, int a, int b ) {
426 EvtSpinAmp ret = ( *this ) * cont;
427 ret.intcont( a, rank() + b );
428
429 *this = ret;
430}
const Int_t n
ostream & report(Severity severity, const char *facility)
Definition EvtReport.cc:34
@ ERROR
Definition EvtReport.hh:49
std::ostream & operator<<(std::ostream &os, const EvtSpinAmp &amp)
Definition EvtSpinAmp.cc:8
EvtSpinAmp operator*(const EvtComplex &real, const EvtSpinAmp &cont)
Definition EvtSpinAmp.cc:21
EvtSpinAmp operator/(const EvtSpinAmp &cont, const EvtComplex &real)
Definition EvtSpinAmp.cc:31
EvtComplex cont(const EvtTensor4C &t1, const EvtTensor4C &t2)
EvtComplex & operator()(const vector< int > &)
EvtSpinAmp & operator-=(const EvtSpinAmp &)
EvtSpinAmp & operator=(const EvtSpinAmp &)
vector< int > iterinit() const
bool iterate(vector< int > &index) const
bool iterateallowed(vector< int > &index) const
EvtSpinAmp & operator*=(const EvtSpinAmp &)
EvtSpinAmp operator+(const EvtSpinAmp &) const
int rank() const
Definition EvtSpinAmp.hh:62
vector< int > iterallowedinit() const
EvtSpinAmp & operator+=(const EvtSpinAmp &)
bool allowed(const vector< int > &index) const
EvtSpinAmp & operator/=(const EvtComplex &)
friend EvtSpinAmp operator*(const EvtComplex &, const EvtSpinAmp &)
Definition EvtSpinAmp.cc:21
void intcont(int, int)
void extcont(const EvtSpinAmp &, int, int)
EvtSpinAmp operator-(const EvtSpinAmp &) const
static int getSpin2(spintype stype)