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