OscProb
PMNS_Maltoni.cxx
Go to the documentation of this file.
1
2//
3// Base class for faster oscillations of neutrinos in matter in a
4// n-neutrino framework using a Taylor Expansion.
5//
6//.............................................................................
7//
8// mloup@apc.in2p3.fr rogan.clark@uclouvain.be
9//
11
12#include "PMNS_Maltoni.h"
13#include <Eigen/Eigenvalues>
14
15using namespace std;
16
17using namespace OscProb;
18
19//.............................................................................
23PMNS_Maltoni::PMNS_Maltoni(int numNus) : PMNS_Base(numNus)
24{
25 fPrem.LoadModel("");
27 SetwidthBin(0, 0);
28 SetAvgProbPrec(1e-4);
29 SetIsOscProbAvg(false);
30}
31
32//.............................................................................
38{
40
43 fKInvE = Eigen::MatrixXcd::Zero(fNumNus, fNumNus);
44
47 fKcosT = Eigen::MatrixXcd::Zero(fNumNus, fNumNus);
48
50
54
55 for (int i = 0; i < fNumNus; i++) { fevolutionMatrixS[i][i] = 1; }
56
57 fLayer = fPrem.GetPremLayers().size() - 1;
58
59 fdl = -1;
60
62}
63
64//.............................................................................
70void PMNS_Maltoni::SetIsOscProbAvg(bool isOscProbAvg)
71{
72 fIsOscProbAvg = isOscProbAvg;
73}
74
75//.............................................................................
85
86//.............................................................................
92void PMNS_Maltoni::SetCosT(double cosT) { fcosT = cosT; }
93
94//.............................................................................
101void PMNS_Maltoni::SetwidthBin(double dE, double dcosT)
102{
103 fdInvE = dE;
104 fdcosT = dcosT;
105}
106
107//.............................................................................
112{
113 UpdateHam();
114
115 double dL = LnDerivative() * kKm2eV;
116
117 for (int j = 0; j < fNumNus; j++) {
118 for (int i = 0; i <= j; i++) {
119 fKflavor[i][j] = dL * fHam(i, j);
120
121 if (i != j) { fKflavor[j][i] = conj(fKflavor[i][j]); }
122 }
123 }
124}
125
126//.............................................................................
137{
138 double lenghtEV = L * kKm2eV; // L in eV-1
139 double bufK = lenghtEV * 0.5; // L/2 in eV-1
140
141 complexD buffer[fNumNus];
142
143 for (int i = 0; i < fNumNus; i++) {
144 complexD Hms_kl;
145
146 for (int l = 0; l < fNumNus; l++) {
147 buffer[l] = 0;
148
149 for (int k = 0; k < fNumNus; k++) {
150 if (k <= l)
151 Hms_kl = fHms[k][l];
152 else
153 Hms_kl = conj(fHms[l][k]);
154
155 if (fIsNuBar && k != l) Hms_kl = conj(Hms_kl);
156
157 buffer[l] += conj(fEvec[k][i]) * Hms_kl;
158 }
159 }
160
161 for (int j = 0; j <= i; j++) {
162 fKmass[i][j] = 0;
163
164 for (int l = 0; l < fNumNus; l++) {
165 fKmass[i][j] += buffer[l] * fEvec[l][j];
166 }
167
168 complexD C;
169
170 if (i == j) { C = complexD(1, 0); }
171 else {
172 double arg = (fEval[i] - fEval[j]) * lenghtEV;
173
174 C = (complexD(cos(arg), sin(arg)) - complexD(1, 0.0)) /
175 complexD(0.0, arg);
176 }
177
178 fKmass[i][j] *= bufK * C;
179
180 if (i != j) fKmass[j][i] = conj(fKmass[i][j]);
181 }
182 }
183}
184
185//.............................................................................
190{
191 double dL = 0;
192
193 double L1 = pow(fPrem.GetPremLayers()[fLayer].radius, 2) - fminRsq;
194
195 double L2 = -fminRsq;
196 if (fLayer > 0) L2 += pow(fPrem.GetPremLayers()[fLayer - 1].radius, 2);
197
198 bool ismin = (L2 <= 0 && fcosT < 0);
199
200 if (ismin)
201 dL = 2 * pow(fDetRadius, 2) * fcosT * pow(L1, -0.5);
202 else
203 dL = pow(fDetRadius, 2) * fcosT * (pow(L1, -0.5) - pow(L2, -0.5));
204
205 if (ismin) fdl = 1;
206
207 fLayer += fdl;
208
209 return dL;
210}
211
212//.............................................................................
217{
218 complexD buffer[fNumNus];
219
220 for (int j = 0; j < fNumNus; j++) {
221 for (int k = 0; k < fNumNus; k++) {
222 buffer[k] = fPhases[k] * conj(fEvec[j][k]);
223 }
224
225 for (int i = 0; i < fNumNus; i++) {
226 fSflavor[i][j] = 0;
227 for (int k = 0; k < fNumNus; k++) {
228 fSflavor[i][j] += fEvec[i][k] * buffer[k];
229 }
230 }
231 }
232}
233
234//.............................................................................
239{
240 complexD buffer[fNumNus];
241
242 for (int j = 0; j < fNumNus; j++) {
243 for (int k = 0; k < fNumNus; k++) {
244 buffer[k] = 0;
245
246 for (int l = 0; l < fNumNus; l++) {
247 buffer[k] += fKmass[k][l] * conj(fEvec[j][l]);
248 }
249 }
250
251 for (int i = 0; i <= j; i++) {
252 fKflavor[i][j] = 0;
253
254 for (int k = 0; k < fNumNus; k++) {
255 fKflavor[i][j] += fEvec[i][k] * buffer[k];
256 }
257
258 if (i != j) { fKflavor[j][i] = conj(fKflavor[i][j]); }
259 }
260 }
261}
262
263//.............................................................................
277{
278 complexD save[fNumNus];
279
280 for (int j = 0; j < fNumNus; j++) {
281 for (int n = 0; n < fNumNus; n++) { save[n] = fevolutionMatrixS[n][j]; }
282
283 for (int i = 0; i < fNumNus; i++) {
284 fevolutionMatrixS[i][j] = 0;
285
286 for (int k = 0; k < fNumNus; k++) {
287 fevolutionMatrixS[i][j] += fSflavor[i][k] * save[k];
288 }
289 }
290 }
291}
292
293//.............................................................................
305void PMNS_Maltoni::MultiplicationRuleK(Eigen::MatrixXcd& K)
306{
307 for (int i = 0; i < fNumNus; i++) {
308 complexD buffer[fNumNus];
309
310 for (int l = 0; l < fNumNus; l++) {
311 for (int k = 0; k < fNumNus; k++) {
312 buffer[l] += conj(fevolutionMatrixS[k][i]) * fKflavor[k][l];
313 }
314 }
315
316 for (int j = 0; j <= i; j++) {
317 for (int l = 0; l < fNumNus; l++) {
318 K(i, j) += buffer[l] * fevolutionMatrixS[l][j];
319 }
320
321 if (i != j) { K(j, i) = conj(K(i, j)); }
322 }
323 }
324}
325
326//.............................................................................
331{
332 for (int i = 0; i < int(fNuPaths.size()); i++) {
334 }
335}
336
337//.............................................................................
344{
345 // Set the neutrino path
346 SetCurPath(p);
347
348 // Solve for eigensystem
349 SolveHam();
350
351 // Get the evolution matrix in mass basis
352 double LengthIneV = kKm2eV * p.length;
353 for (int i = 0; i < fNumNus; i++) {
354 double arg = fEval[i] * LengthIneV;
355 fPhases[i] = complexD(cos(arg), -sin(arg));
356 }
357
358 // Rotate S in flavor basis
359 rotateS();
360
361 // if avg on E
362 if (fdInvE != 0) {
363 // Build KE in mass basis
364 BuildKE(p.length);
365
366 // Rotate KE in flavor basis
367 rotateK();
368
369 // Multiply this layer K's with the previous path K's
371 }
372 // if avg on cosT
373 if (fdcosT != 0) {
374 // Build KcosT in mass basis
375 BuildKcosT();
376
377 // Multiply this layer K's with the previous path K's
379 }
380
381 // Multiply this layer S's with the previous path S's
383}
384
385//.............................................................................
395void PMNS_Maltoni::SolveK(Eigen::MatrixXcd& K, vectorD& lambda, matrixC& V)
396{
397 if (fNumNus == 4) TemplateSolver<Eigen::Matrix4cd>(K, lambda, V);
398 if (fNumNus == 3) TemplateSolver<Eigen::Matrix3cd>(K, lambda, V);
399 if (fNumNus == 2)
400 TemplateSolver<Eigen::Matrix2cd>(K, lambda, V);
401 else
402 TemplateSolver<Eigen::MatrixXcd>(K, lambda, V);
403}
404
405//.............................................................................
414template <typename T>
415void PMNS_Maltoni::TemplateSolver(Eigen::MatrixXcd& K, vectorD& lambda,
416 matrixC& V)
417{
418 Eigen::Ref<T> R(K);
419
420 Eigen::SelfAdjointEigenSolver<T> eigensolver(R);
421
422 // Fill flambdaInvE and fVInvE vectors from GLoBES arrays
423 for (int i = 0; i < fNumNus; i++) {
424 lambda[i] = eigensolver.eigenvalues()(i);
425 for (int j = 0; j < fNumNus; j++) {
426 V[i][j] = eigensolver.eigenvectors()(i, j);
427 }
428 }
429}
430
431//.............................................................................
450double PMNS_Maltoni::AvgFormula(int flvi, int flvf, double dbin, vectorD lambda,
451 matrixC V)
452{
453 vectorC SV = vectorC(fNumNus, 0);
454
455 for (int i = 0; i < fNumNus; i++) {
456 for (int k = 0; k < fNumNus; k++) {
457 SV[i] += fevolutionMatrixS[flvf][k] * V[k][i];
458 }
459 }
460
461 complexD buffer[fNumNus];
462
463 for (int n = 0; n < fNumNus; n++) { buffer[n] = SV[n] * conj(V[flvi][n]); }
464
465 complexD sinc[fNumNus][fNumNus];
466 for (int j = 0; j < fNumNus; j++) {
467 sinc[j][j] = 1;
468 for (int i = 0; i < j; i++) {
469 double arg = (lambda[i] - lambda[j]) * dbin / 2;
470 sinc[i][j] = sin(arg) / arg;
471 sinc[j][i] = sinc[i][j];
472 }
473 }
474
475 complexD P = 0;
476
477 for (int j = 0; j < fNumNus; j++) {
478 for (int i = 0; i < fNumNus; i++) {
479 P += buffer[i] * conj(buffer[j]) * sinc[j][i];
480 }
481 }
482
483 return real(P);
484}
485
486//.............................................................................
507double PMNS_Maltoni::AvgProb(int flvi, int flvf, double E, double dE)
508{
509 if (fIsOscProbAvg == true) return PMNS_Base::AvgProb(flvi, flvf, E, dE);
510
511 // Do nothing if energy not positive
512 if (E <= 0) return 0;
513
514 if (fNuPaths.empty()) return 0;
515
516 // Don't average zero width
517 if (dE <= 0) return Prob(flvi, flvf, E);
518
519 vectorD LoEbin = ConvertEtoLoE(E, dE);
520
521 // Compute average in LoE
522 return AvgProbLoE(flvi, flvf, LoEbin[0], LoEbin[1]);
523}
524
525//.............................................................................
548double PMNS_Maltoni::AvgProbLoE(int flvi, int flvf, double LoE, double dLoE)
549{
550 if (fIsOscProbAvg == true)
551 return PMNS_Base::AvgProbLoE(flvi, flvf, LoE, dLoE);
552
553 if (LoE <= 0) return 0;
554
555 if (fNuPaths.empty()) return 0;
556
557 // Don't average zero width
558 if (dLoE <= 0) return Prob(flvi, flvf, fPath.length / LoE);
559
560 // Get sample points for this bin
561 vectorD samples = GetSamplePointsAvgClass(LoE, dLoE);
562
563 double avgprob = 0;
564 double L = fPath.length;
565 double sumw = 0;
566
567 // Loop over all sample points
568 for (int j = 1; j < int(samples.size()); j++) {
569 // Set (L/E)^-2 weights
570 double w = 1. / pow(samples[j], 2);
571
572 avgprob += w * AvgAlgo(flvi, flvf, samples[j], samples[0], L);
573
574 // Increment sum of weights
575 sumw += w;
576 }
577
578 // Return weighted average of probabilities
579 return avgprob / sumw;
580}
581
582//.............................................................................
594double PMNS_Maltoni::AvgAlgo(int flvi, int flvf, double LoE, double dLoE,
595 double L)
596{
597 // Set width bin as 1/E
598 double d1oE = dLoE / L;
599
600 // reset K et S et Ve et lambdaE
602
603 SetEnergy(L / LoE);
604 SetwidthBin(d1oE, 0);
605
606 // Propagate -> get S and K matrix (on the whole path)
608
609 // DiagolK -> get VE and lambdaE
611
612 // return fct avr proba
613 return AvgFormula(flvi, flvf, d1oE / kGeV2eV, flambdaInvE, fVInvE);
614}
615
616//.............................................................................
629{
630 // Set a number of sub-divisions to achieve "good" accuracy
631 // This needs to be studied better
632 int n_div = ceil(3 * pow(dLoE / LoE, 0.8) * pow(LoE, 0.3) /
633 sqrt(fAvgProbPrec / 1e-4));
634
635 // A vector to store sample points
636 vectorD Samples;
637
638 // Define sub-division width
639 Samples.push_back(dLoE / n_div);
640
641 // Loop over sub-divisions
642 for (int k = 0; k < n_div; k++) {
643 // Define sub-division center
644 double bctr = LoE - dLoE / 2 + (k + 0.5) * dLoE / n_div;
645
646 Samples.push_back(bctr);
647
648 } // End of loop over sub-divisions
649
650 // Return sample points
651 return Samples;
652}
653
654//.............................................................................
671vectorD PMNS_Maltoni::AvgProbVector(int flvi, double E, double dE)
672{
673 if (fIsOscProbAvg == true) return PMNS_Base::AvgProbVector(flvi, E, dE);
674
675 vectorD probs(fNumNus, 0);
676
677 // Do nothing if energy is not positive
678 if (E <= 0) return probs;
679
680 if (fNuPaths.empty()) return probs;
681
682 // Don't average zero width
683 if (dE <= 0) return ProbVector(flvi, E);
684
685 vectorD LoEbin = ConvertEtoLoE(E, dE);
686
687 // Compute average in LoE
688 return AvgProbVectorLoE(flvi, LoEbin[0], LoEbin[1]);
689}
690
691//.............................................................................
708vectorD PMNS_Maltoni::AvgProbVectorLoE(int flvi, double LoE, double dLoE)
709{
710 if (fIsOscProbAvg == true)
711 return PMNS_Base::AvgProbVectorLoE(flvi, LoE, dLoE);
712
713 vectorD probs(fNumNus, 0);
714
715 if (LoE <= 0) return probs;
716
717 if (fNuPaths.empty()) return probs;
718
719 double L = fPath.length;
720
721 // Don't average zero width
722 if (dLoE <= 0) return ProbVector(flvi, L / LoE);
723
724 // Get sample points for this bin
725 vectorD samples = GetSamplePointsAvgClass(LoE, dLoE);
726
727 double sumw = 0;
728
729 // Loop over all sample points
730 for (int j = 1; j < int(samples.size()); j++) {
731 // Set (L/E)^-2 weights
732 double w = 1. / pow(samples[j], 2);
733
734 for (int flvf = 0; flvf < fNumNus; flvf++) {
735 if (flvf == 0)
736 probs[flvf] += w * AvgAlgo(flvi, flvf, samples[j], samples[0], L);
737 else
738 probs[flvf] +=
739 w * AvgFormula(flvi, flvf, fdInvE / kGeV2eV, flambdaInvE, fVInvE);
740 }
741
742 // Increment sum of weights
743 sumw += w;
744 }
745
746 for (int flvf = 0; flvf < fNumNus; flvf++) {
747 // Divide by total sampling weight
748 probs[flvf] /= sumw;
749 }
750
751 // Return weighted average of probabilities
752 return probs;
753}
754
755//.............................................................................
767matrixD PMNS_Maltoni::AvgProbMatrix(int nflvi, int nflvf, double E, double dE)
768{
769 if (fIsOscProbAvg == true)
770 return PMNS_Base::AvgProbMatrix(nflvi, nflvf, E, dE);
771
772 matrixD probs(nflvi, vectorD(nflvf, 0));
773
774 // Do nothing if energy is not positive
775 if (E <= 0) return probs;
776
777 if (fNuPaths.empty()) return probs;
778
779 // Don't average zero width
780 if (dE <= 0) return ProbMatrix(nflvi, nflvf, E);
781
782 vectorD LoEbin = ConvertEtoLoE(E, dE);
783
784 // Compute average in LoE
785 return AvgProbMatrixLoE(nflvi, nflvf, LoEbin[0], LoEbin[1]);
786}
787
788//.............................................................................
800matrixD PMNS_Maltoni::AvgProbMatrixLoE(int nflvi, int nflvf, double LoE,
801 double dLoE)
802{
803 if (fIsOscProbAvg == true)
804 return PMNS_Base::AvgProbMatrixLoE(nflvi, nflvf, LoE, dLoE);
805
806 matrixD probs(nflvi, vectorD(nflvf, 0));
807
808 if (LoE <= 0) return probs;
809
810 if (fNuPaths.empty()) return probs;
811
812 double L = fPath.length;
813
814 // Don't average zero width
815 if (dLoE <= 0) return ProbMatrix(nflvi, nflvf, L / LoE);
816
817 // Get sample points for this bin
818 vectorD samples = GetSamplePointsAvgClass(LoE, dLoE);
819
820 double sumw = 0;
821
822 // Loop over all sample points
823 for (int j = 1; j < int(samples.size()); j++) {
824 // Set (L/E)^-2 weights
825 double w = 1. / pow(samples[j], 2);
826
827 for (int flvi = 0; flvi < nflvi; flvi++) {
828 for (int flvf = 0; flvf < nflvf; flvf++) {
829 // if (!TryCacheK())
830 if (flvi == 0 && flvf == 0)
831 probs[flvi][flvf] +=
832 w * AvgAlgo(flvi, flvf, samples[j], samples[0], L);
833 else
834 probs[flvi][flvf] +=
835 w * AvgFormula(flvi, flvf, fdInvE / kGeV2eV, flambdaInvE, fVInvE);
836 }
837 }
838
839 // Increment sum of weights
840 sumw += w;
841 }
842
843 for (int flvi = 0; flvi < nflvi; flvi++) {
844 for (int flvf = 0; flvf < nflvf; flvf++) {
845 // Divide by total sampling weight
846 probs[flvi][flvf] /= sumw;
847 }
848 }
849
850 // Return weighted average of probabilities
851 return probs;
852}
853
854//.............................................................................
876double PMNS_Maltoni::AvgProb(int flvi, int flvf, double E, double cosT,
877 double dcosT)
878{
879 // reset K et S et Ve et lambdaE
881
882 SetEnergy(E);
883 SetCosT(cosT);
884 SetwidthBin(0, dcosT);
885
886 fPrem.FillPath(cosT);
888
889 fminRsq = pow(fDetRadius * sqrt(1 - cosT * cosT), 2);
890
891 // Propagate -> get S and K matrix (on the whole path)
893
894 // DiagolK -> get VE and lambdaE
896
897 // Compute average
898 return AvgFormula(flvi, flvf, fdcosT, flambdaCosT, fVcosT);
899}
900
901//.............................................................................
913double PMNS_Maltoni::AvgAlgoCosT(int flvi, int flvf, double E, double cosT,
914 double dcosT)
915{
916 // reset K et S et Ve et lambdaE
918
919 SetEnergy(E);
920 SetCosT(cosT);
921 SetwidthBin(0, dcosT);
922
923 fPrem.FillPath(cosT);
925
926 fminRsq = pow(fDetRadius * sqrt(1 - cosT * cosT), 2);
927
928 // Propagate -> get S and K matrix (on the whole path)
930
931 // DiagolK -> get VE and lambdaE
933 // Compute average
934 return AvgFormula(flvi, flvf, fdcosT, flambdaCosT, fVcosT);
935}
936
937//.............................................................................
961double PMNS_Maltoni::AvgProb(int flvi, int flvf, double E, double dE,
962 double cosT, double dcosT)
963{
964 if (E <= 0) return 0;
965 if (cosT > 0) return 0;
966
967 if (fNuPaths.empty()) return 0;
968 // Don't average zero width
969 if (dE <= 0 && dcosT == 0) return Prob(flvi, flvf, E);
970 if (dE <= 0) return AvgProb(flvi, flvf, E, cosT, dcosT);
971 if (dcosT == 0) return AvgProb(flvi, flvf, E, dE);
972
973 vectorD Ebin = ConvertEtoLoE(E, dE);
974
975 // Compute average in LoE
976 return AvgProbLoE(flvi, flvf, Ebin[0], Ebin[1], cosT, dcosT);
977}
978
979//.............................................................................
1008double PMNS_Maltoni::AvgProbLoE(int flvi, int flvf, double LoE, double dLoE,
1009 double cosT, double dcosT)
1010{
1011 if (LoE <= 0) return 0;
1012 if (cosT > 0) return 0;
1013
1014 // if (fNuPaths.empty()) return 0;
1015
1016 // Don't average zero width
1017 if (dLoE <= 0 && dcosT == 0) return Prob(flvi, flvf, fPath.length / LoE);
1018 if (dLoE <= 0)
1019 return AvgProb(flvi, flvf, fPath.length / LoE, cosT, dcosT);
1020 if (dcosT == 0) return AvgProbLoE(flvi, flvf, LoE, dLoE);
1021
1022 // Make sample with 1oE and not LoE
1024 dLoE / fPath.length, cosT, dcosT);
1025
1026 int rows = samples.size();
1027 int cols = samples[0].size();
1028
1029 double avgprob = 0;
1030 double sumw = 0;
1031
1032 // Loop over all sample points
1033 for (int k = 1; k < int(rows); k++) {
1034 for (int l = 1; l < int(cols); l++) {
1035 // Set (L/E)^-2 weights
1036 double w = 1. / pow(real(samples[k][l]), 2);
1037
1038 avgprob +=
1039 w * AvgAlgo(flvi, flvf, real(samples[k][l]), real(samples[0][0]),
1040 imag(samples[k][l]), imag(samples[0][0]));
1041
1042 // Increment sum of weights
1043 sumw += w;
1044 }
1045 }
1046
1047 // Return average of probabilities
1048 return avgprob / ((sumw));
1049}
1050
1051//.............................................................................
1065double PMNS_Maltoni::AvgAlgo(int flvi, int flvf, double InvE, double dInvE,
1066 double cosT, double dcosT)
1067{
1068 fPrem.FillPath(cosT);
1070
1071 // reset K et S et Ve et lambdaE
1073
1074 SetEnergy(1 / InvE);
1075 SetCosT(cosT);
1076 SetwidthBin(dInvE, dcosT);
1077
1078 fminRsq = pow(fDetRadius * sqrt(1 - cosT * cosT), 2);
1079
1080 // Propagate -> get S and K matrix (on the whole path)
1082
1083 // DiagolK -> get VE and lambdaE
1086
1087 return AlgorithmDensityMatrix(flvi, flvf);
1088}
1089
1090//.............................................................................
1100{
1101 fdensityMatrix[flvi][flvi] = 1;
1102
1103 RotateDensityM(true, fVcosT);
1105 RotateDensityM(false, fVcosT);
1106
1107 RotateDensityM(true, fVInvE);
1109 RotateDensityM(false, fVInvE);
1110
1112
1113 return real(fdensityMatrix[flvf][flvf]);
1114}
1115
1116//.............................................................................
1132 double cosT, double dcosT)
1133{
1134 // Set a number of sub-divisions to achieve "good" accuracy
1135 // This needs to be studied better
1136 int n_divCosT = ceil(380 * pow(InvE, 0.5) * pow(abs(dcosT / cosT), 0.8) /
1137 sqrt(fAvgProbPrec / 1e-4));
1138 int n_divE = ceil(260 * pow(dInvE / InvE, 0.8) * pow(InvE, 0.6) /
1139 sqrt(fAvgProbPrec / 1e-4));
1140
1141 // A matrix to store sample points
1142 matrixC Samples = matrixC(n_divE + 1, vectorC(n_divCosT + 1, 0));
1143
1144 // Define sub-division width
1145 Samples[0][0] = complexD(dInvE / n_divE, dcosT / n_divCosT);
1146
1147 // Loop over sub-divisions
1148 for (int k = 0; k < n_divE; k++) {
1149 // Define sub-division center for energy
1150 double bctr_InvE = InvE - dInvE / 2 + (k + 0.5) * dInvE / n_divE;
1151
1152 for (int l = 0; l < n_divCosT; l++) {
1153 // Define sub-division center for angle
1154 double bctr_CosT = cosT - dcosT / 2 + (l + 0.5) * dcosT / n_divCosT;
1155
1156 Samples[k + 1][l + 1] = complexD(bctr_InvE, bctr_CosT);
1157 }
1158
1159 } // End of loop over sub-divisions
1160
1161 // Return sample points
1162 return Samples;
1163}
1164
1165//.............................................................................
1174{
1175 matrixC Buffer = matrixC(fNumNus, vectorC(fNumNus, 0));
1176
1177 for (int i = 0; i < fNumNus; i++) {
1178 for (int j = 0; j < fNumNus; j++) {
1179 for (int k = 0; k < fNumNus; k++) {
1180 if (to_basis)
1181 Buffer[i][j] += fdensityMatrix[i][k] * V[k][j];
1182 else
1183 Buffer[i][j] += fdensityMatrix[i][k] * conj(V[j][k]);
1184 }
1185 }
1186 }
1187
1188 for (int i = 0; i < fNumNus; i++) {
1189 for (int j = i; j < fNumNus; j++) {
1190 fdensityMatrix[i][j] = 0;
1191 for (int k = 0; k < fNumNus; k++) {
1192 if (to_basis)
1193 fdensityMatrix[i][j] += conj(V[k][i]) * Buffer[k][j];
1194 else
1195 fdensityMatrix[i][j] += V[i][k] * Buffer[k][j];
1196 }
1197 if (j > i) fdensityMatrix[j][i] = conj(fdensityMatrix[i][j]);
1198 }
1199 }
1200}
1201
1202//.............................................................................
1210{
1211 matrixC sinc = matrixC(fNumNus, vectorC(fNumNus, 0));
1212 for (int j = 0; j < fNumNus; j++) {
1213 for (int i = 0; i < j; i++) {
1214 double arg = (lambda[i] - lambda[j]) * dbin;
1215 sinc[i][j] = sin(arg) / arg;
1216
1217 sinc[j][i] = sinc[i][j];
1218 }
1219 }
1220
1221 for (int i = 0; i < fNumNus; i++) { sinc[i][i] = 1; }
1222
1223 for (int j = 0; j < fNumNus; j++) {
1224 for (int i = 0; i < fNumNus; i++) {
1225 fdensityMatrix[i][j] = fdensityMatrix[i][j] * sinc[i][j];
1226 }
1227 }
1228}
1229
1230//.............................................................................
1244 double dcosT)
1245{
1246 // Set a number of sub-divisions to achieve "good" accuracy
1247 // This needs to be studied better
1248 int n_div = ceil(35 * pow(E, -0.4) * pow(abs(dcosT / cosT), 0.8) /
1249 sqrt(fAvgProbPrec / 1e-4));
1250
1251 // A vector to store sample points
1252 vectorD Samples;
1253
1254 // Define sub-division width
1255 Samples.push_back(dcosT / n_div);
1256
1257 // Loop over sub-divisions
1258 for (int k = 0; k < n_div; k++) {
1259 // Define sub-division center
1260 double bctr = cosT - dcosT / 2 + (k + 0.5) * dcosT / n_div;
1261
1262 Samples.push_back(bctr);
1263
1264 } // End of loop over sub-divisions
1265
1266 // Return sample points
1267 return Samples;
1268}
1269
1270//.............................................................................
1289double PMNS_Maltoni::AvgFormulaExtrapolation(int flvi, int flvf, double dE,
1290 vectorD lambda, matrixC V)
1291{
1292 vectorC SV = vectorC(fNumNus, 0);
1293
1294 for (int i = 0; i < fNumNus; i++) {
1295 for (int k = 0; k < fNumNus; k++) {
1296 SV[i] += fevolutionMatrixS[flvf][k] * V[k][i];
1297 }
1298 }
1299
1300 complexD buffer[fNumNus];
1301 for (int n = 0; n < fNumNus; n++) { buffer[n] = SV[n] * conj(V[flvi][n]); }
1302
1303 complexD expo[fNumNus][fNumNus];
1304
1305 for (int j = 0; j < fNumNus; j++) {
1306 for (int i = 0; i < fNumNus; i++) {
1307 double arg = (lambda[j] - lambda[i]) * dE;
1308 expo[j][i] = exp(complexD(0.0, arg));
1309 }
1310 }
1311
1312 complexD P = 0;
1313
1314 for (int j = 0; j < fNumNus; j++) {
1315 for (int i = 0; i < fNumNus; i++) {
1316 P += buffer[i] * conj(buffer[j]) * expo[j][i];
1317 }
1318 }
1319
1320 return real(P);
1321}
1322
1323//.............................................................................
1341double PMNS_Maltoni::ExtrapolationProb(int flvi, int flvf, double E, double dE)
1342{
1343 // reset K et S et Ve et lambdaE
1345
1346 SetEnergy(E);
1347 SetwidthBin(1 / (E + dE) - 1 / E, 0);
1348
1349 // Propagate -> get S and K matrix (on the whole path)
1351
1352 // DiagolK -> get VE and lambdaE
1354
1355 return AvgFormulaExtrapolation(flvi, flvf, fdInvE / kGeV2eV, flambdaInvE,
1356 fVInvE);
1357}
1358
1359//.............................................................................
1377double PMNS_Maltoni::ExtrapolationProbLoE(int flvi, int flvf, double LoE,
1378 double dLoE)
1379{
1380 // reset K et S et Ve et lambdaE
1382
1384 double L = fPath.length;
1385
1386 SetEnergy(L / LoE);
1387 SetwidthBin(dLoE / L, 0);
1388
1389 // Propagate -> get S and K matrix (on the whole path)
1391
1392 // DiagolK -> get VE and lambdaE
1394
1395 return AvgFormulaExtrapolation(flvi, flvf, dLoE * kGeV2eV / L, flambdaInvE,
1396 fVInvE);
1397}
1398
1399//.............................................................................
1420double PMNS_Maltoni::ExtrapolationProbCosT(int flvi, int flvf, double cosT,
1421 double dcosT)
1422{
1423 fPrem.FillPath(cosT);
1425
1426 // reset K et S et Ve et lambdaE
1428
1429 // SetEnergy(E);
1430 SetCosT(cosT);
1431 SetwidthBin(0, dcosT);
1432
1433 fminRsq = pow(fDetRadius * sqrt(1 - cosT * cosT), 2);
1434
1435 // Propagate -> get S and K matrix (on the whole path)
1437
1438 // DiagolK -> get VE and lambdaE
1440
1441 return AvgFormulaExtrapolation(flvi, flvf, fdcosT, flambdaCosT, fVcosT);
1442}
virtual std::vector< NuPath > GetNuPath()
Base class implementing general functions for computing neutrino oscillations.
Definition: PMNS_Base.h:26
virtual double P(int flv)
Return the probability of final state in flavour flv.
Definition: PMNS_Base.cxx:1058
bool fIsNuBar
Anti-neutrino flag.
Definition: PMNS_Base.h:293
virtual matrixD AvgProbMatrixLoE(int nflvi, int nflvf, double LoE, double dLoE=0)
Compute the average probability matrix over a bin of L/E.
Definition: PMNS_Base.cxx:1900
virtual vectorD ConvertEtoLoE(double E, double dE)
Definition: PMNS_Base.cxx:1516
virtual double AvgProbLoE(vectorC nu_in, int flvf, double LoE, double dLoE=0)
Compute the average probability over a bin of L/E.
Definition: PMNS_Base.cxx:1643
virtual vectorD AvgProbVectorLoE(vectorC nu_in, double LoE, double dLoE=0)
Compute the average probability vector over a bin of L/E.
Definition: PMNS_Base.cxx:1791
int fNumNus
Number of neutrino flavours.
Definition: PMNS_Base.h:277
std::vector< NuPath > fNuPaths
Vector of neutrino paths.
Definition: PMNS_Base.h:295
static const double kKm2eV
km to eV^-1
Definition: PMNS_Base.h:215
double fAvgProbPrec
AvgProb precision.
Definition: PMNS_Base.h:305
matrixC fHms
matrix H*2E in eV^2
Definition: PMNS_Base.h:284
virtual vectorD AvgProbVector(vectorC nu_in, double E, double dE=0)
Definition: PMNS_Base.cxx:1753
virtual double AvgProb(vectorC nu_in, int flvf, double E, double dE=0)
Compute the average probability over a bin of energy.
Definition: PMNS_Base.cxx:1568
matrixC fEvec
Eigenvectors of the Hamiltonian.
Definition: PMNS_Base.h:290
virtual double Prob(vectorC nu_in, int flvf)
Compute the probability of nu_in going to flvf.
Definition: PMNS_Base.cxx:1114
virtual matrixD AvgProbMatrix(int nflvi, int nflvf, double E, double dE=0)
Definition: PMNS_Base.cxx:1861
NuPath fPath
Current neutrino path.
Definition: PMNS_Base.h:296
virtual void SolveHam()=0
virtual void SetEnergy(double E)
Set the neutrino energy in GeV.
Definition: PMNS_Base.cxx:226
vectorD fEval
Eigenvalues of the Hamiltonian.
Definition: PMNS_Base.h:289
virtual void SetCurPath(NuPath p)
Set the path currently in use by the class.
Definition: PMNS_Base.cxx:274
vectorC fPhases
Buffer for oscillation phases.
Definition: PMNS_Base.h:286
virtual void SetPath(NuPath p)
Set a single path.
Definition: PMNS_Base.cxx:330
virtual void SetAvgProbPrec(double prec)
Set the AvgProb precision.
Definition: PMNS_Base.cxx:1962
virtual vectorD ProbVector(vectorC nu_in)
Definition: PMNS_Base.cxx:1250
static const double kGeV2eV
GeV to eV.
Definition: PMNS_Base.h:217
virtual matrixD ProbMatrix(int nflvi, int nflvf)
Compute the probability matrix.
Definition: PMNS_Base.cxx:1387
virtual void HadamardProduct(vectorD lambda, double dbin)
Apply an Hadamard Product to the density matrix.
double fcosT
Cosine of zenith angle.
Definition: PMNS_Maltoni.h:184
virtual double AvgAlgoCosT(int flvi, int flvf, double E, double cosT, double dcosT)
virtual void MultiplicationRuleS()
Product between two S matrices.
virtual matrixD AvgProbMatrix(int nflvi, int nflvf, double E, double dE)
Eigen::MatrixXcd fHam
The full Hamiltonian.
Definition: PMNS_Maltoni.h:217
virtual void rotateK()
Rotate one K matrix.
virtual void SetIsOscProbAvg(bool isOscProbAvg)
Set flag for which averaging to use.
void TemplateSolver(Eigen::MatrixXcd &K, vectorD &lambda, matrixC &V)
Auxiliary function to choose eigensystem method.
virtual void BuildKcosT()
build K matrix for angle in flavor basis
matrixC fKmass
K matrix in mass basis for one layer.
Definition: PMNS_Maltoni.h:203
virtual void UpdateHam()=0
Build the full Hamiltonian.
virtual double AvgFormulaExtrapolation(int flvi, int flvf, double dE, vectorD flambda, matrixC fV)
Formula for the extrapolation of probability.
matrixC fVInvE
Eigenvalues of K_invE.
Definition: PMNS_Maltoni.h:191
virtual double LnDerivative()
Compute the derivation of one layer's length.
virtual double AlgorithmDensityMatrix(int flvi, int flvf)
Algorithm for the transformations on the density matrix.
Eigen::MatrixXcd fKcosT
K matrix for neutrino angle for the entire path.
Definition: PMNS_Maltoni.h:196
virtual double ExtrapolationProb(int flvi, int flvf, double E, double dE)
Compute the probability of flvi going to flvf for an energy E+dE.
vectorD flambdaInvE
Eigenvectors of K_invE.
Definition: PMNS_Maltoni.h:189
Eigen::MatrixXcd fKInvE
K matrix for the inverse of energy for the entire path.
Definition: PMNS_Maltoni.h:194
virtual void InitializeTaylorsVectors()
Initialize all member vectors with zeros.
OscProb::PremModel fPrem
Earth model used.
Definition: PMNS_Maltoni.h:215
int fdl
Length derivative.
Definition: PMNS_Maltoni.h:210
virtual void rotateS()
Rotate the S matrix.
virtual void PropagateTaylor()
Propagate neutrino through full path.
virtual matrixD AvgProbMatrixLoE(int nflvi, int nflvf, double LoE, double dLoE)
virtual vectorD AvgProbVector(int flvi, double E, double dE)
virtual void PropagatePathTaylor(NuPath p)
Propagate neutrino through a single path.
virtual double AvgAlgo(int flvi, int flvf, double LoE, double dLoE, double L)
virtual void SetCosT(double cosT)
Set neutrino angle.
virtual vectorD AvgProbVectorLoE(int flvi, double LoE, double dLoE)
int fLayer
Layer index.
Definition: PMNS_Maltoni.h:209
double fdInvE
Bin's width for the inverse of energy.
Definition: PMNS_Maltoni.h:186
virtual double AvgFormula(int flvi, int flvf, double dbin, vectorD flambda, matrixC fV)
Formula for the average probability over a bin of width dbin.
virtual void SetPremModel(OscProb::PremModel &prem)
virtual void SetwidthBin(double dE, double dcosT)
Set bin's widths for energy and angle.
vectorD flambdaCosT
Eigenvectors of K_cosTheta.
Definition: PMNS_Maltoni.h:190
double fdcosT
Bin's width for zenith angle.
Definition: PMNS_Maltoni.h:187
virtual double AvgProbLoE(int flvi, int flvf, double LoE, double dLoE)
virtual void RotateDensityM(bool to_basis, matrixC V)
Apply rotation to the density matrix.
bool fIsOscProbAvg
Flag to call OscProb default or Maltoni average.
Definition: PMNS_Maltoni.h:219
double fminRsq
Minimum square radius.
Definition: PMNS_Maltoni.h:212
matrixC fdensityMatrix
The neutrino density matrix state.
Definition: PMNS_Maltoni.h:206
matrixC fVcosT
Eigenvalues of K_cosTheta.
Definition: PMNS_Maltoni.h:201
matrixC fSflavor
S matrix for one layer.
Definition: PMNS_Maltoni.h:202
virtual vectorD GetSamplePointsAvgClass(double LoE, double dLoE)
Compute the sample points fo a bin of L/E with width dLoE.
virtual double AvgProb(int flvi, int flvf, double E, double dE)
void SolveK(Eigen::MatrixXcd &K, vectorD &lambda, matrixC &V)
Solve the K matrix for eigenvectors and eigenvalues.
virtual double ExtrapolationProbCosT(int flvi, int flvf, double cosT, double dcosT)
Compute the probability of flvi going to flvf for an angle cosT+dcosT.
virtual void BuildKE(double L)
build K matrix for the inverse of energy in mass basis
virtual void MultiplicationRuleK(Eigen::MatrixXcd &K)
Product between two K matrices.
double fDetRadius
Detector radius.
Definition: PMNS_Maltoni.h:211
matrixC fKflavor
K matrix in flavor basis for one layer.
Definition: PMNS_Maltoni.h:204
virtual double ExtrapolationProbLoE(int flvi, int flvf, double LoE, double dLoE)
Compute the probability of flvi going to flvf at LoE+dLoE.
Implements an earth model with spherical shells.
Definition: PremModel.h:33
virtual double GetDetRadius()
Definition: PremModel.cxx:429
virtual void LoadModel(std::string filename)
Load an earth model from a file.
Definition: PremModel.cxx:181
int FillPath(double cosT, double phi=0)
Fill the path sequence in a vector.
Definition: PremModel.cxx:347
virtual std::vector< PremLayer > GetPremLayers()
Definition: PremModel.cxx:145
Some useful general definitions.
Definition: Absorption.h:6
std::complex< double > complexD
Definition: Definitions.h:21
std::vector< complexD > vectorC
Definition: Definitions.h:22
std::vector< double > vectorD
Definition: Definitions.h:18
std::vector< vectorD > matrixD
Definition: Definitions.h:19
NuPath AvgPath(NuPath &p1, NuPath &p2)
Get the average of two paths.
Definition: NuPath.cxx:27
std::vector< vectorC > matrixC
Definition: Definitions.h:23
Definition: EigenPoint.h:44
A struct representing a neutrino path segment.
Definition: NuPath.h:34
double length
The length of the path segment in km.
Definition: NuPath.h:78