OscProb
EarthModelBinned.cxx
Go to the documentation of this file.
1/*************************************************************************
2 * EarthModelBinned.cxx
3 * Implements a 3D earth model (binned in depth, latitude, and longitude)
4 * for the programming library OscProb
5 * Created by Rebekah Pestes (last modified: 4/4/23)
6 *************************************************************************/
7
8#include <cmath>
9#include <fstream>
10#include <iostream>
11
12#include "EarthModelBinned.h"
13#include "prem_default.hpp"
14
15using namespace std;
16
17using namespace OscProb;
18
19TrajConstants::TrajConstants(double cosT, double phi, double DetLat,
20 double DetLon, double rDet)
21{
22 UpdateNuAngles(cosT, phi);
23 UpdateDetPos(DetLat, DetLon, rDet);
24}
25
26//.............................................................................
34void TrajConstants::UpdateNuAngles(double cosTheta, double phi)
35{
36 cosT = cosTheta;
37 sinSqT = 1 - cosT * cosT;
38 sinT = sqrt(sinSqT);
39
40 cosA = cos(phi);
41 sinA = sin(phi);
42
43 sinTsinA = sinT * sinA;
44 sinTcosA = sinT * cosA;
45}
46
47//.............................................................................
56void TrajConstants::UpdateDetPos(double rDet, double DetLat, double DetLon)
57{
58 sinDetLat = sin(DetLat);
59 cosDetLat = cos(DetLat);
60 cosDetLon = cos(DetLon);
61 sinDetLon = sin(DetLon);
62 DetRadius = rDet;
63
66}
67
68//.............................................................................
74{
85 maxSinSqLat = 1 - pow(sinA * cosDetLat, 2);
86 if (beta == 0) { xlatextreme = 0; }
87 else {
89 }
90}
91
92EarthBin::EarthBin(double r_out, double r_in, double lat, double lon,
93 double den, double z, int n)
94{
95 SetBin(r_out, r_in, lat, lon, den, z, n);
96}
97
98void EarthBin::SetBin(double r_out, double r_in, double lat, double lon,
99 double den, double z, int n)
100{
101 radius_out = r_out;
102 radius_in = r_in;
103 latitude = lat * M_PI / 180.0; // convert to radians
104 longitude = lon * M_PI / 180.0; // convert to radians
105 density = den;
106 zoa = z;
107 index = n;
108}
109
110//.............................................................................
122{
123 SetDetPos(6368, 0, 0);
124 LoadModel(filename);
125 SetRemoveSmallPaths(false);
126 fLonError = 0;
127}
128
129//.............................................................................
134
135//.............................................................................
141vector<EarthBin> EarthModelBinned::GetEarthBins() { return fEarthBins; }
142
143//.............................................................................
148{
149 fnDepthBins = 0;
150 fnLonBins = 0;
151 fnLatBins = 0;
152 fEarthBins.clear();
153}
154
155//.............................................................................
169void EarthModelBinned::SetDetPos(double rad, double lat, double lon)
170{
171 SetDetectorCoordinates(rad, lat, lon);
173}
174
175//.............................................................................
187void EarthModelBinned::AddBin(double radius_out, double radius_in,
188 double latitude, double longitude, double density,
189 double zoa, double index)
190{
191 fEarthBins.push_back(EarthBin(radius_out, radius_in, latitude, longitude,
192 density, zoa, index));
193}
194
195//.............................................................................
214void EarthModelBinned::LoadModel(string filename)
215{
216 // Clear the current model
217 ClearModel();
218 double EarthRadius = 6371.0;
219
220 // Use default if no file provided
221 if (filename == "") { filename = PREM3D_DEFAULT; }
222 cout << "Loading Earth model table from " << filename << "..." << endl;
223
224 // Open the file
225 ifstream fin;
226 fin.open(filename.c_str());
227 if (!fin) {
228 cerr << "ERROR: File " << filename << " not found!" << endl;
229 return;
230 }
231
232 // Variables for storing table rows
233 float depth, latitude, longitude, density, zoa, index;
234
235 // Keep track of previous depth/latitude/longitude
236 double radius_prev = 0;
237 double lat_prev = -90.0;
238 double lon_prev = 0;
239
240 // Hold onto previous different depth, so we have depth maximum for bin
241 double radius_min = radius_prev;
242
243 // Initialize max region index
244 fmaxRegIndex = -1;
245
246 // Loop over table rows
247 while (fin >> longitude >> latitude >> depth >> density >> zoa >> index) {
248 double outer_radius = EarthRadius - depth;
249
250 // Move minimum depth (and reset latitude/longitude) if depth has changed
251 // from previous one
252 if (outer_radius > radius_prev) {
253 radius_min = radius_prev;
254 lat_prev = -90.0;
255 lon_prev = 0.0;
256 fnDepthBins++;
257 }
258 else if (outer_radius <
259 radius_prev) { // Depths must be ordered in model file
260 cerr << "ERROR: Depths are not sorted in decreasing order in the model "
261 "file "
262 << "(or depth is greater than " << EarthRadius << " km)." << endl;
263 ClearModel();
264 return;
265 }
266 else if (longitude > lon_prev) { // Reset latitude if longitude has changed
267 // from previous one
268 lat_prev = -90.0;
269 fnLonBins++;
270 }
271 else if (longitude < lon_prev) { // Longitudes must be ordered in model file
272 // (after depths)
273 cerr << "ERROR: Longitudes are not sorted in increasing order (after "
274 "depths) in the model file."
275 << endl;
276 ClearModel();
277 return;
278 }
279 else if (latitude < lat_prev) { // Latitudes must be ordered in model file
280 // (after longitudes)
281 cerr << "ERROR: Latitudes are not sorted in increasing order (after "
282 "longitudes) in the model file."
283 << endl;
284 ClearModel();
285 return;
286 }
287
288 // Add this bin to the model
289 AddBin(outer_radius, radius_min, latitude, longitude, density, zoa, index);
290
291 // Check region index
292 if (index > fmaxRegIndex) { fmaxRegIndex = index; }
293
294 // Set previous coordinates for next bin
295 radius_prev = outer_radius;
296 lat_prev = latitude;
297 lon_prev = longitude;
298 }
299
300 // Set Outermost Radius
301 fRadiusMax = radius_prev;
302
303 // Modify number of longitude bins to how many there actually are (instead of
304 // how many times we changed the longitude bin without changing the depth bin
305 // = nLonBins-1 times per depth bin)
307 fInvLonBinWidth = 0.5 * fnLonBins / M_PI; // in radians^(-1)
308 fHalfLonBinWidth = M_PI / fnLonBins; // in radians
309
310 // Calculate number of latitude bins
312 fInvLatBinWidth = fnLatBins / M_PI; // in radians^(-1)
313 fHalfLatBinWidth = 0.5 * M_PI / fnLatBins; // in radians
314
315 // Error if first latitude bin center deviates from about half of the
316 // calculated latitude bin width
317 if (abs(fHalfLatBinWidth - (fEarthBins[0].latitude + 0.5 * M_PI)) >
318 fHalfLatBinWidth * 0.01) { // Warn if first latitude bin center isn't
319 // about half of the latitude bin width
320 cerr << "ERROR: Latitude of 1st bin center (" << fEarthBins[0].latitude
321 << ") is not in the middle of the first bin, whose size should be "
322 << 2 * fHalfLatBinWidth << " rad, as calculated from having "
323 << fnLatBins << " latitude bins." << endl;
324 ClearModel();
325 return;
326 }
327
328 cout << "\t...done (" << fEarthBins.size() << " bins: " << fnDepthBins
329 << " depth, " << fnLatBins << " latitude, and " << fnLonBins
330 << " longitude)." << endl;
331}
332
333//.............................................................................
343void EarthModelBinned::SetRegionZoA(int index, double zoa)
344{
345 if (index > fmaxRegIndex) {
346 cerr << "WARNING: Index " << index << " does not exist in model "
347 << "(max index = " << fmaxRegIndex << ")." << endl
348 << "Doing nothing." << endl;
349 return;
350 }
351
352 int nbins = fEarthBins.size();
353
354 // Loop over all bins and change the ones
355 // with the given index
356 for (int i = 0; i < nbins; i++) {
357 if (fEarthBins[i].index != index) continue;
358
359 fEarthBins[i].zoa = zoa;
360 }
361}
362
363//.............................................................................
373{
374 if (index > fmaxRegIndex) {
375 cerr << "ERROR: Index " << index << " does not exist in model "
376 << "(max index = " << fmaxRegIndex << "). Returning 0" << endl;
377 return 0;
378 }
379
380 int nbins = fEarthBins.size();
381
382 for (int i = 0; i < nbins; i++) {
383 if (fEarthBins[i].index != index)
384 continue;
385
386 else
387 return fEarthBins[i].zoa;
388 }
389
390 // End of vector reached without finding index
391 cerr << "ERROR: Index " << index << " not found! Returning 0" << endl;
392 return 0;
393}
394
395//.............................................................................
403void EarthModelBinned::ScaleRegionDensity(int index, double factor)
404{
405 if (index > fmaxRegIndex) {
406 cerr << "WARNING: Index " << index << " does not exist in model "
407 << "(max index = " << fmaxRegIndex << ")." << endl
408 << "Doing nothing." << endl;
409 return;
410 }
411
412 int nbins = fEarthBins.size();
413
414 // Loop over all bins and change the ones
415 // with the given index
416 for (int i = 0; i < nbins; i++) {
417 if (fEarthBins[i].index != index) continue;
418
419 double density_init = fEarthBins[i].density;
420 fEarthBins[i].density = factor * density_init;
421 }
422}
423
424//.............................................................................
433void EarthModelBinned::AddPath(double length, EarthBin bin)
434{
435 AddPathSegment(length, bin.density, bin.zoa, bin.index);
436}
437
438//.............................................................................
457{
458 // Find next lat bin boundary (bin center +/- 1/2-binwidth)
459 double NewLat = fEarthBins[cur_index].latitude + L.sign * L.dLat;
460 // Turn around if lat reaches +/- 90 degrees (or close enough)
461 if (abs(NewLat) - 0.5 * M_PI > -1.0e-14) {
462 if (L.maxreached) return -1; // Only turn around once
463 L.maxreached = true;
464 // cout << "Max latitude reached..." << endl;
465 L.sign = -L.sign;
466 NewLat = fEarthBins[cur_index].latitude + L.sign * L.dLat;
467 if (abs(NewLat) - 0.5 * M_PI > -1.0e-14)
468 return -1; // This would happen if there's only one latitude bin...
469 }
470
471 // Calculate parts of answer
472 double sinNewLat = sin(NewLat);
473 double NsinSqNewLat = -sinNewLat * sinNewLat;
474 double radicand = fC.maxSinSqLat +
475 NsinSqNewLat; // 1-[sin(NewLat)]^2-[sin(phi)cos(DetLat)]^2
476 // Turn around if the radicand is 0 (close enough) or less
477 if (radicand < 1.0e-14) {
478 if (L.maxreached) return -1; // Only turn around once
479 L.maxreached = true;
480 // cout << "Max latitude reached..." << endl;
481 L.sign = -L.sign;
482 NewLat = fEarthBins[cur_index].latitude + L.sign * L.dLat;
483 sinNewLat = sin(NewLat);
484 NsinSqNewLat = -sinNewLat * sinNewLat;
485 radicand = fC.maxSinSqLat + NsinSqNewLat;
486 if (radicand < 1.0e-14)
487 return -1; // The rest of the track is contained in this lat bin
488 }
489 double denominator = fC.gammaSq + NsinSqNewLat;
490
491 // Calculate distance from the detector at next lat bin boundary
492 double answer;
493 if (denominator == 0) {
494 answer = 0.5 * (fC.xlatextreme - fC.rDetSinDetLat / fC.gamma);
495 // There is a "possible" case where answer would be 0:
496 // if the detector is at the center of the Earth... just don't...
497 }
498 else {
499 answer = -(fC.rDetCosT * NsinSqNewLat + fC.rDetGammaSinDetLat +
500 L.sign * fC.rDetSinT * sinNewLat * sqrt(radicand)) /
501 denominator;
502 }
503
504 // Check to see if going to the edge of the bin jumped to an invalid
505 // part of the function (cosA*rDetCosDetLat/beta = x at max lat)
506 if (L.maxreached && answer >= fC.xlatextreme) {
507 return -1; // The rest of the track is contained in this lat bin
508 }
509
510 return answer;
511}
512
513//.............................................................................
527{
528 double twoPi = 2 * M_PI;
529 // Increment to next bin in direction dLon
530 double lon = prev_lon + L.dLon;
531 if (lon < 0 || lon >= twoPi) { lon -= floor(lon / twoPi) * twoPi; }
532 if (L.dLon > 0) {
533 L.nextBin = L.bin + 1;
534 if (L.nextBin >= fnLonBins) {
535 // cross from 2pi to 0
536 L.nextBin = 0;
537 }
538 }
539 else {
540 L.nextBin = L.bin - 1;
541 if (L.nextBin < 0) {
542 // cross from 0 to 2pi
543 L.nextBin = fnLonBins - 1;
544 }
545 }
546
547 // Check if lon is outside of range covered by neutrino's trajectory
548 if (L.max < L.min) {
549 if (0 > lon - L.min && L.max - lon < 0) return -1;
550 }
551 else {
552 if (0 > lon - L.min || L.max - lon < 0) return -1;
553 }
554
555 // Parts of the answer
556 double cosNewLon = cos(lon);
557 double sinNewLon = sin(lon);
558 double expression = fC.sinDetLon * cosNewLon - sinNewLon * fC.cosDetLon;
559 double denominator = fC.alpha * expression +
560 fC.sinTsinAcosDetLon * cosNewLon +
561 fC.sinTsinAsinDetLon * sinNewLon;
562
563 // Calculate & return detector distance
564 if (denominator == 0) { // Is there ever a case when this is true???
565 // Error message will be printed at the end of the FillPath function
566 L.err_message.assign("Longitude along neutrino trajectory = " +
567 std::to_string(lon));
568 L.error = -1;
569 return -1;
570 }
571 return fC.rDetCosDetLat * expression / denominator;
572}
573
574//.............................................................................
587 double& DetDist, int& index,
588 LatBinInfo& latI,
589 LonBinInfo& lonI)
590{
591 // Keep going as long as there is a lat or lon bin crossing before
592 // the next depth bin crossing
593 while (detDist_nextDbin < latI.detDist_nextBin ||
594 detDist_nextDbin < lonI.detDist_nextBin) {
595 if (latI.detDist_nextBin >
596 lonI.detDist_nextBin) { // if next lat bin crossing is before next lon
597 // bin crossing
598 // Add segment to next lat bin to path
599 AddPath(DetDist - latI.detDist_nextBin, fEarthBins[index]);
600 double latitude_crossing =
601 fEarthBins[index].latitude + latI.sign * latI.dLat;
602
603 // Move lat bins
604 DetDist = latI.detDist_nextBin;
605 index += latI.nextBin - latI.bin;
606 latI.bin = latI.nextBin;
607 // cout << "Latitude bin crossing at x=" << DetDist << "km,lat=" <<
608 // latitude_crossing << "rad...now in Earth bin " << index << " = (r"
609 // << floor(index/(fnLonBins*fnLatBins)) << ", lon" << lonI.bin << ",
610 // lat" << latI.bin << ")" << endl;
611
612 // Find next lat bin
613 if (latI.dLat ==
614 0) { // Only 1 lat bin crossing along entire neutrino trajectory
615 latI.detDist_nextBin = -1;
616 }
617 else {
618 latI.detDist_nextBin = DetDistForNextLatBin(index, latI);
619 latI.nextBin = latI.bin + latI.sign;
620 }
621 }
622 else { // if next lon bin crossing is before (or simultaneous with) next lat
623 // bin corssing
624 // Add segment to next lon bin to path
625 AddPath(DetDist - lonI.detDist_nextBin, fEarthBins[index]);
626
627 // Move lon bins
628 DetDist = lonI.detDist_nextBin;
629 index += (lonI.nextBin - lonI.bin) * fnLatBins;
630 lonI.bin = lonI.nextBin;
631 // cout << "Longitude bin crossing at x=" << DetDist << "km...now in
632 // Earth bin " << index << " = (r" <<
633 // floor(index/(fnLonBins*fnLatBins)) << ", lon" << lonI.bin << ",
634 // lat" << latI.bin << ")" << endl;
635
636 // Find next lon bin
637 if (lonI.dLon ==
638 0) { // Only 1 lon bin crossing along entire neutrino trajectory
639 lonI.detDist_nextBin = -1;
640 }
641 else {
642 lonI.detDist_nextBin =
643 DetDistForNextLonBin(fEarthBins[index].longitude, lonI);
644 }
645 }
646 }
647}
648
649//.............................................................................
655int EarthModelBinned::LonBinIndex(double longitude)
656{
657 // Find difference between longitude and beginning of first lon bin
658 double londiff = longitude - (fEarthBins[0].longitude - fHalfLonBinWidth);
659
660 // Shift londiff to be between 0 and 2pi
661 if (londiff < 0 || londiff >= 2 * M_PI)
662 londiff -= floor(londiff / (2 * M_PI));
663
664 // Number of binwidths after from first lon bin
665 return floor(londiff * fInvLonBinWidth);
666}
667
668//.............................................................................
691int EarthModelBinned::FillPath(double cosT, double phi)
692{
693 // Clear current path sequence
694 fNuPath.clear();
695
696 // Do nothing if cosine is unphysical
697 if (fabs(cosT) > 1) return 0;
698
699 // Calculate useful combinations of variables
700 double Az = phi / 180.0 * M_PI; // convert from degrees to radians
701 fC.UpdateNuAngles(cosT, Az);
702 fC.Recalculate();
703 double rDetSqSinSqT = pow(fC.rDetSinT, 2);
704 double distEdgeToMin =
705 sqrt(fRadiusMax * fRadiusMax -
706 rDetSqSinSqT); // distance from point where neutrino enters to
707 // minimum depth (neglecting stopping at the detector)
708 double baseline = distEdgeToMin - fC.rDetCosT; // total baseline
709
710 // Define the maximum depth (minimum radius) along the path (detector
711 // depth/radius, if cosT is non-negative)
712 double minRadius = fDetRadius;
713 if (cosT < 0) { minRadius = fC.rDetSinT; }
714
715 // Starting latitude
716 /* cout << "Pieces of init_lat calculation:" << endl
717 << "\trDetSinT = " << fC.rDetSinT << endl
718 << "\tbeta = " << fC.beta << endl
719 << "\tgamma = " << fC.gamma << endl
720 << "\tdistEdgeToMin = " << distEdgeToMin << endl
721 << "\tRadiusMax = " << fRadiusMax << endl; */
722 double init_lat = asin((fC.rDetSinT * fC.beta + fC.gamma * distEdgeToMin) /
723 fRadiusMax); // in radians
724
725 // Starting longitude
726 double init_lon = atan2(
728 baseline * (fC.alpha * fC.sinDetLon + fC.sinTsinAcosDetLon),
730 baseline *
732 fC.alpha * fC.cosDetLon)); // in radians (between -M_PI and M_PI)
733 if (init_lon < 0) { init_lon += 2 * M_PI; }
734
735 // Get initial Earth bin and # of bins per depth layer
736 LatBinInfo latinfo;
737 LonBinInfo loninfo;
738 int binsPerDepth = fEarthBins.size() / fnDepthBins;
739 int init_lonBin = LonBinIndex(init_lon);
740 int init_latBin = floor((init_lat + M_PI / 2.0) * fInvLatBinWidth);
741 int index =
742 fEarthBins.size() - binsPerDepth + init_lonBin * fnLatBins + init_latBin;
743
744 latinfo.bin = init_latBin;
745 loninfo.bin = init_lonBin;
746 // cout << "Neutrino starting at (lat,lon)=(" << init_lat << "rad," <<
747 // init_lon << "rad) in Earth bin " << index << " = (r" <<
748 // floor(index/binsPerDepth) << ", lon" << loninfo.bin << ", lat" <<
749 // latinfo.bin << ")" << endl;
750
751 /* Find detector distances for 1st latitude/longitude bin changes */
752 latinfo.dLat = fHalfLatBinWidth; // change in lat from bin center to next bin
753 // (0 if no more than 1 lat bin change)
754 // Condition calculation for starting sign in x(lat) equation
755 latinfo.sign = 1; //+ => lat incr., - => lat decr. (with decr. x)
756 latinfo.maxreached =
757 false; // this changes to true if past the lat func transition
758 if (fC.beta < 0) latinfo.sign = -1;
759 if (fC.beta == 0) {
760 if (fC.cosA > 0) latinfo.sign = -1;
761 }
762 else if (baseline < fC.xlatextreme) {
763 latinfo.sign = -(latinfo.sign);
764 latinfo.maxreached = true;
765 }
766 // Condition calculation for incr./decr. Longitude (with decr. x)
767 loninfo.dLon =
768 fHalfLonBinWidth; // change in lon from bin center to next bin (includes
769 // direction; 0 if no more than 1 lon bin change)
770 loninfo.min = init_lon; // initial lon if lon is inc.
771 loninfo.max = fDetLon; // detector lon if lon is inc.
772 if (fC.sinA < 0) {
773 loninfo.dLon = -(loninfo.dLon);
774 loninfo.min = loninfo.max;
775 loninfo.max = init_lon;
776 // Switch max/min if dec., instead of inc.
777 loninfo.max = init_lon;
778 loninfo.min = fDetLon;
779 }
780 // Remainder of detDist (and nextBin) calculations
781 if (fC.sinT == 0) {
782 // both latitude and logitude flip at center of the Earth
783 loninfo.detDist_nextBin =
784 -fC.rDetCosT; // formula is divided by cosT, but cosT = +-1
785 loninfo.nextBin = LonBinIndex(fDetLon);
786 loninfo.dLon = 0;
787 latinfo.detDist_nextBin = loninfo.detDist_nextBin;
788 latinfo.nextBin = floor((fDetLat + 0.5 * M_PI) * fInvLatBinWidth);
789 latinfo.dLat = 0;
790 }
791 else {
792 if (fC.sinA == 0) {
793 if (fC.alpha == 0) { // crosses "at" infinity
794 loninfo.detDist_nextBin = -1;
795 }
796 else { // longitude flips at center of the Earth
798 loninfo.nextBin = LonBinIndex(fDetLon);
799 }
800 loninfo.dLon = 0;
801 }
802 else if (fC.cosDetLat == 0) {
803 loninfo.detDist_nextBin = -1;
804 }
805 else {
806 // x(lon) calculation
808 fEarthBins[index].longitude, loninfo); // also sets loninfo.nextBin
809 }
810 // x(lat) calculation
811 latinfo.detDist_nextBin = DetDistForNextLatBin(index, latinfo);
812 latinfo.nextBin = init_latBin + latinfo.sign;
813 }
814
815 // Get initial Detector Distance
816 double prev_DetDistance = baseline;
817
818 /* Start at the top layer of Earth model and go down to minimum (not including
819 * minimum), looping over depth bins */
820 int dBin = 0; // depth bin index
821 for (dBin = 0; dBin < fnDepthBins - 1; dBin++) {
822 // Check if minimum radius is contained in depth bin
823 double r_in = fEarthBins[index].radius_in; // inner-most radius
824 if (r_in < minRadius) break;
825
826 // Distance from detector at inner-most radius
827 double DetDistance = -fC.rDetCosT + sqrt(r_in * r_in - rDetSqSinSqT);
828
829 // Check for latitude/longitude bin crossings
830 RecordLatLonBinCrossings(DetDistance, prev_DetDistance, index, latinfo,
831 loninfo);
832
833 // Add Segment to next depth bin to path
834 AddPath(prev_DetDistance - DetDistance, fEarthBins[index]);
835
836 // Reset variables for next depth bin
837 prev_DetDistance = DetDistance;
838 index -= binsPerDepth;
839 // cout << "Depth bin crossing at x=" << DetDistance << "km...now in
840 // Earth bin " << index << " = (r" << floor(index/binsPerDepth) << ",
841 // lon" << loninfo.bin << ", lat" << latinfo.bin << ")" << endl;
842 }
843
844 /* Do minimum depth bin and then go up to the detector */
845 int index2 = index;
846 for (index2 = index; fEarthBins[index2].radius_out < fDetRadius;
847 index2 += binsPerDepth) {
848 double r_out = fEarthBins[index2].radius_out; // outer-most radius
849
850 // Distance from detector at outer-most radius
851 double DetDistance = -fC.rDetCosT - sqrt(r_out * r_out - rDetSqSinSqT);
852
853 // Check for latitude/longitude bin crossings
854 RecordLatLonBinCrossings(DetDistance, prev_DetDistance, index2, latinfo,
855 loninfo);
856
857 // Add Segment in depth bin to path
858 AddPath(prev_DetDistance - DetDistance, fEarthBins[index2]);
859
860 // Reset variables for "previous" depth bin
861 prev_DetDistance = DetDistance;
862 // cout << "Depth bin crossing at x=" << DetDistance << "km...now in
863 // Earth bin " << index2 << " = (r" <<
864 // floor((index2+binsPerDepth)/binsPerDepth) << ", lon" << loninfo.bin <<
865 // ", lat" << latinfo.bin << ")" << endl;
866 }
867
868 /* Do path to detector */
869 // Check for latitude/longitude bin crossings
870 RecordLatLonBinCrossings(0, prev_DetDistance, index2, latinfo, loninfo);
871 // Add the path segment within the detector bin
872 AddPath(prev_DetDistance, fEarthBins[index2]);
873
874 // Longitude calculation error message, if needed
875 if (loninfo.error < 0) {
876 cerr
877 << "ERROR: Oops... It turns out that I was wrong about the denominator"
878 << " of the x(long) equation never being 0 apart from the cases where "
879 << "sin(Zenith) = 0, sin(Azimuthal) = 0, or cos(Detector Longitude) = "
880 << "0."
881 << " Send the following message to rpestes@apc.in2p3.fr:" << endl
882 << endl
883 << "You were wrong about the denominator of x(long)... "
884 << "Here are the values of the variables that broke it:" << endl
885 << "\tDetector Coordinates (r,lat,lon) = (" << fDetRadius << ", "
886 << fDetLat << ", " << fDetLon << ")" << endl
887 << "\tcos(Zenith Angle) = " << cosT << endl
888 << "\tAzimuthal Angle = " << phi << " deg" << endl
889 << "\t" << loninfo.err_message << endl
890 << "Please fix this ASAP!" << endl;
891 return -1;
892 }
893
894 // Return the number of path segments
895 return fNuPath.size();
896}
double fRadiusMax
Maximum radius in Earth model (in km)
double fDetLat
The latitude (in rad) where the detector sits.
double fDetLon
The longitude (in rad) where the detector sits.
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 double GetRegionZoA(int index)
Get Z/A of all bins with specified region index.
virtual double DetDistForNextLonBin(double prev_lon, LonBinInfo &L)
std::vector< EarthBin > fEarthBins
The bins in the earth model.
virtual void ClearModel()
Clear the earth model information.
double fInvLonBinWidth
1/binwidth for each longitude bin
virtual void AddPath(double length, EarthBin bin)
Add a path segment to the sequence.
virtual ~EarthModelBinned()
Destructor.
int fnDepthBins
Total number of depth bins.
int FillPath(double cosT, double phi=0)
virtual std::vector< EarthBin > GetEarthBins()
virtual void LoadModel(std::string filename)
Load an earth model from a file.
EarthModelBinned(std::string filename="")
Constructor.
virtual void RecordLatLonBinCrossings(double detDist_nextDbin, double &DetDist, int &index, LatBinInfo &latI, LonBinInfo &lonI)
double fHalfLonBinWidth
Half-width of each longitude bin.
void SetDetPos(double rad, double lat=0, double lon=0)
virtual void SetRegionZoA(int index, double zoa)
Set Z/A of all bins with specified region index.
int fnLatBins
Total number of latitude bins.
virtual void AddBin(double radius_out, double radius_in, double latitude, double longitude, double density, double zoa, double layer)
Add a bin to the model (angles in degrees)
double fHalfLatBinWidth
Half-width of each latitude bin.
double fInvLatBinWidth
1/binwidth for each latitude bin
virtual int LonBinIndex(double longitude)
Find lon bin index containing longitude.
TrajConstants fC
Useful constants for the trajectory.
int fmaxRegIndex
Largest region index in model.
virtual void ScaleRegionDensity(int index, double scalingfactor)
virtual double DetDistForNextLatBin(int cur_index, LatBinInfo &L)
int fnLonBins
Total number of longitude bins.
Some useful general definitions.
Definition: Absorption.h:6
Definition: EigenPoint.h:44
double radius_in
The inner radius of the bin in km.
void SetBin(double r_out=0, double r_in=0, double lat=0, double lon=0, double den=0, double z=0.5, int n=0)
Set the properties of the bin.
double latitude
The latitude of the bin center in radians.
double longitude
The longitude of the bin center in radians.
double zoa
The effective Z/A value of the matter in the bin.
double radius_out
The outer radius of the bin in km.
int index
Region index.
EarthBin(double r_out=0, double r_in=0, double lat=0, double lon=0, double den=0, double z=0.5, int n=0)
Constructor.
double density
The density of the matter in the bin in g/cm^3.
A struct holding information about upcoming latitude bin crossings along the neutrino's trajectory.
int nextBin
Index of next latitude bin.
int bin
Index of current latitude bin.
A struct holding information about upcoming longitude bin crossings along the neutrino's trajectory.
int nextBin
Index of next longitude bin.
int bin
Index of current longitude bin.
std::string err_message
Part of error message specific to piece of path.
double cosTcosDetLat
cosT*cos(DetLat)
double sinTsinA
sin(T)*sin(phi)
double cosDetLon
cos(DetLon)
double beta
sin(T)*sin(DetLat)-cos(phi)*cosT*cos(DetLat)
double gammaSq
[sin(T)*cos(phi)*cos(DetLat)+cosT*sin(DetLat)]^2
double sinDetLat
sin(DetLat)
double rDetSinT
rDet*sin(T)
double sinTcosA
sin(T)*cos(phi)
double alpha
sin(T)*cos(phi)*sin(DetLat)-cosT*cos(DetLat)
double rDetCosT
rDet*cosT
double rDetGammaSinDetLat
rDet*sin(DetLat)*[sin(T)*cos(phi)*cos(DetLat)+cosT*sin(DetLat)]
double sinSqT
sin^2(T) = 1 - (cosT)^2
double sinDetLon
sin(DetLon)
double sinTsinAsinDetLon
sin(T)*sin(phi)*sin(DetLon)
void UpdateDetPos(double rDet, double DetLat, double DetLon)
double gamma
sin(T)*cos(phi)*cos(DetLat)+cosT*sin(DetLat)
double maxSinSqLat
1 - [sin(phi)*cos(DetLat)]^2
void UpdateNuAngles(double cosTheta, double phi)
double rDetSinDetLat
rDet*sin(DetLat)
double rDetCosDetLat
rDet*cos(DetLat)
double cosDetLat
cos(DetLat)
double sinT
sin(T) = sqrt(sinSqT)
double sinTsinAcosDetLon
sin(T)*sin(phi)*cos(DetLon)