00001
00002
00003
00004
00005
00006
00007 #include "BaseApp.h"
00008 #include "SlabWorld.h"
00009 #include "SmplStat.h"
00010 #include "gismo/Units.h"
00011 #include "geometry/CoordTransform.h"
00012 #include "gismo/EGSInteractor.h"
00013 #include "gismo/GheishaInteractor.h"
00014
00015
00016 #include <iomanip>
00017 SampleStatistic thetaSquared;
00018 SampleStatistic energyLoss;
00019 SampleStatistic multiplicity;
00020 SampleStatistic energyDeposited;
00021
00022 unsigned long numberOfEvents=1000;
00023 unsigned long number=0;
00024 float pBeam = 2.0;
00025 float thickness = 1.0;
00026 const char* materialName = "Al";
00027 const char* particleName = "mu+";
00028 float incidentAngle=0.;
00029
00030 Vector pinit(0,0,pBeam);
00031
00032 float sigmaMS;
00033 float expectedEloss;
00034 float initialEnergy;
00035
00036
00037 using namespace std;
00038
00039 template<class T> inline T sqr(T x){return x*x;}
00040
00041 void WARNING(const char * text){cerr << "WARNING: " << text << '\n';}
00042 void FATAL(const char * text){
00043 cerr << "FATAL error: " <<text << '\n';
00044 cerr << "type help for instructions\n";
00045 exit(-1);}
00046
00047 const char* help=
00048 "Help for the gismo test program mscat:\n\n"
00049 " mscat [[[[particleName] materialName] eventCount] pBeam ] materialsize]\n\n"
00050 "where:\n"
00051 " particleName [mu+] is the name of a particle to interact:\n"
00052 " (\"decay list\" for a list)\n"
00053 " materialName [Al] the name of a PEGS4 material file, e.g. Al.mat\n"
00054 " eventCount [1] number of events to generate\n"
00055 " pBeam [2.0 GeV] the beam momentum\n"
00056 " thickness [1.0 cm] the amount of material\n";
00057
00058
00059
00060
00061
00062 class Spectrometer : public Detector
00063 {
00064 public:
00065 Spectrometer():Detector(){}
00066 void score(MCParticle*);
00067 void clear(){mult=0; m_edep=0;}
00068 void generateResponse(){};
00069 private:
00070 int mult;
00071 float m_edep;
00072 };
00073
00074 void Spectrometer::score( MCParticle *p)
00075 {
00076 if( p->charge()==0 || p->pTot()==0 ) return;
00077 multiplicity += ++mult;
00078 float deltaE = initialEnergy - p->e();
00079 m_edep += deltaE;
00080
00081 if( mult > 1 ) return;
00082
00083 double theta = pinit.dot(*p)/p->momentum().mag()/pBeam;
00084 theta = theta>=1? 0 : acos(theta);
00085 thetaSquared += sqr(theta);
00086
00087 energyLoss += deltaE;
00088
00089 }
00090
00091
00092
00093 class Calorimeter: public Detector
00094 {
00095 public:
00096 Calorimeter():Detector(){}
00097 void score(MCParticle* p){
00098 m_e += p->energyLoss();
00099 ++m_n;
00100 }
00101 void clear(){ m_n=0; m_e=0;}
00102 void generateResponse(){
00103 energyDeposited += m_e;
00104 }
00105 private:
00106 float m_e;
00107 int m_n;
00108 };
00109
00110
00111
00112
00113
00114 class TestApp : public BaseApp
00115 {
00116 public:
00117 void endEvent()
00118 { if( eventNumber%10==0 )
00119
00120 number++;
00121
00122 }
00123 void init(ostream& =cout);
00124 void last(ostream& = cout);
00125 };
00126
00127 void TestApp::init(ostream& cout)
00128 {
00129
00130
00131 pinit.rotateY(incidentAngle);
00132 setBeam(particleName, pinit, Point(0,0,-1));
00133
00134
00135 SlabWorld* w = new SlabWorld;
00136 setWorld(w);
00137 w->addSlab(thickness,materialName,new Calorimeter );
00138 w->addSlab(0.1f,"vacuum",new Spectrometer() );
00139
00140
00141
00142 GParticle p(particleName);
00143 p.setMomentum(pinit);
00144 initialEnergy = p.e();
00145 double ptotal = p.pTot();
00146 double beta = ptotal/initialEnergy;
00147 double eta = ptotal/p.mass();
00148
00149 Material& mat = *Material::hatch(materialName);
00150 double X0 = mat.radiationLength();
00151 double step = thickness/p.cosTheta();
00152 double x = step/X0;
00153
00154 expectedEloss = step * mat.dedx(beta,eta) * sqr(p.charge());
00155
00156 sigmaMS = Units::fromMeV(13.6f)
00157 * sqr(p.charge()) * sqrt(x) * (1.+ 0.038*log(x))
00158 /(beta* ptotal);
00159
00160 cout << "\n\tSimple gismo scattering test";
00161 cout << "\n\t============================\n";
00162 static int wd=25;
00163 cout << std::setw(wd) << "particle: " << particleName
00164 << '\n' << std::setw(wd) << "momentum: " << ptotal << " GeV"
00165 << '\n' << std::setw(wd) << "KE: " << (p.e()-p.mass()) << " GeV"
00166 << '\n' << std::setw(wd) << "incident angle: " << incidentAngle
00167 << '\n' << std::setw(wd) << "material: " << materialName
00168 << '\n' << std::setw(wd) << "thickness: " <<thickness << " cm"
00169 << '\n' << std::setw(wd) << "Radiation length: " << X0
00170 << '\n' << std::setw(wd) << "expected m.s. sigma: " << sigmaMS
00171 << '\n' << std::setw(wd) << "expected E loss: " << expectedEloss*1e3 <<" MeV"
00172
00173
00174 << ", which is "<< expectedEloss*1e3/step/mat.density() <<" MeV/g\n";
00175 cout << "\nbegin run for "<< numberOfEvents<<" events\n";
00176 }
00177 void TestApp::last(ostream& cout)
00178 {
00179 const int width=45;
00180 if( thetaSquared.samples()>0)
00181 {
00182 cout << std::setw(width) << "Mean square angular deviation / expected: "
00183 << thetaSquared.mean() / (2*sqr(sigmaMS))
00184 << " +/- " << thetaSquared.stdDev()
00185 /sqrt((double)thetaSquared.samples())
00186 /(2*sqr(sigmaMS))
00187 << '\n';
00188 cout << std::setw(width) <<"Average energy loss / expected: "
00189 << energyLoss.mean() / expectedEloss
00190 << " +/- " << energyLoss.stdDev()
00191 / sqrt((double)energyLoss.samples())/expectedEloss
00192 << '\n';
00193 cout << std::setw(width) << "energy loss fraction fluctuation: "
00194 << energyLoss.stdDev()/energyLoss.mean() <<'\n';
00195 }
00196 cout << std::setw(width) <<"Average Multiplicity emerging: " << multiplicity.mean() << '\n';
00197 cout << std::setw(width) <<"Mean Energy Deposited: " << energyDeposited.mean()*1e3
00198 << " MeV, or "<< energyDeposited.mean()*1e6/thickness*1e-4 << " keV/um"<<'\n';
00199 cout << std::setw(width) << "Energy dep. fractional rms: "
00200 << energyDeposited.stdDev()/energyDeposited.mean() <<'\n';
00201 }
00202
00203
00204 int main(int argc, char* argv[])
00205 {
00206
00207 if( argc>1 ){
00208 particleName=argv[1];
00209 if( strcmp(particleName, "help")==0 ) {
00210 cout << help;
00211 return 0;
00212 }
00213 }
00214 if( argc>2 ) materialName=argv[2];
00215 if( argc>3 ) numberOfEvents = atoi(argv[3]);
00216 if( argc>4 ) {pBeam = atof(argv[4]); pinit=Vector(0,0,pBeam);}
00217 if( argc>5 ) {thickness = atof(argv[5]);}
00218
00219 TestApp tester;
00220
00221 tester.addInteractor(new EGSInteractor("electromagnetic") );
00222 tester.addInteractor(new GheishaInteractor("hadronic"));
00223
00224 tester.init();
00225 tester.run(numberOfEvents);
00226 tester.last();
00227 return 0;
00228 }
00229
00230
00231