00001
00002
00003
00004 #include "AlbedoPSpectrum.h"
00005
00006 #include <cmath>
00007 #include <algorithm>
00008 #include <functional>
00009 #include "CLHEP/Random/Random.h"
00010 #include "GPS.h"
00011 #include "Geomag.h"
00012 #include "SpectrumFactory.h"
00013
00014 static SpectrumFactory<AlbedoPSpectrum> factory;
00015 const ISpectrumFactory& AlbedoPSpectrumFactory = factory;
00016
00017
00019 void AlbedoPSpectrum::init(const std::vector<float>& params) {
00020
00021 float lat = params.size()>0? params[0]: 0.0f;
00022 float lon = params.size()>1? params[1]: 0.0f;
00023 setPosition(lat, lon);
00024
00025 m_particle_name = "p";
00026
00027
00028 m_observer.setAdapter( new ActionAdapter<AlbedoPSpectrum>
00029 (this, &AlbedoPSpectrum::askGPS) );
00030
00031 GPS::instance()->notification().attach( &m_observer );
00032
00033 }
00034
00035
00036
00037
00039 AlbedoPSpectrum::AlbedoPSpectrum(const std::string& paramstring) {
00040 std::vector<float> params;
00041
00042 parseParamList(paramstring,params);
00043
00044 init(params);
00045 }
00046
00047
00048
00049
00051 std::string AlbedoPSpectrum::title() const {
00052 return "AlbedoPSpectrum";
00053 }
00054
00055
00056
00058 const char * AlbedoPSpectrum::particleName() const {
00059 return m_particle_name.c_str();
00060 }
00061
00062
00063
00065 void AlbedoPSpectrum::setParticleName(std::string name)
00066 {
00067 m_particle_name = name;
00068 }
00069
00070
00071
00073 double AlbedoPSpectrum::flux(double) const {
00074 return m_flux;
00075 }
00076
00077
00078
00080 double AlbedoPSpectrum::solidAngle() const
00081 {
00082 return 4.*M_PI;
00083 }
00084
00085
00086
00090 float AlbedoPSpectrum::flux(float lat, float lon) const {
00091 double v1,v2, alf1, alf2, emin, emax, Ejoin;
00092 fitParams(lat, lon, alf1, alf2, emin, emax, v1, v2, Ejoin);
00093
00094 return 1.47 * (v1+v2);
00095 }
00096
00097
00098
00100 float AlbedoPSpectrum::flux( std::pair<double,double> coords) const {
00101 return flux(coords.first, coords.second);
00102 }
00103
00104
00105
00109 float AlbedoPSpectrum::operator() (float x) const{
00110 double v1,v2, alf1, alf2, emin, emax, Ejoin;
00111 fitParams(m_lat, m_lon, alf1, alf2, emin, emax, v1, v2, Ejoin);
00112 double split = v1/(v1+v2);
00113 if (x > split) {
00114 return pow((pow(Ejoin,1.-alf2)+((1.-x)/(1.-split))*(pow(emax,1.-alf2)
00115 -pow(Ejoin,1.-alf2))), 1./(1.-alf2));
00116 } else {
00117 return pow((pow(emin,1.-alf1)+(x/split)*(pow(Ejoin,1.-alf1)
00118 -pow(emin,1.-alf1))), 1./(1.-alf1));
00119 }
00120 }
00121
00122
00123
00125 int AlbedoPSpectrum::askGPS()
00126 {
00127 setPosition(GPS::instance()->lat(), GPS::instance()->lon());
00128 return 0;
00129 }
00130
00131
00133
00134 m_lat = lat;
00135 m_lon = lon;
00136 m_flux = flux(lat, lon);
00137 }
00138
00139
00141
00142 AlbedoPSpectrum::setPosition(coords.first, coords.second);
00143 }
00144
00145
00147
00148 {
00149 return flux(GPS::instance()->lat(), GPS::instance()->lon());
00150 }
00151
00152
00155
00156 {
00157
00158
00159 float coszenith, earthazi,dens,v;
00160 const int try_max = 1000;
00161 static int max_tried = 0;
00162 int trial = 0;
00163 earthazi = 2. * M_PI * HepRandom::getTheGenerator()->flat();
00164 do {
00165 coszenith = 2. * HepRandom::getTheGenerator()->flat() - 1.;
00166 dens = 1. + 0.6 * sqrt(1.-coszenith*coszenith);
00167 v = 1.6 * HepRandom::getTheGenerator()->flat();
00168 } while (v > dens && trial++ < try_max);
00169
00170 max_tried = std::max(trial, max_tried);
00171
00172 return std::make_pair<float,float>(coszenith, earthazi);
00173 }
00174
00175
00188 void AlbedoPSpectrum::fitParams(const double lat, const double lon,
00189 double& alf1, double& alf2, double& emin, double& emax,
00190 double& v1, double &v2, double& Ejoin) const
00191 {
00192 double theta = abs(Geomag::geolat(lat,lon)) * M_PI / 180.;
00193 double e1 = .2;
00194 double e2 = 1.;
00195 emin = .01;
00196 emax = 10.;
00197
00198 double a1 = 0.142 + theta * (-.4809 + theta * .5517);
00199 double a2 = .0499 + theta * (-.3239 + theta * (.8077 + theta * (-.8800 +
00200 theta * .3607)));
00201 alf1 = .4913 + theta * (2.017 + theta * (-.6941 - 1.49 * theta));
00202 alf2 = 2.85 - .875 * theta;
00203 Ejoin = pow(a1*pow(e1,alf1) / (a2*pow(e2,alf2)), 1./(alf1-alf2));
00204 v1 = 1000.*a1*pow(e1,alf1)*(pow(Ejoin,1.-alf1)-pow(emin,1.-alf1))
00205 /(1.-alf1);
00206 v2 = 1000.*a2*pow(e2,alf2)*(pow(emax,1.-alf2)-pow(Ejoin,1.-alf2))
00207 /(1.-alf2);
00208 }