3 #include "earthmodel.hh" 11 #include "icemc_random.h" 14 #include "Primaries.h" 15 #include "secondaries.hh" 16 #include "EnvironmentVariable.h" 19 const string ICEMC_DATA_DIR=ICEMC_SRC_DIR+
"/data/";
21 const string crust20_in=ICEMC_DATA_DIR+
"/outcr";
22 const string crust20_out=ICEMC_SRC_DIR+
"/altitudes.txt";
31 const double EarthModel::COASTLINE(30.);
32 const double EarthModel::MAXTHETA(180.);
33 const int EarthModel::ILAT_COASTLINE((
int)((COASTLINE/MAXTHETA)*(
double)NLAT+0.00001));
34 const double EarthModel::GEOID_MAX(6.378137E6);
35 const double EarthModel::GEOID_MIN(6.356752E6);
38 EarthModel::EarthModel(
int model,
int WEIGHTABSORPTION_SETTING) {
43 radii[1]=(EarthModel::R_EARTH-4.0E4)*(EarthModel::R_EARTH-4.0E4);
44 radii[2]=(EarthModel::R_EARTH*EarthModel::R_EARTH);
48 weightabsorption= WEIGHTABSORPTION_SETTING;
50 CONSTANTICETHICKNESS = (int) (model / 1000);
51 model -= CONSTANTICETHICKNESS * 1000;
53 CONSTANTCRUST = (int) (model / 100);
54 model -= CONSTANTCRUST * 100;
56 FIXEDELEVATION = (int) (model / 10);
57 model -= FIXEDELEVATION * 10;
61 for (
int i=0;i<NLON;i++) {
63 Tools::Zero(elevationarray[i],NLAT);
64 Tools::Zero(waterthkarray[i],NLAT);
65 Tools::Zero(icethkarray[i],NLAT);
66 Tools::Zero(softsedthkarray[i],NLAT);
67 Tools::Zero(hardsedthkarray[i],NLAT);
68 Tools::Zero(uppercrustthkarray[i],NLAT);
69 Tools::Zero(middlecrustthkarray[i],NLAT);
70 Tools::Zero(lowercrustthkarray[i],NLAT);
71 Tools::Zero(crustthkarray[i],NLAT);
74 Tools::Zero(surfacer[i],NLAT);
75 Tools::Zero(icer[i],NLAT);
76 Tools::Zero(waterr[i],NLAT);
77 Tools::Zero(softsedr[i],NLAT);
78 Tools::Zero(hardsedr[i],NLAT);
79 Tools::Zero(uppercrustr[i],NLAT);
80 Tools::Zero(middlecrustr[i],NLAT);
81 Tools::Zero(lowercrustr[i],NLAT);
83 Tools::Zero(waterdensityarray[i],NLAT);
84 Tools::Zero(icedensityarray[i],NLAT);
85 Tools::Zero(softseddensityarray[i],NLAT);
86 Tools::Zero(hardseddensityarray[i],NLAT);
87 Tools::Zero(uppercrustdensityarray[i],NLAT);
88 Tools::Zero(middlecrustdensityarray[i],NLAT);
89 Tools::Zero(lowercrustdensityarray[i],NLAT);
94 for (
int i=0;i<NLAT;i++) {
95 geoid[i]=GEOID_MIN*GEOID_MAX/sqrt(pow(GEOID_MIN,2.)-(pow(GEOID_MIN,2.)-pow(GEOID_MAX,2.))*pow(cos(dGetTheta(i)),2.));
101 phistep=2*PI/(double)NLON;
102 thetastep=(MAXTHETA*RADDEG)/NLAT;
103 for (
int i=0;i<NLAT;i++) {
104 area[i]=phistep*(cos(dGetTheta(i))-cos(dGetTheta(i+1)))*pow(geoid[i],2.);
107 if (EARTH_MODEL == 0)
108 ReadCrust(crust20_in);
110 cout<<
"Error! Unknown Earth model requested! Defaulting to Crust 2.0 model.\n";
111 ReadCrust(crust20_in);
116 EarthModel::~EarthModel() {}
119 double EarthModel::LongtoPhi_0isPrimeMeridian(
double longitude) {
132 double EarthModel::LongtoPhi_0is180thMeridian(
double longitude) {
137 phi=(270.-longitude);
147 double EarthModel::Geoid(
double latitude) {
150 return (GEOID_MIN*GEOID_MAX/
151 sqrt(GEOID_MIN*GEOID_MIN-(GEOID_MIN*GEOID_MIN-GEOID_MAX*GEOID_MAX)*
152 cos(latitude*RADDEG)*cos(latitude*RADDEG)));
155 double EarthModel::Geoid(
const Position &pos) {
156 return Geoid(pos.
Lat());
159 double EarthModel::IceThickness(
double lon,
double lat) {
160 return icethkarray[(int)(lon/2)][(int)(lat/2)]*1000.;
163 double EarthModel::IceThickness(
const Position& pos) {
164 return IceThickness(pos.
Lon(),pos.
Lat());
166 int EarthModel::InFirn(
const Position& pos) {
167 if (pos.Mag()-Surface(pos)<FIRNDEPTH)
171 double EarthModel::SurfaceDeepIce(
const Position& pos) {
172 return surfacer[(int)(pos.
Lon()/2)][(
int)(pos.
Lat()/2)] + geoid[(
int)(pos.
Lat()/2)] + FIRNDEPTH;
175 double EarthModel::Surface(
double lon,
double lat) {
176 return surfacer[(int)(lon/2)][(int)(lat/2)] + geoid[(int)(lat/2)];
179 double EarthModel::Surface(
const Position& pos) {
180 return surfacer[(int)(pos.
Lon()/2)][(
int)(pos.
Lat()/2)] + geoid[(
int)(pos.
Lat()/2)];
183 double EarthModel::RockSurface(
double lon,
double lat) {
184 return (Surface(lon,lat) - IceThickness(lon,lat) - WaterDepth(lon,lat));
187 double EarthModel::RockSurface(
const Position& pos) {
188 return RockSurface(pos.
Lon(),pos.
Lat());
191 double EarthModel::SurfaceAboveGeoid(
double lon,
double lat) {
192 return surfacer[(int)(lon/2)][(int)(lat/2)];
195 double EarthModel::SurfaceAboveGeoid(
const Position& pos) {
196 return surfacer[(int)(pos.
Lon()/2)][(
int)(pos.
Lat()/2)];
199 double EarthModel::WaterDepth(
double lon,
double lat) {
200 return waterthkarray[(int)(lon/2)][(int)(lat/2)]*1000;
203 double EarthModel::WaterDepth(
const Position& pos) {
204 return WaterDepth(pos.
Lon(),pos.
Lat());
207 double EarthModel::GetLat(
double theta) {
211 double EarthModel::GetLon(
double phi) {
213 double phi_deg = phi*DEGRAD;
215 phi_deg = phi_deg - 360.;
217 return (360.*3./4. - phi_deg);
220 double EarthModel::GetDensity(
double altitude,
const Position earth_in,
227 double lon = where.
Lon();
228 double lat = where.
Lat();
231 int ilon = (int)(lon/2);
232 int ilat = (int)(lat/2);
236 double surface_elevation = this->SurfaceAboveGeoid(lon,lat);
238 double local_icethickness = this->IceThickness(lon,lat);
239 double local_waterdepth = WaterDepth(lon,lat);
241 if (inice) *inice =
false;
244 if(altitude>surface_elevation+0.1){
247 if(altitude>surface_elevation+0.1){
251 if (altitude<=surface_elevation+0.1 && altitude>(surface_elevation-local_icethickness))
253 ddensity=icedensityarray[ilon][ilat]*1000;
254 if (inice) *inice =
true;
257 else if (altitude<=(surface_elevation-local_icethickness) && altitude>(surface_elevation-local_icethickness-local_waterdepth))
258 ddensity=waterdensityarray[ilon][ilat]*1000;
259 else if (altitude<=(surface_elevation-local_icethickness-local_waterdepth) && altitude>softsedr[ilon][ilat]) {
260 ddensity=softseddensityarray[ilon][ilat]*1000;
263 else if (altitude<=softsedr[ilon][ilat] && altitude>hardsedr[ilon][ilat])
264 ddensity=hardseddensityarray[ilon][ilat]*1000;
265 else if (altitude<=hardsedr[ilon][ilat] && altitude>uppercrustr[ilon][ilat])
266 ddensity=uppercrustdensityarray[ilon][ilat]*1000;
267 else if (altitude<=uppercrustr[ilon][ilat] && altitude>middlecrustr[ilon][ilat])
268 ddensity=middlecrustdensityarray[ilon][ilat]*1000;
269 else if (altitude<=middlecrustr[ilon][ilat] && altitude>lowercrustr[ilon][ilat])
270 ddensity=lowercrustdensityarray[ilon][ilat]*1000;
271 else if (altitude<=lowercrustr[ilon][ilat])
272 ddensity=densities[1];
280 int EarthModel::Getchord(
Settings *settings1,
283 double distance_in_ice,
284 bool include_ice_absorption,
288 double& probability_tmp,
290 double& nearthlayers,
309 chord3 = posnu - earth_in;
311 nchord = chord3 / chord;
314 cout <<
"short chord " << chord <<
"\n";
317 if (chord>2.*R_EARTH+1000) {
318 cout <<
"bad chord" <<
" " << chord <<
". Event is " << inu <<
"\n";
326 double costh=(where*nchord)/where.Mag();
327 double sinth=sqrt(1-costh*costh);
333 if (getchord_method<1 || getchord_method>3)
334 cout <<
"Bogus method!\n";
338 if (getchord_method==1) {
342 if (sinth>sqrt(radii[1]/radii[2])) {
346 L=len_int_kgm2/densities[2];
348 weight1_tmp=exp(-posnu.
Distance(where)/L);
354 L=len_int_kgm2/densities[2];
356 halfchord=sqrt(radii[1]-radii[2]*sinth*sinth);
357 distance=sqrt(radii[2])*costh-halfchord;
359 weight1_tmp=exp(-distance/L);
362 where = earth_in + distance*nchord;
365 costh=(where*nchord)/where.Mag();
366 sinth=sqrt(1-costh*costh);
368 if (sinth>sqrt(radii[0]/radii[1])) {
371 halfchord=sqrt(radii[1])*costh;
375 L=len_int_kgm2/densities[1];
378 weight1_tmp *= exp(-2*halfchord/L);
380 L=len_int_kgm2/densities[2];
382 where = where + 2*halfchord*nchord;
383 weight1_tmp*=exp(-where.
Distance(posnu)/L);
388 L=len_int_kgm2/densities[1];
391 halfchord=sqrt(radii[0]-radii[1]*sinth*sinth);
392 distance=sqrt(radii[1])*costh-halfchord;
393 weight1_tmp*=exp(-distance/L);
396 L=len_int_kgm2/densities[0];
397 weight1_tmp*=exp(-2*halfchord/L);
400 L=len_int_kgm2/densities[1];
401 weight1_tmp*=exp(-distance/L);
404 L=len_int_kgm2/densities[2];
406 where = where + (2*distance+2*halfchord)*nchord;
407 weight1_tmp*=exp(-where.
Distance(posnu)/L);
411 if (getchord_method==2) {
420 double surface_elevation = this->SurfaceAboveGeoid(lon,lat);
427 double step=Tools::dMin(len_int_kgm2/densities[1]/10,500.);
431 weight1_tmp*=exp(-myair/len_int_kgm2);
437 double L_ice=len_int_kgm2/Signal::RHOICE;
439 if (settings1->UNBIASED_SELECTION)
440 probability_tmp*=1-exp(-1.*(distance_in_ice/L_ice));
444 double ddensity=Signal::RHOAIR;
447 if (where*nchord>0.) {
448 cout <<
"This one's trouble. Neutrino exit point looks more like an entrance point. Event is " << inu <<
"\n";
449 cout <<
"where is " << where[0] <<
" " << where[1] <<
" " << where[2] <<
"\n";
450 cout <<
"nchord is " << nchord[0] <<
" " << nchord[1] <<
" " << nchord[2] <<
"\n";
451 cout <<
"dot product is " << where*nchord/sqrt(where*where) <<
"\n";
452 cout <<
"posnu is " << posnu[0] <<
" " << posnu[1] <<
" " << posnu[2] <<
"\n";
453 cout <<
"Length of chord is : "<<chord<<endl;
456 altitude=where.Mag()-Geoid(lat);
458 if(altitude>surface_elevation+0.1)
459 cout <<
"neutrino entrance point is above the surface. Event is " << inu <<
"\n";
462 while(altitude>MIN_ALTITUDE_CRUST && x<posnu.
Distance(earth_in)) {
466 ddensity = this->GetDensity(altitude,where,crust_entered,&inice);
468 L=len_int_kgm2/ddensity;
469 if (!inice || include_ice_absorption)
471 weight1_tmp*=exp(-step/L);
472 total_kgm2+=ddensity*step;
474 if (exp(-step/L) > 1)
475 cout<<
"Oops! len_int_kgm2, ddensity, factor : "<<len_int_kgm2<<
" , "<<ddensity<<
" , "<<exp(-step/L)<<endl;
478 where += step*nchord;
484 altitude=where.Mag()-Geoid(lat);
485 surface_elevation = this->SurfaceAboveGeoid(lon,lat);
491 if (x>posnu.
Distance(earth_in) && weightabsorption) {
492 probability_tmp*=weight1_tmp;
496 if (altitude<=MIN_ALTITUDE_CRUST) {
501 sinth=sin(where.Angle(nchord));
502 costh=sqrt(1-sinth*sinth);
504 if (sinth>sqrt(radii[0]/radii[1])) {
508 L=len_int_kgm2/densities[1];
509 halfchord=sqrt(radii[1])*costh;
511 weight1_tmp *= exp(-2*halfchord/L);
512 total_kgm2+= 2*halfchord*densities[1];
513 where += (2*halfchord)*nchord;
522 L=len_int_kgm2/densities[1];
525 halfchord=sqrt(radii[0]-radii[1]*sinth*sinth);
526 distance=sqrt(radii[1])*costh-halfchord;
527 weight1_tmp*=exp(-distance/L);
528 total_kgm2 += 2*distance*densities[1];
530 L=len_int_kgm2/densities[0];
531 weight1_tmp*=exp(-2*halfchord/L);
532 total_kgm2 += 2*halfchord*densities[0];
534 L=len_int_kgm2/densities[1];
535 weight1_tmp*=exp(-distance/L);
536 if (exp(-distance/L) > 1)
537 cout<<
"Oops2! len_int_kgm2, ddensity, distance, factor : "<<len_int_kgm2<<
" , "<<ddensity<<
" , "<<distance<<
" , "<<exp(-distance/L)<<endl;
538 where += (2*distance+2*halfchord)*nchord;
547 altitude=where.Mag()-Geoid(lat);
548 surface_elevation = this->SurfaceAboveGeoid(lon,lat);
552 double distance_remaining=where.
Distance(posnu);
555 while(x<=distance_remaining) {
558 ddensity=this->GetDensity(altitude,where,crust_entered,&inice);
560 L=len_int_kgm2/ddensity;
562 if (!inice || include_ice_absorption)
564 weight1_tmp*=exp(-step/L);
565 total_kgm2 += step*ddensity;
568 if (exp(-step/L) > 1)
569 cout<<
"Oops3! len_int_kgm2, ddensity, step, factor : "<<len_int_kgm2<<
" , "<<ddensity<<
" , "<<step<<
" , "<<exp(-step/L)<<endl;
574 where += step*nchord;
580 altitude=where.Mag()-Geoid(lat);
581 surface_elevation = this->SurfaceAboveGeoid(lon,lat);
588 probability_tmp*=weight1_tmp;
591 if (weightabsorption==0) {
592 if (getRNG(RNG_ABSORB)->Rndm()>weight1_tmp) {
606 cout <<
"made it this far.\n";
613 Vector n_surf = r_out.Unit();
617 double theta=r_out.Theta();
620 GetILonILat(r_out,ilon,ilat);
622 int ilon_previous=ilon-1;
624 ilon_previous=NLON-1;
626 int ilon_next=ilon+1;
630 double r=(geoid[ilat]+surfacer[ilon][ilat])*sin(theta);
632 double slope_phi=(surfacer[ilon_next][ilat]-surfacer[ilon_previous][ilat])/(r*2*phistep);
634 int ilat_previous=ilat-1;
638 int ilat_next=ilat+1;
642 double slope_costheta=(surfacer[ilon][ilat_next]-surfacer[ilon][ilat_previous])/((geoid[ilat]+surfacer[ilon][ilat])*2*thetastep);
645 double angle=atan(slope_costheta);
647 n_surf = n_surf.RotateY(angle);
650 angle=atan(slope_phi);
652 n_surf = n_surf.RotateZ(angle);
658 double EarthModel::SmearPhi(
int ilon,
double rand) {
661 double phi=((double)(360.*3./4.-((
double)ilon+rand)*360/180))*RADDEG;
662 if (phi<0 && phi>-1*PI/2)
669 double EarthModel::SmearTheta(
int ilat,
double rand) {
674 double theta1=dGetTheta(ilat)-PI/(double)NLAT/2.;
675 double theta2=dGetTheta(ilat+1)-PI/(double)NLAT/2.;
677 double costheta1=cos(theta1);
678 double costheta2=cos(theta2);
682 double costheta=rand*(costheta2-costheta1)+costheta1;
684 double theta=acos(costheta);
689 void EarthModel::ReadCrust(
string test) {
694 fstream infile(test.c_str(),ios::in);
711 while(!infile.eof()) {
712 getline(infile,thisline,
'\n');
714 int loc=thisline.find(
"type, latitude, longitude,");
716 if (loc!=(
int)(string::npos)) {
718 beginindex=thisline.find_first_not_of(
" ",57);
720 endindex=thisline.find_first_of(
" ",61);
722 slat=thisline.substr(beginindex,endindex-beginindex);
723 dlat=(double)atof(slat.c_str());
725 beginindex=thisline.find_first_not_of(
" ",68);
726 endindex=thisline.find_first_of(
" ",72);
728 slon=thisline.substr(beginindex,endindex-beginindex);
729 dlon=(double)atof(slon.c_str());
732 indexlon=(int)((dlon+180)/2);
733 indexlat=(int)((90+dlat)/2);
735 beginindex=thisline.find_first_not_of(
" ",78);
736 endindex=thisline.find_first_of(
" ",83);
738 selev=thisline.substr(beginindex,endindex-beginindex);
739 elevationarray[indexlon][indexlat]=(double)atof(selev.c_str());
743 for (
int i=0;i<4;i++) {
744 getline(infile,thisline,
'\n');
747 for (
int i=0;i<7;i++) {
748 getline(infile,thisline,
'\n');
750 endindex=thisline.length()-1;
751 beginindex=thisline.find_last_of(
"0123456789",1000);
752 layertype=thisline.substr(beginindex+3,endindex-beginindex);
755 beginindex=thisline.find_first_not_of(
" ",0);
756 endindex=thisline.find_first_of(
" ",beginindex);
758 sdepth=thisline.substr(beginindex,endindex-beginindex-1);
762 if (layertype.substr(0,5)==
"water")
763 waterthkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
764 if (layertype.substr(0,3)==
"ice")
765 icethkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
766 if (layertype.substr(0,8)==
"soft sed")
767 softsedthkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
768 if (layertype.substr(0,8)==
"hard sed")
769 hardsedthkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
770 if (layertype.substr(0,11)==
"upper crust")
771 uppercrustthkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
772 if (layertype.substr(0,12)==
"middle crust")
773 middlecrustthkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
774 if (layertype.substr(0,11)==
"lower crust")
775 lowercrustthkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
781 if (indexlat==5 && (indexlon<=5 || indexlon>=176))
782 icethkarray[indexlon][indexlat]=0.5;
784 beginindex=thisline.find_first_not_of(
" ",endindex);
785 endindex=thisline.find_first_of(
" ",beginindex);
788 beginindex=thisline.find_first_not_of(
" ",endindex);
789 endindex=thisline.find_first_of(
" ",beginindex);
791 beginindex=thisline.find_first_not_of(
" ",endindex);
792 endindex=thisline.find_first_of(
" ",beginindex);
795 sdensity=thisline.substr(beginindex,endindex-beginindex);
797 double ddensity=(double)atof(sdensity.c_str());
801 if (layertype.substr(0,5)==
"water")
802 waterdensityarray[indexlon][indexlat]=ddensity;
803 if (layertype.substr(0,3)==
"ice")
804 icedensityarray[indexlon][indexlat]=ddensity;
805 if (layertype.substr(0,8)==
"soft sed")
806 softseddensityarray[indexlon][indexlat]=ddensity;
807 if (layertype.substr(0,8)==
"hard sed")
808 hardseddensityarray[indexlon][indexlat]=ddensity;
809 if (layertype.substr(0,11)==
"upper crust")
810 uppercrustdensityarray[indexlon][indexlat]=ddensity;
811 if (layertype.substr(0,12)==
"middle crust")
812 middlecrustdensityarray[indexlon][indexlat]=ddensity;
813 if (layertype.substr(0,11)==
"lower crust")
814 lowercrustdensityarray[indexlon][indexlat]=ddensity;
818 softsedthkarray[indexlon][indexlat]=40.;
819 hardsedthkarray[indexlon][indexlat]=0;
820 uppercrustthkarray[indexlon][indexlat]=0;
821 middlecrustthkarray[indexlon][indexlat]=0;
822 lowercrustthkarray[indexlon][indexlat]=0;
823 crustthkarray[indexlon][indexlat]=0;
824 softseddensityarray[indexlon][indexlat]=2.9;
826 if (CONSTANTICETHICKNESS) {
827 icethkarray[indexlon][indexlat]=3.;
828 waterthkarray[indexlon][indexlat]=0.;
832 crustthkarray[indexlon][indexlat]=softsedthkarray[indexlon][indexlat]+
833 hardsedthkarray[indexlon][indexlat]+
834 uppercrustthkarray[indexlon][indexlat]+
835 middlecrustthkarray[indexlon][indexlat]+
836 lowercrustthkarray[indexlon][indexlat];
838 if (indexlon==179 && indexlat==0)
842 for (
int i=0;i<NLON;i++) {
843 for (
int j=0;j<NLAT;j++) {
846 elevationarray[i][j]=icethkarray[i][j]*1000;
848 if (waterthkarray[i][j] != 0)
849 surfacer[i][j]=elevationarray[i][j]+waterthkarray[i][j]*1000+icethkarray[i][j]*1000;
851 surfacer[i][j]=elevationarray[i][j];
853 if (fabs(surfacer[i][j])<1.E-10)
858 waterr[i][j]=surfacer[i][j]-(icethkarray[i][j]+waterthkarray[i][j])*1000;
859 if ((
double)fabs(waterr[i][j])<1.E-10)
861 icer[i][j]=waterr[i][j]+
862 waterthkarray[i][j]*1000;
863 softsedr[i][j]=waterr[i][j]-
864 softsedthkarray[i][j]*1000;
865 hardsedr[i][j]=waterr[i][j]-
866 (softsedthkarray[i][j]+
867 hardsedthkarray[i][j])*1000;
868 uppercrustr[i][j]=waterr[i][j]-
869 (softsedthkarray[i][j]+
870 hardsedthkarray[i][j]+
871 uppercrustthkarray[i][j])*1000;
872 middlecrustr[i][j]=waterr[i][j]-
873 (softsedthkarray[i][j]+
874 hardsedthkarray[i][j]+
875 uppercrustthkarray[i][j]+
876 middlecrustthkarray[i][j])*1000;
877 lowercrustr[i][j]=waterr[i][j]-
878 (softsedthkarray[i][j]+
879 hardsedthkarray[i][j]+
880 uppercrustthkarray[i][j]+
881 middlecrustthkarray[i][j]+
882 lowercrustthkarray[i][j])*1000;
891 max_icevol_perbin=0.;
892 max_icethk_perbin=0.;
893 for (
int j=0;j<ILAT_COASTLINE;j++) {
894 for (
int i=0;i<NLON;i++) {
895 volume+=icethkarray[i][j]*1000.*area[j];
896 if (icethkarray[i][j]>0)
898 if (icethkarray[i][j]*area[j]>max_icevol_perbin)
899 max_icevol_perbin=icethkarray[i][j]*area[j];
900 if (icethkarray[i][j]>max_icethk_perbin)
901 max_icethk_perbin=icethkarray[i][j];
912 average_iceth+=(surfacer[i][j]-icer[i][j])*area[j];
916 average_iceth=average_iceth/sumarea;
920 MIN_ALTITUDE_CRUST=1.E6;
922 for (
int i=0;i<NLON;i++) {
923 for (
int j=0;j<NLAT;j++) {
924 if (elevationarray[i][j]-(crustthkarray[i][j])*1000<MIN_ALTITUDE_CRUST) {
925 if (waterthkarray[i][j]==0)
926 MIN_ALTITUDE_CRUST=elevationarray[i][j]-(crustthkarray[i][j]+icethkarray[i][j])*1000;
928 MIN_ALTITUDE_CRUST=elevationarray[i][j]-crustthkarray[i][j]*1000;
936 radii[1]=(Geoid(0.)+MIN_ALTITUDE_CRUST)*(Geoid(0.)+MIN_ALTITUDE_CRUST);
941 Vector EarthModel::PickPosnuForaLonLat(
double lon,
double lat,
double theta,
double phi) {
944 double surface_above_geoid = this->SurfaceAboveGeoid(lon,lat);
945 double local_ice_thickness = this->IceThickness(lon,lat);
947 double rnd3=getRNG(RNG_POSNU)->Rndm();
951 double elevation = surface_above_geoid - rnd3*local_ice_thickness;
957 if (elevation > surface_above_geoid || elevation < (surface_above_geoid - local_ice_thickness))
958 cout<<
"elevation > surface_above_geoid || elevation < (surface_above_geoid - local_ice_thickness)\n";
960 Vector posnu((elevation+this->Geoid(lat))*sin(theta)*cos(phi),(elevation+this->Geoid(lat))*sin(theta)*sin(phi),(elevation+this->Geoid(lat))*cos(theta));
962 if (((this->Geoid(lat) + surface_above_geoid)) - posnu.Mag() < 0) {
970 double EarthModel::dGetTheta(
int ilat) {
971 return (((
double)ilat+0.5)/(
double)NLAT*MAXTHETA)*RADDEG;
974 double EarthModel::dGetPhi(
int ilon) {
978 return (
double)(-1*((double)ilon+0.5)+(double)NLON)*2*PI/(double)NLON-PI/2;
981 void EarthModel::GetILonILat(
const Position &p,
int& ilon,
int& ilat) {
983 double phi_deg=p.Phi()*DEGRAD;
989 ilon=(int)((360.*3./4.-phi_deg)*180./360.);
991 ilat=(int)((p.Theta()*DEGRAD)/2.);
994 void EarthModel::EarthCurvature(
double *array,
double depth_temp) {
997 parray.SetXYZ(array[0],array[1],array[2]);
1000 double length=Surface(parray)-depth_temp;
1002 double rxposx=array[0];
1003 double rxposy=array[1];
1004 double rxdr=sqrt(rxposx*rxposx+rxposy*rxposy);
1005 if (Tools::dSquare(array)==0) cout <<
"Attempt of divide by zero in Earth curvature!!\n";
1006 double rxdtheta=asin(rxdr/sqrt(Tools::dSquare(array)));
1007 double rxdphi=atan2(rxposy,rxposx);
1009 array[0]=length*sin(rxdtheta)*cos(rxdphi);
1010 array[1]=length*sin(rxdtheta)*sin(rxdphi);
1011 array[2]=length*cos(rxdtheta);
1016 double p = posnu.Mag();
1017 double costheta = (nnu*posnu) / p;
1018 double sintheta = sqrt(1-costheta*costheta);
1020 double lon = posnu.
Lon();
1021 double lat = posnu.
Lat();
1025 double R = Surface(lon,lat);
1026 double delta = R - p;
1030 a=p*costheta+sqrt(R*R*costheta*costheta+2*delta*R*sintheta*sintheta);
1032 cout <<
"Negative chord length: " << a <<
"\n";
1035 else if (delta<=-0.001) {
1037 cout <<
"lon, lat from WhereDoesItEnter is " << lon <<
" " << lat <<
"\n";
1038 cout <<
"geoid, surface, p, surface-p are " << Geoid(lat) <<
" " << Surface(lon,lat) <<
" " << p <<
" , "<<(Surface(lon,lat)-p)<<
"\n";
1055 delta = r_in.Mag() - Surface( r_in );
1057 while ( fabs(delta) >= 0.1 ) {
1058 r_in = r_in + (delta * nnu);
1059 delta = r_in.Mag() - Surface( r_in );
1063 r_in = Surface( r_in ) * r_in.Unit();
1064 delta = r_in.Mag() - Surface( r_in );
1110 double POLAR_RADIUS = 6356752.31425 + extra_height;
1111 double EQUATORIAL_RADIUS = 6378137.0 + extra_height;
1112 double EQ2 = EQUATORIAL_RADIUS*EQUATORIAL_RADIUS;
1113 double PO2 = POLAR_RADIUS*POLAR_RADIUS;
1114 double RAT = EQ2/PO2;
1119 double a = p0.X()*p0.X() + p0.Y()*p0.Y() + p0.Z()*p0.Z() *RAT;
1122 double b = 2 * ( p0.X()*x0.X() + x0.Y()*p0.Y() + x0.Z()*p0.Z() *RAT) ;
1125 double c = -EQ2 + x0.X()*x0.X() + x0.Y()*x0.Y() + x0.Z()*x0.Z() *RAT;
1128 double discr = b*b-4*a*c;
1136 discr = sqrt(discr);
1138 double d0= (-b + discr)/(2*a);
1139 double d1= (-b - discr)/(2*a);
1149 x0.X() + d0 *p0.X(),
1150 x0.Y() + d0 *p0.Y(),
1151 x0.Z() + d0 *p0.Z() );
1157 x0.X() + d1 *p0.X(),
1158 x0.Y() + d1 *p0.Y(),
1159 x0.Z() + d1 *p0.Z() );
1163 return discr == 0 ? 1 : 2;
const char * ICEMC_SRC_DIR()
Reads in and stores input settings for the run.
double Lat() const
Returns latitude, where the +z direction is at 0 latitude.
This class is a 3-vector that represents a position on the Earth's surface.
int GeoidIntersection(Vector x0, Vector p0, Position *int1, Position *int2, double extra_height=5500, double *ds=0) const
This class represents a three-vector. Operators are overloaded to provide for the familiar operations...
double Distance(const Position &second) const
Returns chord distance (direct distance between two vectors)
double Lon() const
Returns longitude.