OscProb
PMNS_Deco.cxx
Go to the documentation of this file.
1
2//
3// Implementation of oscillations of neutrinos in matter in a
4// three-neutrino framework with decoherence.
5//
6// This class inherits from the PMNS_DensityMatrix class
7//
8// jcoelho\@apc.in2p3.fr
10
11#include <iostream>
12
13#include "PMNS_Deco.h"
14#include "exceptions.h"
15
16using namespace OscProb;
17
18using namespace std;
19
20//.............................................................................
26PMNS_Deco::PMNS_Deco() : PMNS_DensityMatrix(), fGamma()
27{
28 SetGamma(2, 0);
29 SetGamma(3, 0);
30 SetDecoAngle(0);
31 SetPower(0);
32}
33
34//.............................................................................
39
40//.............................................................................
49void PMNS_Deco::SetGamma(int j, double val)
50{
51 THROW_ON_INVALID_ARG(j == 2 || j == 3, j);
52
53 if (val < 0) {
54 cerr << "WARNING: Gamma_" << j << 1 << " must be positive. "
55 << "Setting it to absolute value of input: " << abs(val) << endl;
56 }
57
58 fGamma[j - 1] = abs(val);
59}
60
61//.............................................................................
77void PMNS_Deco::SetGamma32(double gamma32)
78{
79 if (gamma32 < 0) {
80 cerr << "WARNING: Gamma_32 must be positive. "
81 << "Setting it to absolute value of input: " << abs(gamma32) << endl;
82 }
83
84 double min32 = 0.25 * fGamma[1];
85
86 if (fGamma[0] >= 0)
87 min32 *= 1 - pow(fGamma[0], 2);
88 else
89 min32 *= 1 + 3 * pow(fGamma[0], 2);
90
91 if (gamma32 < min32) {
92 if (fGamma[0] >= 0 || 4 * gamma32 / fGamma[1] < 1) {
93 fGamma[0] = sqrt(1 - 4 * gamma32 / fGamma[1]);
94 fGamma[2] = 0.25 * fGamma[1] * (1 + 3 * pow(fGamma[0], 2));
95 }
96 else {
97 fGamma[0] = -sqrt((4 * gamma32 / fGamma[1] - 1) / 3);
98 fGamma[2] = 0.25 * fGamma[1] * (1 - pow(fGamma[0], 2));
99 }
100
101 cerr << "WARNING: Impossible to have Gamma32 = " << gamma32
102 << " with current Gamma21 and theta parameters." << endl
103 << " Changing the value of cos(theta) to " << fGamma[0]
104 << endl;
105
106 return;
107 }
108
109 double arg = fGamma[1] * (4 * gamma32 - fGamma[1] * (1 - pow(fGamma[0], 2)));
110
111 if (arg < 0) {
112 arg = 0;
113 fGamma[0] = sqrt(1 - 4 * gamma32 / fGamma[1]);
114 cerr << "WARNING: Imaginary Gamma31 found. "
115 << "Changing the value of cos(theta) to " << fGamma[0] << endl;
116 }
117
118 double gamma31 = gamma32 + fGamma[0] * (fGamma[0] * fGamma[1] + sqrt(arg));
119
120 fGamma[2] = gamma31;
121
122 // Sanity check
123 double get_gamma32 = GetGamma(3, 2);
124 THROW_ON_INVALID_ARG(fabs(gamma32 - get_gamma32) < 1e-6, gamma32, gamma32);
125}
126
127//.............................................................................
138void PMNS_Deco::SetDecoAngle(double th) { fGamma[0] = cos(th); }
139
140//.............................................................................
151void PMNS_Deco::SetPower(double n) { fPower = n; }
152
153//.............................................................................
157double PMNS_Deco::GetDecoAngle() { return acos(fGamma[0]); }
158
159//.............................................................................
163double PMNS_Deco::GetPower() { return fPower; }
164
165//.............................................................................
175double PMNS_Deco::GetGamma(int i, int j)
176{
177 if (i < j) {
178 cerr << "WARNING: First argument should be larger than second argument"
179 << endl
180 << "Setting reverse order (Gamma_" << j << i << "). " << endl;
181 int temp = i;
182 i = j;
183 j = temp;
184 }
185 THROW_ON_INVALID_ARG(i == 2 || i == 3, i);
186 THROW_ON_INVALID_ARG(j == 1 || j == 2, i);
187 THROW_ON_INVALID_ARG(i > j, i, j);
188
189 if (j == 1) { return fGamma[i - 1]; }
190 else {
191 // Combine Gamma31, Gamma21 and an angle (fGamma[0] = cos(th)) to make
192 // Gamma32
193 double arg =
194 fGamma[1] * (4 * fGamma[2] - fGamma[1] * (1 - pow(fGamma[0], 2)));
195
196 if (arg < 0) return fGamma[1] - 3 * fGamma[2];
197
198 return fGamma[2] + fGamma[1] * pow(fGamma[0], 2) - fGamma[0] * sqrt(arg);
199 }
200}
201
202//.............................................................................
207{
208 vectorI out(3, 0);
209
210 // 1st element is smallest
211 if (x[0] < x[1] && x[0] < x[2]) {
212 // 3rd element is largest
213 if (x[1] < x[2]) {
214 out[1] = 1;
215 out[2] = 2;
216 }
217 // 2nd element is largest
218 else {
219 out[1] = 2;
220 out[2] = 1;
221 }
222 }
223 // 2nd element is smallest
224 else if (x[1] < x[2]) {
225 out[0] = 1;
226 // 3rd element is largest
227 if (x[0] < x[2]) out[2] = 2;
228 // 1st element is largest
229 else
230 out[1] = 2;
231 }
232 // 3rd element is smallest
233 else {
234 out[0] = 2;
235 // 2nd element is largest
236 if (x[0] < x[1]) out[2] = 1;
237 // 1st element is largest
238 else
239 out[1] = 1;
240 }
241
242 return out;
243}
244
245//.............................................................................
252{
253 // Set the neutrino path
254 SetCurPath(p);
255
256 // Solve for eigensystem
257 SolveHam();
258
259 // Rotate to effective mass basis
260 RotateState(true, fEvec);
261
262 // Some ugly way of matching gamma and dmsqr indices
263 vectorI dm_idx = sort3(fDm);
264 vectorI ev_idx = sort3(fEval);
265
266 int idx[3];
267 for (int i = 0; i < fNumNus; i++) idx[ev_idx[i]] = dm_idx[i];
268
269 // Power law dependency of gamma parameters
270 double energyCorr = pow(fEnergy, fPower);
271
272 // Convert path length to eV
273 double lengthIneV = kKm2eV * p.length;
274
275 // Apply phase rotation to off-diagonal elements
276 for (int j = 0; j < fNumNus; j++) {
277 for (int i = 0; i < j; i++) {
278 // Get the appropriate gamma parameters based on sorted indices
279 double gamma_ij =
280 GetGamma(max(idx[i], idx[j]) + 1, min(idx[i], idx[j]) + 1) *
281 energyCorr;
282 // Multiply by path length
283 gamma_ij *= kGeV2eV * lengthIneV;
284 // This is the standard oscillation phase
285 double arg = (fEval[i] - fEval[j]) * lengthIneV;
286 // apply phase to rho
287 fRho[i][j] *= exp(-gamma_ij) * complexD(cos(arg), -sin(arg));
288 fRho[j][i] = conj(fRho[i][j]);
289 }
290 }
291
292 // Rotate back to flavour basis
293 RotateState(false, fEvec);
294}
295
vectorI sort3(const vectorD &x)
Definition: PMNS_Deco.cxx:206
int fNumNus
Number of neutrino flavours.
Definition: PMNS_Base.h:277
double fEnergy
Neutrino energy.
Definition: PMNS_Base.h:292
static const double kKm2eV
km to eV^-1
Definition: PMNS_Base.h:215
matrixC fEvec
Eigenvectors of the Hamiltonian.
Definition: PMNS_Base.h:290
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
vectorD fDm
m^2_i - m^2_1 in vacuum
Definition: PMNS_Base.h:279
static const double kGeV2eV
GeV to eV.
Definition: PMNS_Base.h:217
virtual void PropagatePath(NuPath p)
Propagate neutrino through a single path.
Definition: PMNS_Deco.cxx:251
double fPower
Stores the power index parameter.
Definition: PMNS_Deco.h:58
virtual void SetGamma32(double val)
Set the parameter.
Definition: PMNS_Deco.cxx:77
virtual void SetDecoAngle(double th)
Set the decoherence angle.
Definition: PMNS_Deco.cxx:138
virtual ~PMNS_Deco()
Destructor.
Definition: PMNS_Deco.cxx:38
virtual double GetDecoAngle()
Get the decoherence angle.
Definition: PMNS_Deco.cxx:157
virtual double GetGamma(int i, int j)
Get any given decoherence parameter.
Definition: PMNS_Deco.cxx:175
virtual double GetPower()
Get the power index.
Definition: PMNS_Deco.cxx:163
virtual void SetGamma(int j, double val)
Set any given decoherence parameter.
Definition: PMNS_Deco.cxx:49
double fGamma[3]
Stores each decoherence parameter.
Definition: PMNS_Deco.h:57
virtual void SetPower(double n)
Set the power index.
Definition: PMNS_Deco.cxx:151
Base class for methods based on density matrices.
virtual void RotateState(bool to_basis, matrixC U)
Rotate rho to/from a given basis.
matrixC fRho
The neutrino density matrix state.
virtual void SolveHam()
Solve the full Hamiltonian for eigenvectors and eigenvalues.
Definition: PMNS_Fast.cxx:98
#define THROW_ON_INVALID_ARG(condition,...)
Definition: exceptions.h:85
Some useful general definitions.
Definition: Absorption.h:6
std::vector< int > vectorI
Definition: Definitions.h:16
std::complex< double > complexD
Definition: Definitions.h:21
std::vector< double > vectorD
Definition: Definitions.h:18
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