BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
SamplerAnalysis.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2023.
4
5This file is part of BDSIM.
6
7BDSIM is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published
9by the Free Software Foundation version 3 of the License.
10
11BDSIM is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "SamplerAnalysis.hh"
20#include "rebdsim.hh"
21
22#include <cmath>
23#include <vector>
24
25double SamplerAnalysis::particleMass = 0;
26
27SamplerAnalysis::SamplerAnalysis():
28 s(nullptr),
29 npart(0),
30 S(0),
31 debug(false)
32{
33 CommonCtor();
34}
35
36#ifndef __ROOTDOUBLE__
37SamplerAnalysis::SamplerAnalysis(BDSOutputROOTEventSampler<float> *samplerIn,
38 bool debugIn):
39#else
41 bool debugIn):
42#endif
43 s(samplerIn),
44 npart(0),
45 S(0),
46 debug(debugIn)
47{
48 CommonCtor();
49}
50
52{
53 int id = s->s->partID[0];
54 switch (std::abs(id))
55 {
56 case 11:
57 case -11:
58 {
59 std::cout << "Primary particle: e-" << std::endl;
60 particleMass = 0.000510999; break;}
61 case 2212:
62 {
63 std::cout << "Primary particle: proton" << std::endl;
64 particleMass = 0.938272; break;}
65 default:
66 {
67 std::cout << "Primary particle: unknown -> m=0" << std::endl;
68 particleMass = 0; break;}
69 }
70}
71
72void SamplerAnalysis::UpdateMass(const std::string& particleName)
73{
74 if ((particleName == "e-") || (particleName == "e+"))
75 {
76 std::cout << "Primary particle: e-" << std::endl;
77 particleMass = 0.000510999;;
78 }
79 else if (particleName == "proton")
80 {
81 std::cout << "Primary particle: proton" << std::endl;
82 particleMass = 0.938272;
83 }
84 else
85 {
86 std::cout << "Primary particle: unknown -> m=0" << std::endl;
87 particleMass = 0;
88 }
89}
90
92{
93 npart = 0;
94
95 // initialise a vector to store the coordinates of every event in a sampler
96 coordinates.resize(6, 0);
97
98 // initialise a vector to store the first values in a sampler for assumed mean subtraction
99 offsets.resize(6, 0);
100
101 optical.resize(3); // resize to 3 entries initialised to 0
102 varOptical.resize(3);
103 for(int i=0;i<3;++i)
104 {
105 optical[i].resize(25, 0); // 12 for central values and 12 for errors and 1 for xy correlation
106 varOptical[i].resize(12, 0);
107 }
108
109 covMats.resize(3);
110 for(int i=0;i<3;++i)
111 {
112 covMats[i].resize(3);
113 for(int j=0;j<3;++j)
114 {covMats[i][j].resize(3, 0);}
115 }
116
117 derivMats.resize(3);
118 for(int i=0;i<3;++i)
119 {
120 derivMats[i].resize(12);
121 for(int j=0;j<12;++j)
122 {derivMats[i][j].resize(3, 0);}
123 }
124
125 powSums.resize(6);
126 cenMoms.resize(6);
127
128 powSumsFirst.resize(6); // first sampler
129 cenMomsFirst.resize(6);
130
131 // (x,xp,y,yp,E,t) (x,xp,y,yp,E,t) v1pow, v2pow
132 for(int i=0;i<6;++i)
133 {
134 powSums[i].resize(6);
135 cenMoms[i].resize(6);
136
137 powSumsFirst[i].resize(6);
138 cenMomsFirst[i].resize(6);
139
140 for(int j=0;j<6;++j)
141 {
142 powSums[i][j].resize(5);
143 cenMoms[i][j].resize(5);
144
145 powSumsFirst[i][j].resize(5);
146 cenMomsFirst[i][j].resize(5);
147
148 for(int k=0;k<=4;++k)
149 {
150 powSums[i][j][k].resize(5, 0);
151 cenMoms[i][j][k].resize(5, 0);
152
153 powSumsFirst[i][j][k].resize(5, 0);
154 cenMomsFirst[i][j][k].resize(5, 0);
155 }
156 }
157 }
158}
159
160SamplerAnalysis::~SamplerAnalysis()
161{;}
162
164{
165 npart = 0;
166}
167
168void SamplerAnalysis::Process(bool firstTime)
169{
170 if(debug)
171 {std::cout << __METHOD_NAME__ << "\"" << s->samplerName << "\" with " << s->n << " entries" << std::endl;}
172
173 double m2 = std::pow(particleMass,2);
174
175 // loop over all entries
176 for(int i=0;i<s->n;++i)
177 {
178 if (i == 0)
179 {S = s->S;} // update sampler on first round - do here so not to load default data
180 if (s->parentID[i] != 0)
181 {continue;} // select only primary particles
182 if (s->turnNumber[i] > 1)
183 {continue;} // only use first turn particles
184 if (s->zp[i] <= 0)
185 {continue;} // only forward going particles - sampler can intercept backwards particles
186
187 coordinates[0] = s->x[i];
188 coordinates[1] = s->xp[i];
189 coordinates[2] = s->y[i];
190 coordinates[3] = s->yp[i];
191 coordinates[4] = std::sqrt(std::pow(s->energy[i],2) - m2); // p = sqrt(E^2 - M^2)
192 coordinates[5] = s->T[i];
193
194 if (firstTime)
195 {offsets = coordinates;}
196
197 // power sums
198 for(int a=0;a<6;++a)
199 {
200 for(int b=0;b<6;++b)
201 {
202 for (int j = 0; j <= 4; ++j)
203 {
204 for (int k = 0; k <= 4; ++k)
205 {
206 powSums[a][b][j][k] += std::pow(coordinates[a]-offsets[a],j)*std::pow(coordinates[b]-offsets[b],k);
207 }
208 }
209 }
210 }
211 npart++;
212 }
213}
214
215std::vector<double> SamplerAnalysis::Terminate(std::vector<double> emittance,
216 bool useEmittanceFromFirstSampler)
217{
218 if(debug)
219 {std::cout << " " << __METHOD_NAME__ << s->modelID << " " << npart << std::flush;}
220
221 // determine whether the input emittance is non-zero
222 bool nonZeroEmittanceIn = !std::all_of(emittance.begin(), emittance.end(), [](double l) { return l==0; });
223
224 // central moments
225 for(int a=0;a<6;++a)
226 {
227 for(int b=0;b<6;++b)
228 {
229 for (int j = 0; j <= 4; ++j)
230 {
231 for (int k = 0; k <= 4; ++k)
232 {
233 cenMoms[a][b][j][k] = powSumToCentralMoment(powSums, npart, a, b, j, k);
234 }
235 }
236 }
237 }
238
239 if (debug)
240 {printBeamCorrelationMatrix(cenMoms);}
241
242 // optical function calculation
243 for(int i=0;i<3;++i)
244 {
245 int j = 0;
246 if(i == 1) j = 2;
247 if(i == 2) j = 4;
248
249 // note: optical functions vector not populated in sequential order in order
250 // to apply dispersion correction to lattice funcs.
251
252 optical[i][6] = cenMoms[j][j+1][1][0]; // mean spatial (transv.)/ mean P (longit.)
253 optical[i][7] = cenMoms[j][j+1][0][1]; // mean divergence (transv.)/ mean t (longit.)
254 optical[i][8] = sqrt(cenMoms[j][j+1][2][0]); // sigma spatial (transv.)/ sigma P (longit.)
255 optical[i][9] = sqrt(cenMoms[j][j+1][0][2]); // sigma divergence (transv.)/ sigma t (longit.)
256
257 // transverse optical function calculation skipped for longitudinal plane,
258 // only mean and sigma of longit. coordinates recorded
259 if (i==2)
260 {continue;}
261
262 optical[i][4] = (cenMoms[4][4][1][0]*cenMoms[j][4][1][1])/cenMoms[4][4][2][0]; // eta
263 optical[i][5] = (cenMoms[4][4][1][0]*cenMoms[j+1][4][1][1])/cenMoms[4][4][2][0]; // eta prime
264
265 // check for nans (expected if dP=0) and set disp=0 if found
266 if (!std::isfinite(optical[i][4]))
267 {optical[i][4] = 0;}
268 if (!std::isfinite(optical[i][5]))
269 {optical[i][5] = 0;}
270
271 // temp variables to store dispersion corrected moments, aka moments without dispersion contribution
272 double corrCentMom_2_0 = 0.0, corrCentMom_1_1 = 0.0;
273 double corrCentMom_0_2 = 0.0;
274
275 //Correction example: var[x]_corrected = var[x] - eta_x^2*sigma[dP/P]^2
276 corrCentMom_2_0 =
277 cenMoms[j][j+1][2][0] - std::pow(optical[i][4],2)*cenMoms[4][4][2][0]/std::pow(cenMoms[4][4][1][0],2);
278
279 corrCentMom_0_2 =
280 cenMoms[j][j+1][0][2] - std::pow(optical[i][5],2)*cenMoms[4][4][2][0]/std::pow(cenMoms[4][4][1][0],2);
281
282 corrCentMom_1_1 =
283 cenMoms[j][j+1][1][1] - (optical[i][4]*optical[i][5])*cenMoms[4][4][2][0]/std::pow(cenMoms[4][4][1][0],2);
284
285 if(useEmittanceFromFirstSampler && nonZeroEmittanceIn)
286 {optical[i][0] = emittance[i];}
287 else
288 {optical[i][0] = sqrt(corrCentMom_2_0 * corrCentMom_0_2 - std::pow(corrCentMom_1_1, 2));} //emittance
289
290 optical[i][1] = -corrCentMom_1_1/optical[i][0]; // alpha
291 optical[i][2] = corrCentMom_2_0/optical[i][0]; // beta
292 optical[i][3] = (1+std::pow(optical[i][1],2))/optical[i][2]; // gamma
293
294 optical[i][10] = S;
295 optical[i][11] = (double)npart;
296 }
297
298 // statistical error calculation
299
300 // covariance matrix of central moments for optical functions.
301 for(int i=0;i<3;++i)
302 {
303 for(int j=0;j<3;++j)
304 {
305 for(int k=0;k<3;++k)
306 {
307 covMats[i][j][k]=centMomToCovariance(cenMoms, npart, i, j, k);
308 }
309 }
310 }
311
312 // derivative matrix of parameters for optical functions. Each entry is
313 // a first order derivative w.r.t central moments.
314 for(int i=0;i<3;++i)
315 {
316 for(int j=0;j<12;++j) //loop over optical functions.
317 {
318 for(int k=0;k<3;++k) //loop over derivative indices
319 {
320 derivMats[i][j][k]=centMomToDerivative(cenMoms, i, j, k);
321 }
322 }
323 }
324
325 // compute variances of optical functions
326 for(int i=0;i<3;++i)
327 {
328 for(int j=0;j<12;++j)
329 {
330 for(int k=0;k<3;++k)
331 {
332 for(int l=0;l<3;++l)
333 {
334 varOptical[i][j] += derivMats[i][j][k]*derivMats[i][j][l]*covMats[i][k][l];
335 }
336 }
337 }
338 }
339
340 // compute the sigmas of optical functions
341 for(int i=0;i<3;++i)
342 {
343 for(int j=0;j<12;++j)
344 {
345 if(j==6 || j==7)
346 {optical[i][j+12]=optical[i][j+2]/sqrt(npart);} //errors of the means
347 else if(j == 10 || j == 11)
348 {optical[i][j+12]= 0.0;} //no errors on S and Npart
349 else if (j==0)
350 {
351 if(useEmittanceFromFirstSampler && nonZeroEmittanceIn)
352 {
353 optical[i][j+12]=emittance[j+2];
354 }
355 else
356 {
357 optical[i][j+12]=sqrt(varOptical[i][j]);
358 }
359 }
360 else
361 {optical[i][j+12]=sqrt(varOptical[i][j]);}
362 }
363 }
364
365 // convert meanP back to meanE
366 double m2 = std::pow(particleMass,2);
367 double meanP = optical[2][6];
368 optical[2][6] = std::sqrt(std::pow(meanP,2) + m2);
369
370 //convert sigmaP back to SigmaE
371 double gamma = optical[2][6] / particleMass;
372 double beta = std::sqrt(1.0 - 1.0/std::pow(gamma,2));
373 double sigmaP = optical[2][8];
374 optical[2][8] = (sigmaP/meanP)*std::pow(beta,2);
375
376 // write out the correlation x-y coefficient to the output as a matrix of horizontal-vertical coupling
377 // writen only to the x vector, but 0 is added to y and z vectors to keep all vector sizes the same
378 optical[0][24]=cenMoms[0][2][1][1]/std::sqrt(cenMoms[0][2][2][0]*cenMoms[0][2][0][2]);
379
380 // emitt_x, emitt_y, err_emitt_x, err_emitt_y
381 std::vector<double> emittanceOut = {optical[0][0],
382 optical[1][0],
383 optical[0][12],
384 optical[1][12]};
385
386 return emittanceOut;
387}
388
389double SamplerAnalysis::powSumToCentralMoment(fourDArray& powSumsIn,
390 long long int npartIn,
391 int a,
392 int b,
393 int m,
394 int n)
395{
396 double moment = 0.0;
397
398 // Explicitly multiply out the number of particles to achieve the appropriate power.
399 // Typecast to a double is done to avoid integer overflow for large number of particles.
400 double npartPow1 = (double)npartIn;
401
402 // Done because of potential problems with the pow() funtion in C++ where some
403 // arguments cause NaNs
404 double npartPow2 = npartPow1 * npartPow1;
405 double npartPow3 = npartPow2 * npartPow1;
406 double npartPow4 = npartPow3 * npartPow1;
407
408 if((m == 1 && n == 0) || (m == 0 && n == 1))
409 {
410 double s_1_0 = powSumsIn[a][b][m][n];
411 int k = m > n ? a : b;
412
413 moment = s_1_0/(double)npartIn+offsets[k];
414 }
415
416 else if((n == 2 && m == 0) || (n == 0 && m == 2))
417 {
418 double s_1_0 = 0.0, s_2_0 = 0.0;
419 if(m == 2)
420 {
421 s_1_0 = powSumsIn[a][b][m-1][n];
422 s_2_0 = powSumsIn[a][b][m][n];
423 }
424 else if(n == 2)
425 {
426 s_1_0 = powSumsIn[a][b][m][n-1];
427 s_2_0 = powSumsIn[a][b][m][n];
428 }
429
430 moment = (npartPow1*s_2_0 - std::pow(std::abs(s_1_0),2))/(npartPow1*(npartPow1-1));
431 }
432
433 else if(n == 1 && m == 1)
434 {
435 double s_1_0 = 0.0, s_0_1 = 0.0, s_1_1 = 0.0;
436
437 s_1_0 = powSumsIn[a][b][m][n-1];
438 s_0_1 = powSumsIn[a][b][m-1][n];
439 s_1_1 = powSumsIn[a][b][m][n];
440
441 moment = (npartPow1*s_1_1 - s_0_1*s_1_0)/(npartPow1*(npartPow1-1));
442 }
443
444 else if((n == 4 && m == 0) || (n == 0 && m == 4))
445 {
446 double s_1_0 = 0.0, s_2_0 = 0.0, s_3_0 = 0.0, s_4_0 = 0.0;
447 if(m == 4)
448 {
449 s_1_0 = powSumsIn[a][b][m-3][n];
450 s_2_0 = powSumsIn[a][b][m-2][n];
451 s_3_0 = powSumsIn[a][b][m-1][n];
452 s_4_0 = powSumsIn[a][b][m][n];
453 }
454 else if( n == 4)
455 {
456 s_1_0 = powSumsIn[a][b][m][n-3];
457 s_2_0 = powSumsIn[a][b][m][n-2];
458 s_3_0 = powSumsIn[a][b][m][n-1];
459 s_4_0 = powSumsIn[a][b][m][n];
460 }
461
462 moment = - (3*std::pow(s_1_0,4))/npartPow4 + (6*std::pow(s_1_0,2)*s_2_0)/npartPow3
463 - (4*s_1_0*s_3_0)/npartPow2 + s_4_0/npartPow1;
464 }
465
466 else if((m == 3 && n == 1) || (m == 1 && n ==3))
467 {
468 double s_1_0 = 0.0, s_0_1 = 0.0, s_1_1 = 0.0, s_2_0 = 0.0, s_2_1 = 0.0, s_3_0 = 0.0, s_3_1 = 0.0;
469
470 if(m == 3)
471 {
472 s_1_0 = powSumsIn[a][b][m-2][n-1];
473 s_0_1 = powSumsIn[a][b][m-3][n];
474 s_1_1 = powSumsIn[a][b][m-2][n];
475 s_2_0 = powSumsIn[a][b][m-1][n-1];
476 s_2_1 = powSumsIn[a][b][m-1][n];
477 s_3_0 = powSumsIn[a][b][m][n-1];
478 s_3_1 = powSumsIn[a][b][m][n];
479 }
480 else if(n == 3)
481 {
482 s_1_0 = powSumsIn[a][b][m-1][n-2];
483 s_0_1 = powSumsIn[a][b][m][n-3];
484 s_1_1 = powSumsIn[a][b][m][n-2];
485 s_2_0 = powSumsIn[a][b][m-1][n-1];
486 s_2_1 = powSumsIn[a][b][m][n-1];
487 s_3_0 = powSumsIn[a][b][m-1][n];
488 s_3_1 = powSumsIn[a][b][m][n];
489 }
490
491 moment = - (3*s_0_1*std::pow(s_1_0,3))/npartPow4 + (3*s_1_0*s_1_0*s_1_1)/npartPow3
492 + (3*s_0_1*s_1_0*s_2_0)/npartPow3 - (3*s_1_0*s_2_1)/npartPow2
493 - (s_0_1*s_3_0)/npartPow2 + s_3_1/npartPow1;
494 }
495
496 else if(m == 2 && n == 2)
497 {
498 double s_1_0 = 0.0, s_0_1 = 0.0, s_1_1 = 0.0, s_2_0 = 0.0, s_0_2 = 0.0, s_1_2 = 0.0, s_2_1 = 0.0, s_2_2 = 0.0;
499
500 s_1_0 = powSumsIn[a][b][m-1][n-2];
501 s_0_1 = powSumsIn[a][b][m-2][n-1];
502 s_1_1 = powSumsIn[a][b][m-1][n-1];
503 s_2_0 = powSumsIn[a][b][m][n-2];
504 s_0_2 = powSumsIn[a][b][m-2][n];
505 s_1_2 = powSumsIn[a][b][m-1][n];
506 s_2_1 = powSumsIn[a][b][m][n-1];
507 s_2_2 = powSumsIn[a][b][m][n];
508
509 moment = - (3*std::pow(s_0_1,2)*std::pow(s_1_0,2))/npartPow4 + (s_0_2*std::pow(s_1_0,2))/npartPow3
510 + (4*s_0_1*s_1_0*s_1_1)/npartPow3 - (2*s_1_0*s_1_2)/npartPow2
511 + (std::pow(s_0_1,2)*s_2_0)/npartPow3 - (2*s_0_1*s_2_1)/npartPow2 + s_2_2/npartPow1;
512 }
513
514 return moment;
515}
516
517double SamplerAnalysis::centMomToCovariance(fourDArray& centMoms,
518 long long int npartIn,
519 int k,
520 int i,
521 int j)
522{
523 double npartInD = (double)npartIn;
524 double cov = 0.0;
525
526 int a = 0;
527 if(k == 1) {a=2;}
528 if(k == 2) {a=4;}
529
530 if((i == 0 && j == 0) || (i == 1 && j == 1))
531 {
532 double m_4_0 = 0.0, m_2_0 = 0.0;
533
534 if(i == 0)
535 {
536 m_4_0 = centMoms[a][a+1][4][0];
537 m_2_0 = centMoms[a][a+1][2][0];
538 }
539
540 else if(i == 1)
541 {
542 m_4_0 = centMoms[a][a+1][0][4];
543 m_2_0 = centMoms[a][a+1][0][2];
544 }
545
546 cov = -((npartInD-3)*std::pow(m_2_0,2))/(npartInD*(npartInD-1)) + m_4_0/npartInD;
547 }
548
549 else if(i == 2 && j == 2)
550 {
551 double m_1_1 = 0.0, m_2_0 = 0.0, m_0_2 = 0.0, m_2_2 = 0.0;
552
553 m_1_1 = centMoms[a][a+1][1][1];
554 m_2_0 = centMoms[a][a+1][2][0];
555 m_0_2 = centMoms[a][a+1][0][2];
556 m_2_2 = centMoms[a][a+1][2][2];
557
558 cov = -((npartInD-2)*std::pow(m_1_1,2))/(npartInD*(npartInD-1)) + (m_0_2*m_2_0)/(npartInD*(npartInD-1)) + m_2_2/npartInD;
559 }
560
561 else if((i == 0 && j == 2) || (i == 1 && j == 2) || (i == 2 && j == 0) || (i == 2 && j == 1))
562 {
563 double m_1_1 = 0.0, m_2_0 = 0.0, m_3_1 = 0.0;
564
565 if((i == 0 && j == 2) || (i == 2 && j == 0 ))
566 {
567 m_1_1 = centMoms[a][a+1][1][1];
568 m_2_0 = centMoms[a][a+1][2][0];
569 m_3_1 = centMoms[a][a+1][3][1];
570 }
571 else if((i == 1 && j == 2) || (i == 2 && j == 1))
572 {
573 m_1_1 = centMoms[a][a+1][1][1];
574 m_2_0 = centMoms[a][a+1][0][2];
575 m_3_1 = centMoms[a][a+1][1][3];
576 }
577
578 cov = -((npartInD-3)*m_1_1*m_2_0)/(npartInD*(npartInD-1)) + m_3_1/npartInD;
579 }
580 else if((i == 0 && j == 1) || (i == 1 && j == 0) )
581 {
582 double m_1_1 = 0.0, m_2_0 = 0.0, m_0_2 = 0.0, m_2_2 = 0.0;
583
584 m_1_1 = centMoms[a][a+1][1][1];
585 m_2_0 = centMoms[a][a+1][0][2];
586 m_0_2 = centMoms[a][a+1][2][0];
587 m_2_2 = centMoms[a][a+1][2][2];
588
589 cov = 2*std::pow(m_1_1,2)/(npartInD*(npartInD-1)) - m_2_0*m_0_2/npartInD + m_2_2/npartInD;
590 }
591
592 return cov;
593}
594
595double SamplerAnalysis::centMomToDerivative(fourDArray& centMoms,
596 int k,
597 int t,
598 int i)
599
600{
601 double deriv = 0.0;
602
603 int a = 0;
604 if(k == 1) {a=2;}
605 if(k == 2) {a=4;}
606
607 switch(t)
608 {
609 case 0:
610 //emittance
611 if(i == 0 && k < 2) // k<2 check selects transverse planes, longitudinal parameters are not calculated
612 {
613 deriv = centMoms[a][a+1][0][2]/(2*sqrt(centMoms[a][a+1][2][0]*centMoms[a][a+1][0][2]-std::pow(centMoms[a][a+1][1][1],2)));
614 }
615 else if(i == 1 && k < 2)
616 {
617 deriv = centMoms[a][a+1][2][0]/(2*sqrt(centMoms[a][a+1][2][0]*centMoms[a][a+1][0][2]-std::pow(centMoms[a][a+1][1][1],2)));
618 }
619 else if(i == 2 && k < 2)
620 {
621 deriv = -centMoms[a][a+1][1][1]/(sqrt(centMoms[a][a+1][2][0]*centMoms[a][a+1][0][2]-std::pow(centMoms[a][a+1][1][1],2)));
622 }
623 else {deriv=0;}
624
625 return deriv;
626 break;
627
628 case 1:
629 //alpha
630 if(i == 0 && k < 2)
631 {
632 deriv = centMoms[a][a+1][0][2]*centMoms[a][a+1][1][1]/(2*std::pow(centMoms[a][a+1][2][0]*centMoms[a][a+1][0][2]-std::pow(centMoms[a][a+1][1][1],2),3./2.));
633 }
634 else if(i == 1 && k < 2)
635 {
636 deriv = centMoms[a][a+1][2][0]*centMoms[a][a+1][1][1]/(2*std::pow(centMoms[a][a+1][2][0]*centMoms[a][a+1][0][2]-std::pow(centMoms[a][a+1][1][1],2),3./2.));
637 }
638 else if(i == 2 && k < 2)
639 {
640 deriv = - centMoms[a][a+1][2][0]*centMoms[a][a+1][0][2]/std::pow(centMoms[a][a+1][2][0]*centMoms[a][a+1][0][2]-std::pow(centMoms[a][a+1][1][1],2),3./2.);
641 }
642 else {deriv=0;}
643
644 return deriv;
645 break;
646
647 case 2:
648 //beta
649 if(i == 0 && k < 2)
650 {
651 deriv = (centMoms[a][a+1][2][0]*centMoms[a][a+1][0][2]-2*std::pow(centMoms[a][a+1][1][1],2))/(2*std::pow(centMoms[a][a+1][2][0]*centMoms[a][a+1][0][2]-std::pow(centMoms[a][a+1][1][1],2),3./2.));
652 }
653 else if(i == 1 && k < 2)
654 {
655 deriv = - std::pow(centMoms[a][a+1][2][0],2)/(2*std::pow(centMoms[a][a+1][2][0]*centMoms[a][a+1][0][2]-std::pow(centMoms[a][a+1][1][1],2),3./2.));
656 }
657 else if(i == 2 && k < 2)
658 {
659 deriv = centMoms[a][a+1][2][0]*centMoms[a][a+1][1][1]/std::pow(centMoms[a][a+1][2][0]*centMoms[a][a+1][0][2]-std::pow(centMoms[a][a+1][1][1],2),3./2.);
660 }
661 else {deriv=0;}
662
663 return deriv;
664 break;
665
666
667 case 3:
668 //gamma
669 return 0; // TODO
670 break;
671
672 case 4:
673 //eta
674 if(i == 0 && k < 2)
675 {
676 deriv = 0;
677 }
678 else if(i == 1 && k < 2)
679 {
680 deriv = -centMoms[a][4][1][1]/std::pow(centMoms[4][4][2][0],2);
681 }
682 else if(i == 2 && k < 2)
683 {
684 deriv = 1/centMoms[4][4][2][0];
685 }
686 else {deriv=0;}
687
688 return deriv;
689 break;
690
691 case 5:
692 //eta prime
693 if(i == 0 && k < 2)
694 {
695 deriv = 0;
696 }
697 else if(i == 1 && k < 2)
698 {
699 deriv = -centMoms[a+1][4][1][1]/std::pow(centMoms[4][4][2][0],2);
700 }
701 else if(i == 2 && k < 2)
702 {
703 deriv = 1/centMoms[4][4][2][0];
704 }
705 else {deriv=0;}
706
707 return deriv;
708 break;
709
710 case 6: // mean derivatives are all 0 as they don't depend on second order moments
711 //mean spatial
712 return 0;
713 break;
714
715 case 7:
716 //mean divergence
717 return 0;
718 break;
719
720 case 8:
721 //sigma spatial
722 if(i == 0)
723 {
724 deriv = 1/(2*sqrt(centMoms[a][a+1][2][0]));
725 }
726
727 else {deriv=0;}
728
729 return deriv;
730 break;
731
732 case 9:
733 //sigma divergence
734 if(i == 1)
735 {
736 deriv = 1/(2*sqrt(centMoms[a][a+1][0][2]));
737 }
738
739 else {deriv=0;}
740
741 return deriv;
742 break;
743
744 default:
745 return 0;
746 break;
747 }
748}
749
750
751void SamplerAnalysis::printBeamCorrelationMatrix(fourDArray& centMoms)
752{
753 std::cout<<"\nCorrelation matrix for sampler: "<<s->samplerName<<std::endl;
754 double corr = 0.0;
755 for (int i=0; i<6; i++)
756 {
757 for(int j=0; j<6; j++)
758 {
759 corr = centMoms[i][j][1][1]/std::sqrt(centMoms[i][j][2][0]*centMoms[i][j][0][2]);
760 std::printf("%- *.6e ", 12, corr);
761 }
762 std::printf("\n");
763 }
764
765}
Information stored per sampler per event.
Analysis routines for an individual sampler.
twoDArray optical
emt, alf, bta, gma, eta, etapr, mean, sigma
twoDArray varOptical
variances of optical functions
double centMomToDerivative(fourDArray &centMoms, int k, int t, int i)
void Initialise()
Initialise variables.
static void UpdateMass(SamplerAnalysis *s)
Set primary particle mass for optical functions from sampler data.
void CommonCtor()
Initialisation of arrays for optical function calculations.
void Process(bool firstTime=false)
Loop over all entries in the sampler and accumulate power sums over variuos moments.
double centMomToCovariance(fourDArray &centMoms, long long int npartIn, int k, int i, int j)
double powSumToCentralMoment(fourDArray &powSum, long long int npartIn, int i, int j, int m, int n)
std::vector< double > Terminate(std::vector< double > emittance, bool useEmittanceFromFirstSampler=true)
Calculate optical functions based on combinations of moments already accumulated.