26const double PMNS_Base::kGeV2eV = 1.0e+09;
27const double PMNS_Base::kKm2eV = 1.0 / 1.973269788e-10;
28const double PMNS_Base::kNA = 6.022140857e23;
29const double PMNS_Base::kK2 =
30 1e-3 * kNA / pow(kKm2eV, 3);
31const double PMNS_Base::kGf = 1.1663787e-05;
47PMNS_Base::PMNS_Base(
int numNus)
48 : fGotES(false), fBuiltHms(false), fMaxCache(1e6), fProbe(numNus)
142 for (
int i = 0; i <
fNumNus; i++) {
144 for (
int j = 0; j <
fNumNus; j++) {
fEvec[i][j] = (*it).fEvec[i][j]; }
162 for (
int i = 0; i <
fNumNus; i++) {
367 cerr <<
"WARNING: Clearing path vector and starting new single path."
369 <<
"To avoid possible issues, use the SetPath function." << endl;
375 case 0:
fNuPaths[0].length = att;
break;
376 case 1:
fNuPaths[0].density = att;
break;
377 case 2:
fNuPaths[0].zoa = att;
break;
378 case 3:
fNuPaths[0].layer = att;
break;
436 for (
int i = 0; i < nP; i++) {
438 case 0:
fNuPaths[i].length = att[i];
break;
439 case 1:
fNuPaths[i].density = att[i];
break;
440 case 2:
fNuPaths[i].zoa = att[i];
break;
441 case 3:
fNuPaths[i].layer = att[i];
break;
449 cerr <<
"WARNING: New vector size. Starting new path vector." << endl
450 <<
"To avoid possible issues, use the SetPath function." << endl;
464 for (
int i = 0; i < nA; i++) {
466 case 0: p.
length = att[i];
break;
467 case 1: p.
density = att[i];
break;
468 case 2: p.
zoa = att[i];
break;
469 case 3: p.
layer = att[i];
break;
521 vectorD lay_double(lay.begin(), lay.end());
542 cerr <<
"WARNING: First argument should be smaller than second argument"
544 <<
" Setting reverse order (Theta" << j << i <<
"). " << endl;
550 cerr <<
"ERROR: Theta" << i << j <<
" not valid for " <<
fNumNus
551 <<
" neutrinos. Doing nothing." << endl;
558 fTheta[i - 1][j - 1] = th;
573 cerr <<
"WARNING: First argument should be smaller than second argument"
575 <<
" Setting reverse order (Theta" << j << i <<
"). " << endl;
581 cerr <<
"ERROR: Theta" << i << j <<
" not valid for " <<
fNumNus
582 <<
" neutrinos. Returning zero." << endl;
586 return fTheta[i - 1][j - 1];
605 cerr <<
"WARNING: First argument should be smaller than second argument"
607 <<
" Setting reverse order (Delta" << j << i <<
"). " << endl;
613 cerr <<
"ERROR: Delta" << i << j <<
" not valid for " <<
fNumNus
614 <<
" neutrinos. Doing nothing." << endl;
618 cerr <<
"WARNING: Rotation " << i << j <<
" is real. Doing nothing."
626 fDelta[i - 1][j - 1] = delta;
641 cerr <<
"WARNING: First argument should be smaller than second argument"
643 <<
" Setting reverse order (Delta" << j << i <<
"). " << endl;
649 cerr <<
"ERROR: Delta" << i << j <<
" not valid for " <<
fNumNus
650 <<
" neutrinos. Returning zero." << endl;
654 cerr <<
"WARNING: Rotation " << i << j <<
" is real. Returning zero."
659 return fDelta[i - 1][j - 1];
677 cerr <<
"ERROR: Dm" << j <<
"1 not valid for " <<
fNumNus
678 <<
" neutrinos. Doing nothing." << endl;
699 cerr <<
"ERROR: Dm" << j <<
"1 not valid for " <<
fNumNus
700 <<
" neutrinos. Returning zero." << endl;
718 for (
int i = 0; i < x.size(); i++) idx[i] = i;
735 cerr <<
"ERROR: Dm_" << j <<
"1 not valid for " <<
fNumNus
736 <<
" neutrinos. Returning zero." << endl;
745 vectorD dm_idx_double(dm_idx.begin(), dm_idx.end());
750 return (
fEval[ev_idx[dm_idx[j - 1]]] -
fEval[ev_idx[dm_idx[0]]]) * 2 *
763 if (
fTheta[i][j] == 0)
return;
765 double sij = sin(
fTheta[i][j]);
766 double cij = cos(
fTheta[i][j]);
770 if (i + 1 == j ||
fDelta[i][j] == 0) {
801 for (
int j = 0; j <
fNumNus; j++) {
825 if (
fTheta[i][j] == 0)
return;
827 double fSinBuffer = sin(
fTheta[i][j]);
828 double fCosBuffer = cos(
fTheta[i][j]);
840 for (
int k = 0; k < i; k++) {
841 fHmsBufferC = Ham[k][i];
843 Ham[k][i] *= fCosBuffer;
844 Ham[k][i] += Ham[k][j] * fSinBuffer * conj(fExpBuffer);
846 Ham[k][j] *= fCosBuffer;
847 Ham[k][j] -= fHmsBufferC * fSinBuffer * fExpBuffer;
851 for (
int k = i + 1; k < j; k++) {
852 fHmsBufferC = Ham[k][j];
854 Ham[k][j] *= fCosBuffer;
855 Ham[k][j] -= conj(Ham[i][k]) * fSinBuffer * fExpBuffer;
857 Ham[i][k] *= fCosBuffer;
858 Ham[i][k] += fSinBuffer * fExpBuffer * conj(fHmsBufferC);
862 fHmsBufferC = Ham[i][i];
863 fHmsBufferD = real(Ham[j][j]);
865 Ham[i][i] *= fCosBuffer * fCosBuffer;
867 2 * fSinBuffer * fCosBuffer * real(Ham[i][j] * conj(fExpBuffer));
868 Ham[i][i] += fSinBuffer * Ham[j][j] * fSinBuffer;
870 Ham[j][j] *= fCosBuffer * fCosBuffer;
871 Ham[j][j] += fSinBuffer * fHmsBufferC * fSinBuffer;
873 2 * fSinBuffer * fCosBuffer * real(Ham[i][j] * conj(fExpBuffer));
875 Ham[i][j] -= 2 * fSinBuffer * real(Ham[i][j] * conj(fExpBuffer)) *
876 fSinBuffer * fExpBuffer;
878 fSinBuffer * fCosBuffer * (fHmsBufferD - fHmsBufferC) * fExpBuffer;
883 for (
int k = i + 1; k < j; k++) {
884 Ham[k][j] = -conj(Ham[i][k]) * fSinBuffer * fExpBuffer;
886 Ham[i][k] *= fCosBuffer;
890 fHmsBufferD = real(Ham[i][i]);
893 fSinBuffer * fCosBuffer * (Ham[j][j] - fHmsBufferD) * fExpBuffer;
895 Ham[i][i] *= fCosBuffer * fCosBuffer;
896 Ham[i][i] += fSinBuffer * Ham[j][j] * fSinBuffer;
898 Ham[j][j] *= fCosBuffer * fCosBuffer;
899 Ham[j][j] += fSinBuffer * fHmsBufferD * fSinBuffer;
907 for (
int k = 0; k < i; k++) {
908 fHmsBufferC = Ham[k][i];
910 Ham[k][i] *= fCosBuffer;
911 Ham[k][i] += Ham[k][j] * fSinBuffer;
913 Ham[k][j] *= fCosBuffer;
914 Ham[k][j] -= fHmsBufferC * fSinBuffer;
918 fHmsBufferC = Ham[i][i];
919 fHmsBufferD = real(Ham[j][j]);
921 Ham[i][i] *= fCosBuffer * fCosBuffer;
922 Ham[i][i] += 2 * fSinBuffer * fCosBuffer * real(Ham[i][j]);
923 Ham[i][i] += fSinBuffer * Ham[j][j] * fSinBuffer;
925 Ham[j][j] *= fCosBuffer * fCosBuffer;
926 Ham[j][j] += fSinBuffer * fHmsBufferC * fSinBuffer;
927 Ham[j][j] -= 2 * fSinBuffer * fCosBuffer * real(Ham[i][j]);
929 Ham[i][j] -= 2 * fSinBuffer * real(Ham[i][j]) * fSinBuffer;
930 Ham[i][j] += fSinBuffer * fCosBuffer * (fHmsBufferD - fHmsBufferC);
934 Ham[i][j] = fSinBuffer * fCosBuffer * Ham[j][j];
936 Ham[i][i] = fSinBuffer * Ham[j][j] * fSinBuffer;
938 Ham[j][j] *= fCosBuffer * fCosBuffer;
963 for (
int j = 0; j <
fNumNus; j++) {
967 for (
int i = 0; i < j; i++) {
fHms[i][j] = 0; }
969 for (
int i = 0; i < j; i++) {
RotateH(i, j,
fHms); }
992 for (
int i = 0; i <
fNumNus; i++) {
993 double arg =
fEval[i] * LengthIneV;
997 for (
int i = 0; i <
fNumNus; i++) {
999 for (
int j = 0; j <
fNumNus; j++) {
1006 for (
int i = 0; i <
fNumNus; i++) {
1008 for (
int j = 0; j <
fNumNus; j++) {
1036 assert(flv >= 0 && flv <
fNumNus);
1037 for (
int i = 0; i <
fNumNus; ++i) {
1060 assert(flv >= 0 && flv <
fNumNus);
1072 assert(nu_in.size() ==
fNumNus);
1142 return Prob(nu_in, flvf);
1164 return Prob(flvi, flvf);
1194 return Prob(nu_in, flvf);
1224 return Prob(flvi, flvf);
1237 for (
int i = 0; i < probs.size(); i++) { probs[i] =
P(i); }
1389 assert(nflvi <= fNumNus && nflvi >= 0);
1390 assert(nflvf <= fNumNus && nflvf >= 0);
1399 for (
int i = 0; i < nflvi; i++) {
1405 for (
int i = 0; i < int(
fNuPaths.size()); i++) {
1406 for (
int flvi = 0; flvi < nflvi; flvi++) {
1414 for (
int flvi = 0; flvi < nflvi; flvi++) {
1415 for (
int flvj = 0; flvj < nflvf; flvj++) {
1416 probs[flvi][flvj] = norm(allstates[flvi][flvj]);
1526 double minE = 0.1 * E;
1530 if (E - dE / 2 > minE) {
1571 if (E <= 0)
return 0;
1576 if (dE <= 0)
return Prob(nu_in, flvf, E);
1581 return AvgProbLoE(nu_in, flvf, LoEbin[0], LoEbin[1]);
1646 if (LoE <= 0)
return 0;
1658 if (dLoE <= 0)
return Prob(nu_in, flvf);
1670 for (
int j = 0; j < int(samples.size()); j++) {
1672 double w = 1. / pow(samples[j], 2);
1675 prob += w *
Prob(nu_in, flvf, length / samples[j]);
1758 if (E <= 0)
return probs;
1760 if (
fNuPaths.empty())
return probs;
1796 if (LoE <= 0)
return probs;
1798 if (
fNuPaths.empty())
return probs;
1819 for (
int j = 0; j < int(samples.size()); j++) {
1821 double w = 1. / pow(samples[j], 2);
1825 for (
int i = 0; i <
fNumNus; i++) {
1827 probs[i] += w * sample_probs[i];
1833 for (
int i = 0; i <
fNumNus; i++) {
1866 if (E <= 0)
return probs;
1868 if (
fNuPaths.empty())
return probs;
1871 if (dE <= 0)
return ProbMatrix(nflvi, nflvf, E);
1906 if (LoE <= 0)
return probs;
1908 if (
fNuPaths.empty())
return probs;
1918 if (dLoE <= 0)
return ProbMatrix(nflvi, nflvf);
1929 for (
int j = 0; j < int(samples.size()); j++) {
1931 double w = 1. / pow(samples[j], 2);
1935 for (
int flvi = 0; flvi < nflvi; flvi++) {
1936 for (
int flvf = 0; flvf < nflvf; flvf++) {
1938 probs[flvi][flvf] += w * sample_probs[flvi][flvf];
1945 for (
int flvi = 0; flvi < nflvi; flvi++) {
1946 for (
int flvf = 0; flvf < nflvf; flvf++) {
1948 probs[flvi][flvf] /= sumw;
1965 cerr <<
"WARNING: Cannot set AvgProb precision lower that 1e-8."
1966 <<
"Setting to 1e-8." << endl;
1996 for (
int i = 0; i <
fNumNus - 1; i++) {
1997 for (
int j = i + 1; j <
fNumNus; j++) {
2002 int numDm = effDm.size();
2005 sort(effDm.begin(), effDm.end());
2009 int n_div = ceil(200 * pow(dLoE / LoE, 0.8) / sqrt(
fAvgProbPrec / 1e-4));
2016 for (
int k = 0; k < n_div; k++) {
2018 double bctr = LoE - dLoE / 2 + (k + 0.5) * dLoE / n_div;
2019 double bwdt = dLoE / n_div;
2024 samples.push_back(bctr);
2029 for (
int i = 0; i < numDm; i++) {
2035 2 * min(prev[0] - (bctr - bwdt / 2), (bctr + bwdt / 2) - prev[0]);
2038 const double arg = k1267 * effDm[i] * Width;
2042 if (i < numDm - 1) {
2043 if (arg < 0.9)
continue;
2046 if (arg < 0.1)
continue;
2053 for (
int j = 0; j < int(prev.size()); j++) {
2056 double sample = (1 / sqrt(3)) * (Width / 2);
2057 if (arg != 0) sample = acos(sin(arg) / arg) / arg * (Width / 2);
2060 samples.push_back(prev[j] - sample);
2061 samples.push_back(prev[j] + sample);
2067 allSamples.insert(allSamples.end(), samples.begin(), samples.end());
virtual void Propagate()
Propagate neutrino through full path.
static const complexD zero
zero in complex
virtual double P(int flv)
Return the probability of final state in flavour flv.
bool fIsNuBar
Anti-neutrino flag.
virtual matrixD AvgProbMatrixLoE(int nflvi, int nflvf, double LoE, double dLoE=0)
Compute the average probability matrix over a bin of L/E.
virtual vectorD ConvertEtoLoE(double E, double dE)
virtual void SetZoA(double zoa)
Set Z/A value for single path.
virtual double AvgProbLoE(vectorC nu_in, int flvf, double LoE, double dLoE=0)
Compute the average probability over a bin of L/E.
virtual vectorD AvgProbVectorLoE(vectorC nu_in, double LoE, double dLoE=0)
Compute the average probability vector over a bin of L/E.
vectorC fNuState
The neutrino current state.
int fNumNus
Number of neutrino flavours.
std::vector< NuPath > fNuPaths
Vector of neutrino paths.
double fEnergy
Neutrino energy.
virtual vectorC GetMassEigenstate(int mi)
Get a neutrino mass eigenstate.
virtual void RotateH(int i, int j, matrixC &Ham)
Rotate the Hamiltonian by theta_ij and delta_ij.
virtual bool GetIsNuBar()
Get the anti-neutrino flag.
std::unordered_set< EigenPoint > fMixCache
Caching set of eigensystems.
static const double kKm2eV
km to eV^-1
double fAvgProbPrec
AvgProb precision.
virtual void SetDm(int j, double dm)
Set the mass-splitting dm_j1 in eV^2.
virtual void SetDelta(int i, int j, double delta)
Set the CP phase delta_ij.
virtual void SetStdPars()
Set PDG 3-flavor parameters.
virtual double GetDmEff(int j)
Get the effective mass-splitting dm_j1 in eV^2.
virtual void PropagatePath(NuPath p)
Propagate neutrino through a single path.
virtual void SetLength(double L)
Set a single path lentgh in km.
matrixC fHms
matrix H*2E in eV^2
vectorC fBuffer
Buffer for neutrino state tranformations.
bool fGotES
Tag to avoid recalculating eigensystem.
virtual void SetIsNuBar(bool isNuBar)
Set the anti-neutrino flag.
virtual vectorD AvgProbVector(vectorC nu_in, double E, double dE=0)
virtual double AvgProb(vectorC nu_in, int flvf, double E, double dE=0)
Compute the average probability over a bin of energy.
int fMaxCache
Maximum cache size.
virtual void FillCache()
Cache the current eigensystem.
static const complexD one
one in complex
matrixC fEvec
Eigenvectors of the Hamiltonian.
virtual double Prob(vectorC nu_in, int flvf)
Compute the probability of nu_in going to flvf.
virtual matrixD AvgProbMatrix(int nflvi, int nflvf, double E, double dE=0)
NuPath fPath
Current neutrino path.
virtual void SetLayers(std::vector< int > lay)
Set multiple path layer indices.
virtual ~PMNS_Base()
Destructor.
virtual void SolveHam()=0
virtual void AddPath(NuPath p)
Add a path to the sequence.
virtual void SetEnergy(double E)
Set the neutrino energy in GeV.
vectorD fEval
Eigenvalues of the Hamiltonian.
bool fBuiltHms
Tag to avoid rebuilding Hms.
virtual void SetUseCache(bool u=true)
Set caching on/off.
virtual void SetCurPath(NuPath p)
Set the path currently in use by the class.
vectorC fPhases
Buffer for oscillation phases.
EigenPoint fProbe
EigenpPoint to try.
vectorD fDm
m^2_i - m^2_1 in vacuum
virtual void SetPath(NuPath p)
Set a single path.
virtual void SetAvgProbPrec(double prec)
Set the AvgProb precision.
virtual void SetAtt(double att, int idx)
Set one of the path attributes.
virtual bool TryCache()
Try to find a cached eigensystem.
virtual void ResetToFlavour(int flv)
Reset neutrino state to pure flavour flv.
virtual void SetPureState(vectorC nu_in)
Set the initial state from a pure state.
virtual void ClearCache()
Clear the cache.
matrixD fDelta
delta[i][j] CP violating phase
virtual void SetDensity(double rho)
Set single path density in g/cm^3.
virtual std::vector< NuPath > GetPath()
Get the neutrino path sequence.
virtual vectorD ProbVector(vectorC nu_in)
virtual double GetEnergy()
Get the neutrino energy in GeV.
virtual void SetAngle(int i, int j, double th)
Set the mixing angle theta_ij.
virtual double GetAngle(int i, int j)
Get the mixing angle theta_ij.
virtual void BuildHms()
Build the matrix of masses squared.
virtual double GetDm(int j)
Get the mass-splitting dm_j1 in eV^2.
bool fUseCache
Flag for whether to use caching.
static const double kGeV2eV
GeV to eV.
virtual double GetDelta(int i, int j)
Get the CP phase delta_ij.
virtual void SetStdPath()
Set standard neutrino path.
virtual void InitializeVectors()
virtual void RotateState(int i, int j)
Rotate the neutrino state by theta_ij and delta_ij.
virtual void SetMaxCache(int mc=1e6)
Set max cache size.
virtual vectorD GetSamplePoints(double LoE, double dLoE)
Compute the sample points for a bin of L/E with width dLoE.
virtual void ClearPath()
Clear the path vector.
virtual std::vector< int > GetSortedIndices(const vectorD x)
Get indices that sort a vector.
virtual matrixD ProbMatrix(int nflvi, int nflvf)
Compute the probability matrix.
matrixD fTheta
theta[i][j] mixing angle
virtual vectorD GetProbVector()
Some useful general definitions.
std::vector< int > vectorI
std::complex< double > complexD
std::vector< complexD > vectorC
std::vector< double > vectorD
std::vector< vectorD > matrixD
NuPath AvgPath(NuPath &p1, NuPath &p2)
Get the average of two paths.
std::vector< vectorC > matrixC
vectorD fEval
Eigenvalues to be cached.
void SetVars(double e=0, NuPath p=NuPath(0, 0), bool n=false)
Set eigensystem parameters.
matrixC fEvec
Eigenvectors to be cached.
An index sorting comparator.
A struct representing a neutrino path segment.
int layer
An index to identify the matter type.
double density
The density of the path segment in g/cm^3.
double length
The length of the path segment in km.
double zoa
The effective Z/A value of the path segment.