OscProb
PremModel.cxx
Go to the documentation of this file.
1
2//
3// Implements an earth model with spherical shells
4//
5// jcoelho\@apc.in2p3.fr
7
8#include <cmath>
9#include <fstream>
10#include <iostream>
11
12#include "PremModel.h"
13#include "prem_default.hpp"
14
15using namespace std;
16
17using namespace OscProb;
18
24const double PremModel::DET_TOL = 0.2; // Tolerance in km
25
26//.............................................................................
35PremModel::PremModel(string filename) : fDetLayer(0)
36{
38 SetDetPos(6368);
39 LoadModel(filename);
40}
41
42//.............................................................................
47
48//.............................................................................
55{
56 int i = 0;
57
58 while (i < int(fPremLayers.size()) - 1) {
59 if (fPremLayers[i] == fPremLayers[i + 1]) {
60 fPremLayers.erase(fPremLayers.begin() + i);
61 continue;
62 }
63
64 i++;
65 }
66}
67
68//.............................................................................
74{
76
77 fDetLayer = fPremLayers.size() - 1;
78
79 if (fPremLayers.size() && fDetRadius > fPremLayers.back().radius) {
80 cerr << "WARNING: Detector must be inside Earth model." << endl
81 << "WARNING: Adjusting detector radius from " << fDetRadius
82 << " km to " << fPremLayers.back().radius << " km." << endl;
83
84 fDetRadius = fPremLayers.back().radius;
85
86 return;
87 }
88
89 for (int i = 0; i < fPremLayers.size(); i++) {
90 double radius = fPremLayers[i].radius;
91
92 // See if we passed the detector and decide whether
93 // to create a special layer for it
94 if (radius > fDetRadius - DET_TOL) {
95 fDetLayer = i;
96
97 // If detector is not near boundary, add a special layer
98 if (radius > fDetRadius + DET_TOL) {
99 PremLayer det_layer = fPremLayers[i];
100 det_layer.radius = fDetRadius;
101 fPremLayers.insert(fPremLayers.begin() + fDetLayer, det_layer);
102 }
103 else if (radius != fDetRadius) {
104 // update detector radius
105 cerr << "WARNING: Adjusting detector radius from " << fDetRadius
106 << " km to " << radius << " km." << endl;
107 fDetRadius = radius;
108 }
109
110 break;
111 }
112 }
113}
114
115//.............................................................................
131void PremModel::SetDetPos(double rad, double lat, double lon)
132{
133 SetDetectorCoordinates(rad, lat, lon);
134
135 if (fPremLayers.size()) AddDetLayer();
136}
137
138//.............................................................................
145vector<PremLayer> PremModel::GetPremLayers() { return fPremLayers; }
146
147//.............................................................................
152{
153 fDetLayer = 0;
154 fPremLayers.clear();
155}
156
157//.............................................................................
167void PremModel::AddLayer(double radius, double density, double zoa,
168 double layer)
169{
170 fPremLayers.push_back(PremLayer(radius, density, zoa, layer));
171}
172
173//.............................................................................
181void PremModel::LoadModel(string filename)
182{
183 // Clear the current model
184 ClearModel();
185
186 // Use default if no file provided
187 if (filename == "") { filename = PREM_DEFAULT; }
188
189 // Open the file
190 ifstream fin;
191 fin.open(filename.c_str());
192
193 if (!fin) {
194 cerr << "ERROR: File " << filename << " not found!" << endl;
195 return;
196 }
197
198 // Variables for storing table rows
199 float radius, density, zoa, layer;
200
201 // Keep track of previous radius
202 double rprev = 0;
203
204 // Loop over table rows
205 while (fin >> radius >> density >> zoa >> layer) {
206 // Radii must be ordered in model file
207 if (radius <= rprev) {
208 cerr
209 << "ERROR: Radii are not sorted in increasing order in the model file"
210 << endl;
211 ClearModel();
212 return;
213 }
214
215 // Add this layer to the model
216 AddLayer(radius, density, zoa, layer);
217 }
218
219 AddDetLayer();
220
221 // Set the maximum radius in the model
222 fRadiusMax = fPremLayers.back().radius;
223}
224
225//.............................................................................
235void PremModel::SetLayerZoA(int layer, double zoa)
236{
237 int nlayers = fPremLayers.size();
238
239 // Loop over all layers and change the ones
240 // with the given index
241 for (int i = 0; i < nlayers; i++) {
242 if (fPremLayers[i].layer != layer) continue;
243
244 fPremLayers[i].zoa = zoa;
245 }
246}
247
248//.............................................................................
256double PremModel::GetLayerZoA(int layer)
257{
258 int nlayers = fPremLayers.size();
259
260 // This check assumes the layer types are in increasing order
261 if (layer > fPremLayers.back().layer) {
262 cerr << "ERROR: Not that many layer types. Returning 0" << endl;
263 return 0;
264 }
265
266 for (int i = 0; i < nlayers; i++) {
267 if (fPremLayers[i].layer != layer)
268 continue;
269
270 else
271 return fPremLayers[i].zoa;
272 }
273
274 // End of vector reached without finding input type
275 cerr << "ERROR: layer type not found. Returning 0" << endl;
276 return 0;
277}
278
279//.............................................................................
289{
290 if (thick <= 0) {
291 cerr << "WARNING: Layer thickness should be positive. Do nothing." << endl;
292 return;
293 }
294
295 int nlayers = fPremLayers.size();
296
297 if (nlayers < 1) {
298 cerr << "WARNING: PremModel has no layers. Do nothing." << endl;
299 return;
300 }
301
302 double bottomRadius;
303 if (nlayers > 1)
304 bottomRadius = fPremLayers[nlayers - 2].radius;
305 else
306 bottomRadius = 0;
307
308 double topRadius = bottomRadius + thick;
309
310 fPremLayers[nlayers - 1].radius = topRadius;
311
312 // Update max radius
313 fRadiusMax = fPremLayers.back().radius;
314}
315
316//.............................................................................
325void PremModel::AddPath(double length, PremLayer pl)
326{
327 AddPathSegment(length, pl.density, pl.zoa, pl.layer);
328}
329
330//.............................................................................
347int PremModel::FillPath(double cosT, double phi)
348{
349 // Clear current path sequence
350 fNuPath.clear();
351
352 // Do nothing if cosine is unphysical
353 if (fabs(cosT) > 1) return 0;
354
355 // Define the minimum path radius
356 double minR = fDetRadius * sqrt(1 - cosT * cosT);
357 double minRsq = minR * minR;
358
359 // Set the top layer index
360 int toplayer = fPremLayers.size() - 1;
361
362 // Find the inner-most crossed layer
363 int minlayer = 0;
364 while (fPremLayers[minlayer].radius < minR) minlayer++;
365
366 // Compute the number of path segments needed
367 int nsteps = toplayer - fDetLayer;
368 if (cosT < 0) nsteps += 2 * (fDetLayer - minlayer) + 1;
369
370 // Start at the top layer and go down
371 int layer = toplayer;
372 int dl = -1;
373
374 // Loop over all path segments
375 for (int i = 0; i < nsteps; i++) {
376 // Get square of the path length between this layer's
377 // outer radius and inner-most radius
378 double L1 = pow(fPremLayers[layer].radius, 2) - minRsq;
379
380 // If L1 is negative, outer radius is not crossed.
381 // This only happens if detector is at the top layer and the
382 // neutrino is coming from above.
383 if (L1 < 0) return true;
384
385 // Get square of the path length between this layer's
386 // inner radius and inner-most radius
387 double L2 = -minRsq;
388 if (layer > 0) L2 += pow(fPremLayers[layer - 1].radius, 2);
389
390 // If L2 is negative, inner radius is not crossed,
391 // so set this as the minimum layer.
392 bool ismin = (L2 <= 0 && cosT < 0);
393
394 // Store the path segment length
395 double dL;
396
397 // If it's the minimum layer, connect two outer radius
398 // crossing points. If not, compute difference between
399 // inner and outer radius crossings.
400 if (ismin)
401 dL = 2 * sqrt(L1);
402 else if (L2 >= 0)
403 dL = sqrt(L1) - sqrt(L2);
404 else
405 dL = sqrt(L1); // This should never actually happen,
406 // but protect in case L2 is slightly
407 // negative when it should be zero.
408 // e.g. arriving at the detector from above.
409
410 // Add this path segment to the sequence
411 AddPath(dL, fPremLayers[layer]);
412
413 // If we reached the inner-most layer,
414 // start moving up again.
415 if (ismin) dl = 1;
416
417 // Move to next layer
418 layer += dl;
419 }
420
421 // Return the number of path segments
422 return fNuPath.size();
423}
double fRadiusMax
Maximum radius in Earth model (in km)
virtual void SetRemoveSmallPaths(bool rp=true)
Set tag to remove small paths.
virtual void AddPathSegment(double length, double density, double zoa, int index)
Add a path segment to the sequence.
std::vector< NuPath > fNuPath
The current neutrino path sequence.
double fDetRadius
The radius where the detector sits (in km)
virtual void SetDetectorCoordinates(double rad, double lat, double lon)
virtual void AddLayer(double radius, double density, double zoa, double layer)
Add a layer to the model.
Definition: PremModel.cxx:167
virtual void SetTopLayerSize(double thick)
Set the outermost layer thickness in km.
Definition: PremModel.cxx:288
virtual void CleanIdentical()
Clear identical consecutive layers.
Definition: PremModel.cxx:54
int fDetLayer
The layer index of the detector.
Definition: PremModel.h:73
virtual void AddDetLayer()
Add the detector layer.
Definition: PremModel.cxx:73
virtual void LoadModel(std::string filename)
Load an earth model from a file.
Definition: PremModel.cxx:181
void SetDetPos(double rad, double lat=0, double lon=0)
Definition: PremModel.cxx:131
int FillPath(double cosT, double phi=0)
Fill the path sequence in a vector.
Definition: PremModel.cxx:347
static const double DET_TOL
The detector position tolerance near boundaries.
Definition: PremModel.h:78
std::vector< PremLayer > fPremLayers
The layers in the earth model.
Definition: PremModel.h:71
virtual ~PremModel()
Destructor.
Definition: PremModel.cxx:46
virtual void ClearModel()
Clear the earth model information.
Definition: PremModel.cxx:151
virtual void SetLayerZoA(int layer, double zoa)
Set Z/A of all layers of a given type.
Definition: PremModel.cxx:235
virtual void AddPath(double length, PremLayer pl)
Add a path segment to the sequence.
Definition: PremModel.cxx:325
virtual std::vector< PremLayer > GetPremLayers()
Definition: PremModel.cxx:145
virtual double GetLayerZoA(int layer)
Get Z/A of all layers of a given type.
Definition: PremModel.cxx:256
Some useful general definitions.
Definition: Absorption.h:6
Definition: EigenPoint.h:44
A struct representing a spherical shell of matter for earth models.
Definition: NuPath.h:84
double radius
The outer radius of the layer in km.
Definition: NuPath.h:128
double zoa
The effective Z/A value of the layer.
Definition: NuPath.h:130
double density
The density of the layer in g/cm^3.
Definition: NuPath.h:129
int layer
An index to identify the matter type.
Definition: NuPath.h:131