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(
bool unbiased_selection,
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 (unbiased_selection)
441 probability_tmp*=1-exp(-1.*(distance_in_ice/L_ice));
446 double ddensity=Signal::RHOAIR;
449 if (where*nchord>0.) {
450 cout <<
"This one's trouble. Neutrino exit point looks more like an entrance point. Event is " << inu <<
"\n";
451 cout <<
"where is " << where[0] <<
" " << where[1] <<
" " << where[2] <<
"\n";
452 cout <<
"nchord is " << nchord[0] <<
" " << nchord[1] <<
" " << nchord[2] <<
"\n";
453 cout <<
"dot product is " << where*nchord/sqrt(where*where) <<
"\n";
454 cout <<
"posnu is " << posnu[0] <<
" " << posnu[1] <<
" " << posnu[2] <<
"\n";
455 cout <<
"Length of chord is : "<<chord<<endl;
458 altitude=where.Mag()-Geoid(lat);
460 if(altitude>surface_elevation+0.1)
461 cout <<
"neutrino entrance point is above the surface. Event is " << inu <<
"\n";
464 while(altitude>MIN_ALTITUDE_CRUST && x<posnu.
Distance(earth_in)) {
468 ddensity = this->GetDensity(altitude,where,crust_entered,&inice);
470 L=len_int_kgm2/ddensity;
471 if (!inice || include_ice_absorption)
473 weight1_tmp*=exp(-step/L);
474 total_kgm2+=ddensity*step;
476 if (exp(-step/L) > 1)
477 cout<<
"Oops! len_int_kgm2, ddensity, factor : "<<len_int_kgm2<<
" , "<<ddensity<<
" , "<<exp(-step/L)<<endl;
480 where += step*nchord;
486 altitude=where.Mag()-Geoid(lat);
487 surface_elevation = this->SurfaceAboveGeoid(lon,lat);
493 if (x>posnu.
Distance(earth_in) && weightabsorption) {
494 probability_tmp*=weight1_tmp;
498 if (altitude<=MIN_ALTITUDE_CRUST) {
503 sinth=sin(where.Angle(nchord));
504 costh=sqrt(1-sinth*sinth);
506 if (sinth>sqrt(radii[0]/radii[1])) {
510 L=len_int_kgm2/densities[1];
511 halfchord=sqrt(radii[1])*costh;
513 weight1_tmp *= exp(-2*halfchord/L);
514 total_kgm2+= 2*halfchord*densities[1];
515 where += (2*halfchord)*nchord;
524 L=len_int_kgm2/densities[1];
527 halfchord=sqrt(radii[0]-radii[1]*sinth*sinth);
528 distance=sqrt(radii[1])*costh-halfchord;
529 weight1_tmp*=exp(-distance/L);
530 total_kgm2 += 2*distance*densities[1];
532 L=len_int_kgm2/densities[0];
533 weight1_tmp*=exp(-2*halfchord/L);
534 total_kgm2 += 2*halfchord*densities[0];
536 L=len_int_kgm2/densities[1];
537 weight1_tmp*=exp(-distance/L);
538 if (exp(-distance/L) > 1)
539 cout<<
"Oops2! len_int_kgm2, ddensity, distance, factor : "<<len_int_kgm2<<
" , "<<ddensity<<
" , "<<distance<<
" , "<<exp(-distance/L)<<endl;
540 where += (2*distance+2*halfchord)*nchord;
549 altitude=where.Mag()-Geoid(lat);
550 surface_elevation = this->SurfaceAboveGeoid(lon,lat);
554 double distance_remaining=where.
Distance(posnu);
557 while(x<=distance_remaining) {
560 ddensity=this->GetDensity(altitude,where,crust_entered,&inice);
562 L=len_int_kgm2/ddensity;
564 if (!inice || include_ice_absorption)
566 weight1_tmp*=exp(-step/L);
567 total_kgm2 += step*ddensity;
570 if (exp(-step/L) > 1)
571 cout<<
"Oops3! len_int_kgm2, ddensity, step, factor : "<<len_int_kgm2<<
" , "<<ddensity<<
" , "<<step<<
" , "<<exp(-step/L)<<endl;
576 where += step*nchord;
582 altitude=where.Mag()-Geoid(lat);
583 surface_elevation = this->SurfaceAboveGeoid(lon,lat);
590 probability_tmp*=weight1_tmp;
593 if (weightabsorption==0) {
594 if (getRNG(RNG_ABSORB)->Rndm()>weight1_tmp) {
608 cout <<
"made it this far.\n";
615 Vector n_surf = r_out.Unit();
619 double theta=r_out.Theta();
622 GetILonILat(r_out,ilon,ilat);
624 int ilon_previous=ilon-1;
626 ilon_previous=NLON-1;
628 int ilon_next=ilon+1;
632 double r=(geoid[ilat]+surfacer[ilon][ilat])*sin(theta);
634 double slope_phi=(surfacer[ilon_next][ilat]-surfacer[ilon_previous][ilat])/(r*2*phistep);
636 int ilat_previous=ilat-1;
640 int ilat_next=ilat+1;
644 double slope_costheta=(surfacer[ilon][ilat_next]-surfacer[ilon][ilat_previous])/((geoid[ilat]+surfacer[ilon][ilat])*2*thetastep);
647 double angle=atan(slope_costheta);
649 n_surf = n_surf.RotateY(angle);
652 angle=atan(slope_phi);
654 n_surf = n_surf.RotateZ(angle);
660 double EarthModel::SmearPhi(
int ilon,
double rand) {
663 double phi=((double)(360.*3./4.-((
double)ilon+rand)*360/180))*RADDEG;
664 if (phi<0 && phi>-1*PI/2)
671 double EarthModel::SmearTheta(
int ilat,
double rand) {
676 double theta1=dGetTheta(ilat)-PI/(double)NLAT/2.;
677 double theta2=dGetTheta(ilat+1)-PI/(double)NLAT/2.;
679 double costheta1=cos(theta1);
680 double costheta2=cos(theta2);
684 double costheta=rand*(costheta2-costheta1)+costheta1;
686 double theta=acos(costheta);
691 void EarthModel::ReadCrust(
string test) {
696 fstream infile(test.c_str(),ios::in);
713 while(!infile.eof()) {
714 getline(infile,thisline,
'\n');
716 int loc=thisline.find(
"type, latitude, longitude,");
718 if (loc!=(
int)(string::npos)) {
720 beginindex=thisline.find_first_not_of(
" ",57);
722 endindex=thisline.find_first_of(
" ",61);
724 slat=thisline.substr(beginindex,endindex-beginindex);
725 dlat=(double)atof(slat.c_str());
727 beginindex=thisline.find_first_not_of(
" ",68);
728 endindex=thisline.find_first_of(
" ",72);
730 slon=thisline.substr(beginindex,endindex-beginindex);
731 dlon=(double)atof(slon.c_str());
734 indexlon=(int)((dlon+180)/2);
735 indexlat=(int)((90+dlat)/2);
737 beginindex=thisline.find_first_not_of(
" ",78);
738 endindex=thisline.find_first_of(
" ",83);
740 selev=thisline.substr(beginindex,endindex-beginindex);
741 elevationarray[indexlon][indexlat]=(double)atof(selev.c_str());
745 for (
int i=0;i<4;i++) {
746 getline(infile,thisline,
'\n');
749 for (
int i=0;i<7;i++) {
750 getline(infile,thisline,
'\n');
752 endindex=thisline.length()-1;
753 beginindex=thisline.find_last_of(
"0123456789",1000);
754 layertype=thisline.substr(beginindex+3,endindex-beginindex);
757 beginindex=thisline.find_first_not_of(
" ",0);
758 endindex=thisline.find_first_of(
" ",beginindex);
760 sdepth=thisline.substr(beginindex,endindex-beginindex-1);
764 if (layertype.substr(0,5)==
"water")
765 waterthkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
766 if (layertype.substr(0,3)==
"ice")
767 icethkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
768 if (layertype.substr(0,8)==
"soft sed")
769 softsedthkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
770 if (layertype.substr(0,8)==
"hard sed")
771 hardsedthkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
772 if (layertype.substr(0,11)==
"upper crust")
773 uppercrustthkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
774 if (layertype.substr(0,12)==
"middle crust")
775 middlecrustthkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
776 if (layertype.substr(0,11)==
"lower crust")
777 lowercrustthkarray[indexlon][indexlat]=(
double)atof(sdepth.c_str());
783 if (indexlat==5 && (indexlon<=5 || indexlon>=176))
784 icethkarray[indexlon][indexlat]=0.5;
786 beginindex=thisline.find_first_not_of(
" ",endindex);
787 endindex=thisline.find_first_of(
" ",beginindex);
790 beginindex=thisline.find_first_not_of(
" ",endindex);
791 endindex=thisline.find_first_of(
" ",beginindex);
793 beginindex=thisline.find_first_not_of(
" ",endindex);
794 endindex=thisline.find_first_of(
" ",beginindex);
797 sdensity=thisline.substr(beginindex,endindex-beginindex);
799 double ddensity=(double)atof(sdensity.c_str());
803 if (layertype.substr(0,5)==
"water")
804 waterdensityarray[indexlon][indexlat]=ddensity;
805 if (layertype.substr(0,3)==
"ice")
806 icedensityarray[indexlon][indexlat]=ddensity;
807 if (layertype.substr(0,8)==
"soft sed")
808 softseddensityarray[indexlon][indexlat]=ddensity;
809 if (layertype.substr(0,8)==
"hard sed")
810 hardseddensityarray[indexlon][indexlat]=ddensity;
811 if (layertype.substr(0,11)==
"upper crust")
812 uppercrustdensityarray[indexlon][indexlat]=ddensity;
813 if (layertype.substr(0,12)==
"middle crust")
814 middlecrustdensityarray[indexlon][indexlat]=ddensity;
815 if (layertype.substr(0,11)==
"lower crust")
816 lowercrustdensityarray[indexlon][indexlat]=ddensity;
820 softsedthkarray[indexlon][indexlat]=40.;
821 hardsedthkarray[indexlon][indexlat]=0;
822 uppercrustthkarray[indexlon][indexlat]=0;
823 middlecrustthkarray[indexlon][indexlat]=0;
824 lowercrustthkarray[indexlon][indexlat]=0;
825 crustthkarray[indexlon][indexlat]=0;
826 softseddensityarray[indexlon][indexlat]=2.9;
828 if (CONSTANTICETHICKNESS) {
829 icethkarray[indexlon][indexlat]=3.;
830 waterthkarray[indexlon][indexlat]=0.;
834 crustthkarray[indexlon][indexlat]=softsedthkarray[indexlon][indexlat]+
835 hardsedthkarray[indexlon][indexlat]+
836 uppercrustthkarray[indexlon][indexlat]+
837 middlecrustthkarray[indexlon][indexlat]+
838 lowercrustthkarray[indexlon][indexlat];
840 if (indexlon==179 && indexlat==0)
844 for (
int i=0;i<NLON;i++) {
845 for (
int j=0;j<NLAT;j++) {
848 elevationarray[i][j]=icethkarray[i][j]*1000;
850 if (waterthkarray[i][j] != 0)
851 surfacer[i][j]=elevationarray[i][j]+waterthkarray[i][j]*1000+icethkarray[i][j]*1000;
853 surfacer[i][j]=elevationarray[i][j];
855 if (fabs(surfacer[i][j])<1.E-10)
860 waterr[i][j]=surfacer[i][j]-(icethkarray[i][j]+waterthkarray[i][j])*1000;
861 if ((
double)fabs(waterr[i][j])<1.E-10)
863 icer[i][j]=waterr[i][j]+
864 waterthkarray[i][j]*1000;
865 softsedr[i][j]=waterr[i][j]-
866 softsedthkarray[i][j]*1000;
867 hardsedr[i][j]=waterr[i][j]-
868 (softsedthkarray[i][j]+
869 hardsedthkarray[i][j])*1000;
870 uppercrustr[i][j]=waterr[i][j]-
871 (softsedthkarray[i][j]+
872 hardsedthkarray[i][j]+
873 uppercrustthkarray[i][j])*1000;
874 middlecrustr[i][j]=waterr[i][j]-
875 (softsedthkarray[i][j]+
876 hardsedthkarray[i][j]+
877 uppercrustthkarray[i][j]+
878 middlecrustthkarray[i][j])*1000;
879 lowercrustr[i][j]=waterr[i][j]-
880 (softsedthkarray[i][j]+
881 hardsedthkarray[i][j]+
882 uppercrustthkarray[i][j]+
883 middlecrustthkarray[i][j]+
884 lowercrustthkarray[i][j])*1000;
893 max_icevol_perbin=0.;
894 max_icethk_perbin=0.;
895 for (
int j=0;j<ILAT_COASTLINE;j++) {
896 for (
int i=0;i<NLON;i++) {
897 volume+=icethkarray[i][j]*1000.*area[j];
898 if (icethkarray[i][j]>0)
900 if (icethkarray[i][j]*area[j]>max_icevol_perbin)
901 max_icevol_perbin=icethkarray[i][j]*area[j];
902 if (icethkarray[i][j]>max_icethk_perbin)
903 max_icethk_perbin=icethkarray[i][j];
914 average_iceth+=(surfacer[i][j]-icer[i][j])*area[j];
918 average_iceth=average_iceth/sumarea;
920 cout <<
"Total ice volume=" << volume << endl;
924 MIN_ALTITUDE_CRUST=1.E6;
926 for (
int i=0;i<NLON;i++) {
927 for (
int j=0;j<NLAT;j++) {
928 if (elevationarray[i][j]-(crustthkarray[i][j])*1000<MIN_ALTITUDE_CRUST) {
929 if (waterthkarray[i][j]==0)
930 MIN_ALTITUDE_CRUST=elevationarray[i][j]-(crustthkarray[i][j]+icethkarray[i][j])*1000;
932 MIN_ALTITUDE_CRUST=elevationarray[i][j]-crustthkarray[i][j]*1000;
940 radii[1]=(Geoid(0.)+MIN_ALTITUDE_CRUST)*(Geoid(0.)+MIN_ALTITUDE_CRUST);
945 Vector EarthModel::PickPosnuForaLonLat(
double lon,
double lat,
double theta,
double phi) {
948 double surface_above_geoid = this->SurfaceAboveGeoid(lon,lat);
949 double local_ice_thickness = this->IceThickness(lon,lat);
951 double rnd3=getRNG(RNG_POSNU)->Rndm();
955 double elevation = surface_above_geoid - rnd3*local_ice_thickness;
961 if (elevation > surface_above_geoid || elevation < (surface_above_geoid - local_ice_thickness))
962 cout<<
"elevation > surface_above_geoid || elevation < (surface_above_geoid - local_ice_thickness)\n";
964 Vector posnu((elevation+this->Geoid(lat))*sin(theta)*cos(phi),(elevation+this->Geoid(lat))*sin(theta)*sin(phi),(elevation+this->Geoid(lat))*cos(theta));
966 if (((this->Geoid(lat) + surface_above_geoid)) - posnu.Mag() < 0) {
974 double EarthModel::dGetTheta(
int ilat) {
975 return RADDEG*ilat*MAXTHETA/NLAT;
978 double EarthModel::dGetPhi(
int ilon) {
982 return (
double)(-1*((double)ilon+0.5)+(double)NLON)*2*PI/(double)NLON-PI/2;
985 void EarthModel::GetILonILat(
const Position &p,
int& ilon,
int& ilat) {
987 double phi_deg=p.Phi()*DEGRAD;
993 ilon=(int)((360.*3./4.-phi_deg)*180./360.);
995 ilat=(int)((p.Theta()*DEGRAD)/2.);
998 void EarthModel::EarthCurvature(
double *array,
double depth_temp) {
1001 parray.SetXYZ(array[0],array[1],array[2]);
1004 double length=Surface(parray)-depth_temp;
1006 double rxposx=array[0];
1007 double rxposy=array[1];
1008 double rxdr=sqrt(rxposx*rxposx+rxposy*rxposy);
1009 if (Tools::dSquare(array)==0) cout <<
"Attempt of divide by zero in Earth curvature!!\n";
1010 double rxdtheta=asin(rxdr/sqrt(Tools::dSquare(array)));
1011 double rxdphi=atan2(rxposy,rxposx);
1013 array[0]=length*sin(rxdtheta)*cos(rxdphi);
1014 array[1]=length*sin(rxdtheta)*sin(rxdphi);
1015 array[2]=length*cos(rxdtheta);
1020 double p = posnu.Mag();
1021 double costheta = (nnu*posnu) / p;
1022 double sintheta = sqrt(1-costheta*costheta);
1024 double lon = posnu.
Lon();
1025 double lat = posnu.
Lat();
1029 double R = Surface(lon,lat);
1030 double delta = R - p;
1034 a=p*costheta+sqrt(R*R*costheta*costheta+2*delta*R*sintheta*sintheta);
1036 cout <<
"Negative chord length: " << a <<
"\n";
1039 else if (delta<=-0.001) {
1041 cout <<
"lon, lat from WhereDoesItEnter is " << lon <<
" " << lat <<
"\n";
1042 cout <<
"geoid, surface, p, surface-p are " << Geoid(lat) <<
" " << Surface(lon,lat) <<
" " << p <<
" , "<<(Surface(lon,lat)-p)<<
"\n";
1059 delta = r_in.Mag() - Surface( r_in );
1061 while ( fabs(delta) >= 0.1 ) {
1062 r_in = r_in + (delta * nnu);
1063 delta = r_in.Mag() - Surface( r_in );
1067 r_in = Surface( r_in ) * r_in.Unit();
1068 delta = r_in.Mag() - Surface( r_in );
1114 double POLAR_RADIUS = 6356752.31425 + extra_height;
1115 double EQUATORIAL_RADIUS = 6378137.0 + extra_height;
1116 double EQ2 = EQUATORIAL_RADIUS*EQUATORIAL_RADIUS;
1117 double PO2 = POLAR_RADIUS*POLAR_RADIUS;
1118 double RAT = EQ2/PO2;
1123 double a = p0.X()*p0.X() + p0.Y()*p0.Y() + p0.Z()*p0.Z() *RAT;
1126 double b = 2 * ( p0.X()*x0.X() + x0.Y()*p0.Y() + x0.Z()*p0.Z() *RAT) ;
1129 double c = -EQ2 + x0.X()*x0.X() + x0.Y()*x0.Y() + x0.Z()*x0.Z() *RAT;
1132 double discr = b*b-4*a*c;
1140 discr = sqrt(discr);
1142 double d0= (-b + discr)/(2*a);
1143 double d1= (-b - discr)/(2*a);
1153 x0.X() + d0 *p0.X(),
1154 x0.Y() + d0 *p0.Y(),
1155 x0.Z() + d0 *p0.Z() );
1161 x0.X() + d1 *p0.X(),
1162 x0.Y() + d1 *p0.Y(),
1163 x0.Z() + d1 *p0.Z() );
1167 return discr == 0 ? 1 : 2;
double Distance(const Position &second) const
Returns chord distance (direct distance between two vectors)
const char * ICEMC_SRC_DIR()
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 Lon() const
Returns longitude.