Main Page   Compound List   File List   Compound Members   File Members  

ReactorDetector.cpp

Go to the documentation of this file.
00001 
00011 #include <math.h>
00012 #include <iostream.h>
00013 #include <string.h>
00014 #include "ReactorEvent.hh"
00015 #include "ReactorFortran.hh"
00016 #include "ReactorConstants.hh"
00017 #include "ReactorXC.hh"
00018 #include "ReactorDetector.hh"
00019 #include "MyTlSource.hh"
00020 //
00021 // constructor
00022 //
00023 ReactorDetector::ReactorDetector(){
00024   //
00025   // initialize PMT arrays
00026   //
00027   Xpmt = new double[0];
00028   Ypmt = new double[0];
00029   Zpmt = new double[0];
00030   PMTdata = new PMT[0];
00031   PMTpositron = new PMT[0];
00032   PMTneutron = new PMT[0];
00033   //
00034   // Set parameters
00035   //
00036   SetNominalParameters();
00037   SetPMT();
00038   //
00039   // initialize gamma arrays
00040   //
00041   Ngamma = 0;
00042   Rgamma = new double[Ngamma];
00043   Egamma = new double[Ngamma];
00044   Tgamma = new double[Ngamma];
00045   Ogamma = new char[Ngamma];
00046 
00047   Nneutron = 0;
00048   Absorber = new double[Nneutron];
00049   NeutronSteps = new double[Nneutron];
00050 
00051   pmtRadCount = 0;
00052 }
00053 //
00054 // destructor
00055 //
00056 ReactorDetector::~ReactorDetector(){
00057   delete[] Xpmt;
00058   delete[] Ypmt;
00059   delete[] Zpmt;
00060   delete[] PMTdata;
00061   delete[] PMTpositron;
00062   delete[] PMTneutron;
00063   delete[] Rgamma;
00064   delete[] Egamma;
00065   delete[] Tgamma;
00066   delete[] Ogamma;
00067   delete[] Absorber;
00068   delete[] NeutronSteps;
00069 }
00070 //
00071 // copy constructor
00072 //
00073 ReactorDetector::ReactorDetector(const ReactorDetector& Detector){
00074 
00075   R0=Detector.R0;
00076   R1=Detector.R1;
00077   R2=Detector.R2;
00078   GdConcentration=Detector.GdConcentration;
00079   refracGd=Detector.refracGd;
00080   refracSc=Detector.refracSc;
00081   mfpGd=Detector.mfpGd;
00082   mfpSc=Detector.mfpSc;
00083   MeanNeuDispl = Detector.MeanNeuDispl;
00084   FastNeutronOption = Detector.FastNeutronOption;
00085   Temperature = Detector.Temperature;
00086   tGd=Detector.tGd;
00087   tSc=Detector.tSc;
00088   GdCaptureFraction=Detector.GdCaptureFraction;
00089   GammasPerGd=Detector.GammasPerGd;
00090   attenlGd=Detector.attenlGd;
00091   attenlSc=Detector.attenlSc;
00092   PhotonsPerMeV=Detector.PhotonsPerMeV;
00093   ShortPosFrac0=Detector.ShortPosFrac0;
00094   ShortPosFrac1=Detector.ShortPosFrac1;
00095   LongPosFrac=Detector.LongPosFrac;
00096   ShortPosTime0=Detector.ShortPosTime0;
00097   ShortPosTime1=Detector.ShortPosTime1;
00098   LongPosTime=Detector.LongPosTime;
00099   PMTcoverage=Detector.PMTcoverage;
00100   PMTdiameter=Detector.PMTdiameter;
00101   PMTqe=Detector.PMTqe;
00102   ScintDecayTime=Detector.ScintDecayTime;
00103 
00104   Npmt = Detector.Npmt;
00105   Ncosbins = Detector.Ncosbins;
00106   Nphibins = Detector.Nphibins;
00107 
00108   Xpmt = new double[Npmt];
00109   Ypmt = new double[Npmt];  
00110   Zpmt = new double[Npmt];
00111 
00112   double* pold = Detector.Xpmt+Npmt;
00113   double* pnew = Xpmt+Npmt;
00114   while(pnew>Ypmt)*--pnew=*--pold;
00115 
00116   pold = Detector.Ypmt+Npmt;
00117   pnew = Ypmt+Npmt;
00118   while(pnew>Ypmt)*--pnew=*--pold;
00119 
00120   pold = Detector.Zpmt+Npmt;
00121   pnew = Zpmt+Npmt;
00122   while(pnew>Zpmt)*--pnew=*--pold;
00123 
00124   PHpositron = Detector.PHpositron;
00125   PHneutron = Detector.PHneutron;
00126 
00127   PHposReco = Detector.PHposReco;
00128   PHneuReco = Detector.PHneuReco;
00129 
00130   TimePositron = Detector.TimePositron;
00131   TimeNeutron = Detector.TimeNeutron;
00132 
00133   for(int i=0;i<3;i++){
00134     DipolePositron[i] = Detector.DipolePositron[i];
00135     DipoleNeutron[i] = Detector.DipoleNeutron[i];
00136   }
00137 
00138   for(int i=0;i<2;i++){
00139     MeanNpe[i]=Detector.MeanNpe[i];
00140     MeanAtten[i] = Detector.MeanAtten[i];
00141     MeanSfactor[i] = Detector.MeanSfactor[i];
00142   }
00143 
00144   Nneutron = Detector.Nneutron;
00145   Absorber = new double[Nneutron];
00146   pold = Detector.Absorber+Nneutron;
00147   pnew = Absorber+Nneutron;
00148   while(pnew>Absorber)*--pnew=*--pold;
00149 
00150   NeutronSteps = new double[Nneutron];
00151   pold = Detector.NeutronSteps+Nneutron;
00152   pnew = NeutronSteps+Nneutron;
00153   while(pnew>NeutronSteps)*--pnew=*--pold;
00154 
00155   Ngamma = Detector.Ngamma;
00156   Rgamma = new double[Ngamma];
00157   pold = Detector.Rgamma+3*Ngamma;
00158   pnew = Rgamma+3*Ngamma;
00159   while(pnew>Rgamma)*--pnew=*--pold;
00160 
00161   Egamma = new double[Ngamma];
00162   pold = Detector.Egamma+Ngamma;
00163   pnew = Egamma+Ngamma;
00164   while(pnew>Egamma)*--pnew=*--pold;
00165 
00166   Tgamma = new double[Ngamma];
00167   pold = Detector.Tgamma+Ngamma;
00168   pnew = Tgamma+Ngamma;
00169   while(pnew>Tgamma)*--pnew=*--pold;
00170 
00171   Ogamma = new char[Ngamma];
00172   char* rold = Detector.Ogamma+Ngamma;
00173   char* rnew = Ogamma+Ngamma;
00174   while(rnew>Ogamma)*--rnew=*--rold;
00175 
00176   PMTsize = Detector.PMTsize;
00177   PMTlen = Detector.PMTlen;
00178   PMTdata = new PMT[PMTsize];
00179   PMT* qold = Detector.PMTdata+PMTsize;
00180   PMT* qnew = PMTdata+PMTsize;
00181   while(qnew>PMTdata)*--qnew=*--qold;
00182 
00183   PMTpositron = new PMT[Npmt];
00184   qold = Detector.PMTpositron+Npmt;
00185   qnew = PMTpositron+Npmt;
00186   while(qnew>PMTpositron)*--qnew=*--qold;
00187 
00188   PMTneutron = new PMT[Npmt];
00189   qold = Detector.PMTneutron+Npmt;
00190   qnew = PMTneutron+Npmt;
00191   while(qnew>PMTneutron)*--qnew=*--qold;
00192 
00193 }    
00194 //
00195 // = operator
00196 //
00197 ReactorDetector& ReactorDetector::operator=(const ReactorDetector& rhs){
00198 
00199   if(this == &rhs)return *this;
00200 
00201   R0=rhs.R0;
00202   R1=rhs.R1;
00203   R2=rhs.R2;
00204   GdConcentration=rhs.GdConcentration;
00205   refracGd=rhs.refracGd;
00206   refracSc=rhs.refracSc;
00207   mfpGd=rhs.mfpGd;
00208   mfpSc=rhs.mfpSc;
00209   MeanNeuDispl = rhs.MeanNeuDispl;
00210   FastNeutronOption = rhs.FastNeutronOption;
00211   Temperature = rhs.Temperature;
00212   tGd=rhs.tGd;
00213   tSc=rhs.tSc;
00214   GdCaptureFraction=rhs.GdCaptureFraction;
00215   GammasPerGd=rhs.GammasPerGd;
00216   attenlGd=rhs.attenlGd;
00217   attenlSc=rhs.attenlSc;
00218   PhotonsPerMeV=rhs.PhotonsPerMeV;
00219   ShortPosFrac0=rhs.ShortPosFrac0;
00220   ShortPosFrac1=rhs.ShortPosFrac1;
00221   LongPosFrac=rhs.LongPosFrac;
00222   ShortPosTime0=rhs.ShortPosTime0;
00223   ShortPosTime1=rhs.ShortPosTime1;
00224   LongPosTime=rhs.LongPosTime;
00225   PMTcoverage=rhs.PMTcoverage;
00226   PMTdiameter=rhs.PMTdiameter;
00227   PMTqe=rhs.PMTqe;
00228   ScintDecayTime=rhs.ScintDecayTime;
00229 
00230   Npmt = rhs.Npmt;
00231   Ncosbins = rhs.Ncosbins;
00232   Nphibins = rhs.Nphibins;
00233 
00234   delete[] Xpmt;
00235   delete[] Ypmt;
00236   delete[] Zpmt;
00237 
00238   Xpmt = new double[Npmt];
00239   Ypmt = new double[Npmt];  
00240   Zpmt = new double[Npmt];
00241 
00242   double* pold = rhs.Xpmt+Npmt;
00243   double* pnew = Xpmt+Npmt;
00244   while(pnew>Ypmt)*--pnew=*--pold;
00245 
00246   pold = rhs.Ypmt+Npmt;
00247   pnew = Ypmt+Npmt;
00248   while(pnew>Ypmt)*--pnew=*--pold;
00249 
00250   pold = rhs.Zpmt+Npmt;
00251   pnew = Zpmt+Npmt;
00252   while(pnew>Zpmt)*--pnew=*--pold;
00253 
00254   PHpositron = rhs.PHpositron;
00255   PHneutron = rhs.PHneutron;
00256 
00257   PHposReco = rhs.PHposReco;
00258   PHneuReco = rhs.PHneuReco;
00259 
00260   TimePositron = rhs.TimePositron;
00261   TimeNeutron = rhs.TimeNeutron;
00262 
00263   for(int i=0;i<3;i++){
00264     DipolePositron[i] = rhs.DipolePositron[i];
00265     DipoleNeutron[i] = rhs.DipoleNeutron[i];
00266   }
00267 
00268   for (int i=0;i<2;i++){
00269     MeanNpe[i] = rhs.MeanNpe[i];
00270     MeanAtten[i] = rhs.MeanAtten[i];
00271     MeanSfactor[i] = rhs.MeanSfactor[i];
00272   }
00273 
00274   Nneutron = rhs.Nneutron;
00275   delete[] Absorber;
00276   Absorber = new double[Nneutron];
00277   pold = rhs.Absorber+Nneutron;
00278   pnew = Absorber+Nneutron;
00279   while(pnew>Absorber)*--pnew=*--pold;
00280 
00281   NeutronSteps = new double[Nneutron];
00282   delete[] NeutronSteps;
00283   pold = rhs.NeutronSteps+Nneutron;
00284   pnew = NeutronSteps+Nneutron;
00285   while(pnew>NeutronSteps)*--pnew=*--pold;
00286 
00287   Ngamma = rhs.Ngamma;
00288   delete[] Rgamma;
00289   Rgamma = new double[Ngamma];
00290   pold = rhs.Rgamma+3*Ngamma;
00291   pnew = Rgamma+3*Ngamma;
00292   while(pnew>Rgamma)*--pnew=*--pold;
00293 
00294   delete[] Egamma;
00295   Egamma = new double[Ngamma];
00296   pold = rhs.Egamma+Ngamma;
00297   pnew = Egamma+Ngamma;
00298   while(pnew>Egamma)*--pnew=*--pold;
00299 
00300   delete[] Tgamma;
00301   Tgamma = new double[Ngamma];
00302   pold = rhs.Tgamma+Ngamma;
00303   pnew = Tgamma+Ngamma;
00304   while(pnew>Tgamma)*--pnew=*--pold;
00305 
00306   delete[] Ogamma;
00307   Ogamma = new char[Ngamma];
00308   char* rold = rhs.Ogamma+Ngamma;
00309   char* rnew = Ogamma+Ngamma;
00310   while(rnew>Ogamma)*--rnew=*--rold;
00311 
00312   PMTsize = rhs.PMTsize;
00313   PMTlen = rhs.PMTlen;
00314   delete[] PMTdata;
00315   PMTdata = new PMT[PMTsize];
00316   PMT* qold = rhs.PMTdata+PMTsize;
00317   PMT* qnew = PMTdata+PMTsize;
00318   while(qnew>PMTdata)*--qnew=*--qold;
00319 
00320   delete[] PMTpositron;
00321   PMTpositron = new PMT[Npmt];
00322   qold = rhs.PMTpositron+Npmt;
00323   qnew = PMTpositron+Npmt;
00324   while(qnew>PMTpositron)*--qnew=*--qold;
00325 
00326   delete[] PMTneutron;
00327   PMTneutron = new PMT[Npmt];
00328   qold = rhs.PMTneutron+Npmt;
00329   qnew = PMTneutron+Npmt;
00330   while(qnew>PMTneutron)*--qnew=*--qold;
00331 
00332   return *this;
00333 
00334 }
00335 //
00336 // PMT sub-class  constructors,destructor,operator
00337 //    
00338 ReactorDetector::PMT::PMT(){
00339   npmt=0;
00340   for (int i=0;i<3;i++)xyz[i]=0; 
00341   TimeGen=0;
00342   TimeSmr=0;
00343   PHgen=0;
00344   PHsmr=0;
00345   PathGd=0;
00346   PathSc=0;
00347   Sfactor=0;
00348   Atten=0;
00349   Npe=0;
00350   Xpe=0;
00351   Parent='U';
00352 
00353   SubHits=0;
00354   SubHitsPtr = new PMT*[0];
00355 }
00356   
00357 ReactorDetector::PMT::~PMT(){
00358   delete[] SubHitsPtr;
00359 }
00360 
00361 ReactorDetector::PMT::PMT(const ReactorDetector::PMT& p){
00362   
00363   npmt=p.npmt; 
00364   for (int i=0;i<3;i++)xyz[i]=p.xyz[i]; 
00365   TimeGen=p.TimeGen;
00366   TimeSmr=p.TimeSmr;
00367   PHgen=p.PHgen;
00368   PHsmr=p.PHsmr;
00369   PathGd=p.PathGd;
00370   PathSc=p.PathSc;
00371   Sfactor=p.Sfactor;
00372   Atten=p.Atten;
00373   Npe=p.Npe;
00374   Xpe=p.Xpe;
00375   Parent=p.Parent;
00376   //
00377   SubHits=p.SubHits;
00378   SubHitsPtr = new PMT*[SubHits];
00379   PMT** pold = p.SubHitsPtr+SubHits;
00380   PMT** pnew = SubHitsPtr+SubHits;
00381   while(pnew>SubHitsPtr)*--pnew=*--pold;
00382 }
00383 //
00384 // PMT sub-class equal operator
00385 //    
00386 ReactorDetector::PMT& 
00387 ReactorDetector::PMT::operator=(const ReactorDetector::PMT& rhs){
00388 
00389   if(this == &rhs)return *this;
00390 
00391   npmt=rhs.npmt;
00392   for (int i=0;i<3;i++)xyz[i]=rhs.xyz[i]; 
00393   TimeGen=rhs.TimeGen;
00394   TimeSmr=rhs.TimeSmr;
00395   PHgen=rhs.PHgen;
00396   PHsmr=rhs.PHsmr;
00397   PathGd=rhs.PathGd;
00398   PathSc=rhs.PathSc;
00399   Sfactor=rhs.Sfactor;
00400   Atten=rhs.Atten;
00401   Npe=rhs.Npe;
00402   Xpe=rhs.Xpe;
00403   Parent=rhs.Parent;
00404   //
00405   SubHits=rhs.SubHits;
00406   delete[] SubHitsPtr;
00407   SubHitsPtr = new PMT*[SubHits];
00408   PMT** pold = rhs.SubHitsPtr+SubHits;
00409   PMT** pnew = SubHitsPtr+SubHits;
00410   while(pnew>SubHitsPtr)*--pnew=*--pold;
00411 
00412   return *this;
00413 }
00414 ReactorDetector::PMT 
00415 ReactorDetector::PMT::operator+(const ReactorDetector::PMT& rhs){
00416 
00417   PMT sum(*this);
00418   if(npmt!=rhs.npmt)return sum;
00419   sum.npmt = npmt;
00420 
00421   double w1=Xpe/(Xpe+rhs.Xpe);
00422   double w2=1-w1;
00423 
00424   for (int i=0;i<3;i++)sum.xyz[i]=w1*xyz[i]+w2*rhs.xyz[i]; 
00425   sum.TimeGen=w1*TimeGen+w2*rhs.TimeGen;
00426   sum.TimeSmr=w1*TimeSmr+w2*rhs.TimeSmr;
00427   sum.PHgen=w1*PHgen+w2*rhs.PHgen;
00428   sum.PHsmr=w1*PHsmr+w2*rhs.PHsmr;
00429   sum.PathGd=w1*PathGd+w2*rhs.PathGd;
00430   sum.PathSc=w1*PathSc+w2*rhs.PathSc;
00431   sum.Sfactor=w1*Sfactor+w1*rhs.Sfactor;
00432   sum.Atten=w1*Atten+w2*rhs.Atten;
00433   sum.Npe=Npe+rhs.Npe;
00434   sum.Xpe=Xpe+rhs.Xpe;
00435   if(Parent==rhs.Parent)sum.Parent=rhs.Parent;
00436   else sum.Parent='U';
00437 
00438   sum.SubHits = SubHits+rhs.SubHits;
00439   delete[] sum.SubHitsPtr;
00440   sum.SubHitsPtr = new PMT*[sum.SubHits];
00441   PMT** p = sum.SubHitsPtr+sum.SubHits;
00442   PMT** q = SubHitsPtr+SubHits;
00443   PMT** r = rhs.SubHitsPtr+rhs.SubHits;
00444   while(p>sum.SubHitsPtr+SubHits)*--p=*--r;
00445   while(p>sum.SubHitsPtr)*--p=*--q;
00446 
00447   return sum;
00448 }
00449 ReactorDetector::PMT& 
00450 ReactorDetector::PMT::operator+=(const ReactorDetector::PMT& rhs){
00451 
00452   if(npmt!=rhs.npmt)return *this;
00453 
00454   double w1=Xpe/(Xpe+rhs.Xpe);
00455   double w2=1-w1;
00456 
00457   for (int i=0;i<3;i++)xyz[i]=w1*xyz[i]+w2*rhs.xyz[i]; 
00458   TimeGen=w1*TimeGen+w2*rhs.TimeGen;
00459   TimeSmr=w1*TimeSmr+w2*rhs.TimeSmr;
00460   PHgen=w1*PHgen+w2*rhs.PHgen;
00461   PHsmr=w1*PHsmr+w2*rhs.PHsmr;
00462   PathGd=w1*PathGd+w2*rhs.PathGd;
00463   PathSc=w1*PathSc+w2*rhs.PathSc;
00464   Sfactor=w1*Sfactor+w1*rhs.Sfactor;
00465   Atten=w1*Atten+w2*rhs.Atten;
00466   Npe+=rhs.Npe;
00467   Xpe+=rhs.Xpe;
00468   if(Parent!=rhs.Parent)Parent='U';
00469   //
00470   PMT** SubHitsTmp = new PMT*[SubHits];
00471   PMT** p = SubHitsTmp+SubHits;
00472   PMT** q = SubHitsPtr+SubHits;
00473   while(p>SubHitsTmp)*--p=*--q;
00474   delete[] SubHitsPtr;
00475   SubHitsPtr = new PMT*[SubHits+rhs.SubHits];
00476   p = SubHitsPtr+SubHits+rhs.SubHits;
00477   q = SubHitsTmp+SubHits;
00478   PMT** r = rhs.SubHitsPtr+rhs.SubHits;
00479   while(p>SubHitsPtr+SubHits)*--p=*--r;
00480   while(p>SubHitsPtr)*--p=*--q;
00481   SubHits += rhs.SubHits;
00482   delete[] SubHitsTmp;
00483   //
00484   return *this;
00485 }
00486 void ReactorDetector::PMT::SetSubHitsPtr(int subhits){
00487   delete[] SubHitsPtr;
00488   SubHits = subhits;
00489   SubHitsPtr = new PMT*[subhits];
00490   return;
00491 }
00492 
00493 
00494 //
00495 // Detector simulation function
00496 //
00497 void ReactorDetector::LightsOut(ReactorEvent& Event){
00498 
00499   PMTlen=0;
00500   delete[] PMTdata;
00501   PMTdata = new PMT[PMTsize];
00502   
00503   GenerateSecondaries(Event);
00504   GenerateGammas(Event);
00505   GenerateResponse(Event);
00506 
00507   ConsolidatePMT();
00508 
00509   CalculateDipoleMoment('P');
00510   CalculateDipoleMoment('N');
00511 
00512   ImproveDipoleMoment('P');
00513   ImproveDipoleMoment('N');
00514 }
00515 //
00516 // Access to PMT data
00517 //
00518 void ReactorDetector::GetPMTdata(int npmt,double* XYZpmt,
00519                                  int& npos,double* PHpos,double* Tpos,
00520                                  int& nneu,double* PHneu,double* Tneu){
00521   
00522   *(XYZpmt+0) = *(Xpmt+npmt);
00523   *(XYZpmt+1) = *(Ypmt+npmt);
00524   *(XYZpmt+2) = *(Zpmt+npmt);
00525 
00526   npos=0;
00527   nneu=0;
00528   for(PMT* PMTptr=PMTdata;PMTptr<PMTdata+PMTlen;PMTptr++){
00529     if(npmt==(*PMTptr).npmt){
00530       if((*PMTptr).Parent=='P'){
00531         *(PHpos+npos) = (*PMTptr).PHsmr;
00532         *(Tpos+npos) = (*PMTptr).TimeSmr;
00533         npos++;
00534       }
00535       if((*PMTptr).Parent=='N'){
00536         *(PHneu+nneu) = (*PMTptr).PHsmr;
00537         *(Tneu+nneu) = (*PMTptr).TimeSmr;
00538         nneu++;
00539       }
00540     } 
00541   }
00542   return;
00543 }
00544 void ReactorDetector::GenerateSecondaries(ReactorEvent& Event){
00545 
00546   //cout << "GenerateSecondaries(Event)" << endl;
00547   //
00548   // Displace the positron vertex by its range along the positron direction.
00549   //
00550   int Npositron = Event.GetNumPositron();
00551   //cout << Npositron << " positron(s):" << endl;
00552 
00553   double Rpos[Event.Rdim*Npositron];
00554 
00555   // loop over the positrons
00556   for(int n=0;n<Npositron;n++){
00557 
00558     double kepos = Event.GetPositronKE(n);
00559     double tpos = 0.;
00560     double rangepos = 0.;
00561     PositronRange(kepos,rangepos,tpos);
00562     //
00563     double cospos = Event.GetPositronCosTheta(n);
00564     double phipos = Event.GetPositronPhi(n);
00565 
00566     double rint[3];
00567     for(int i=0;i<3;i++){
00568       rint[i] = *(Event.GetPositronVertexXYZ()+(i+n*Event.Rdim));
00569     }
00570     //
00571     double rpos[3];
00572     rpos[0]=rint[0]+rangepos*sqrt(1-cospos*cospos)*cos(phipos);
00573     rpos[1]=rint[1]+rangepos*sqrt(1-cospos*cospos)*sin(phipos);
00574     rpos[2]=rint[2]+rangepos*cospos;
00575     double rrpos = sqrt(rpos[0]*rpos[0]+rpos[1]*rpos[1]+rpos[2]*rpos[2]);
00576     //
00577     // set positron vertex in Event class
00578     //
00579     Rpos[0+n*Event.Rdim] = tpos;
00580     for(int i=1;i<4;i++)Rpos[i+n*Event.Rdim]=rpos[i-1];
00581     Rpos[4+n*Event.Rdim] = rrpos;
00582     Rpos[5+n*Event.Rdim] = rpos[2]/rrpos;
00583     Rpos[6+n*Event.Rdim] = atan2(rpos[1],rpos[0]);
00584     if(Rpos[6+n*Event.Rdim]<0)Rpos[6+n*Event.Rdim]+=2*RC.pi;
00585     Event.SetPositronVertex(n,Rpos);
00586   }
00587   //  for(int n=0;n<Event.Rdim*Npositron;n++){
00588   //    cout << " Rpos[" << n << "] " << Rpos[n] << endl;
00589   //  }
00590   // done with positrons
00591 
00592   int Nneutron = Event.GetNumNeutron();
00593   //cout << Nneutron << " neutron(s):" << endl;
00594 
00595   delete[] Absorber;
00596   delete[] NeutronSteps;
00597 
00598   Absorber = new double[Nneutron];
00599   NeutronSteps = new double[Nneutron];
00600 
00601   double Rneu[Event.Rdim*Nneutron];
00602 
00603   // loop over the neutrons
00604   for(int n=0;n<Nneutron;n++){
00605     //
00606     double rneu[3];
00607     double tneu = 0.;
00608     if(FastNeutronOption){
00609       //
00610       // Throw the neutron vertex via a simple Gaussian
00611       //
00612       float rn[3];
00613       int len=3;
00614       rnormx_(rn,len,ranlux_);
00615       //
00616       // Random for throwing neutron time
00617       //
00618       len=1;
00619       float rv[1];
00620       ranlux_(rv,len);
00621       //
00622       //  Simple scheme that is not right at boundaries
00623       //  Neglects discontinuity in mean free path;
00624       //  Time will be taken as protportional to sqrt(path)
00625       //
00626       double rint[3];
00627       for(int i=0;i<3;i++){
00628         rint[i] = *(Event.GetNeutronVertexXYZ()+(i+n*Event.Rdim));
00629       }
00630       //
00631       double rrint = sqrt(rint[0]*rint[0]+rint[1]*rint[1]+rint[2]*rint[2]);
00632       double path = 0.;
00633       if(rrint<=R0){
00634         for (int i=0;i<3;i++)rneu[i]=rint[i]+mfpGd*rn[i]/sqrt(3.);
00635         path = mfpGd*sqrt(rn[0]*rn[0]+rn[1]*rn[1]+rn[2]*rn[2]);
00636         tneu = tGd*sqrt(path/mfpGd)*log(1/rv[0]);
00637       }
00638       else if(rrint<R2){
00639         for (int i=0;i<3;i++)rneu[i]=rint[i]+mfpSc*rn[i]/sqrt(3.);
00640         path = mfpSc*sqrt(rn[0]*rn[0]+rn[1]*rn[1]+rn[2]*rn[2]);
00641         tneu = tSc*sqrt(path/mfpSc)*log(1/rv[0]);
00642       }
00643       else{
00644         for (int i=0;i<3;i++)rneu[i]=999999;
00645         tneu = 999999.;
00646       }
00647       //
00648       // Shift z displacement by mean Chooz value
00649       //
00650       rneu[2]+=MeanNeuDispl;
00651     }
00652     else{
00653       double pneu[3];
00654       for(int i=0;i<3;i++){
00655         pneu[i]=*(Event.GetNeutronPxyz()+(i+n*Event.Pdim));
00656         //cout << "pneu[" << i << "] " << pneu[i] << endl;
00657       }
00658       for(int i=0;i<3;i++){
00659         rneu[i]=*(Event.GetNeutronVertexXYZ()+(i+n*Event.Rdim));
00660         //cout << "rneu[" << i << "] " << rneu[i] << endl;
00661       }
00662       double keneu = Event.GetNeutronKE(n);
00663       NeutronSteps[n]=0.;
00664       Absorber[n]=0.;
00665       NeutronPropagator(R0,R2,keneu,Absorber[n],NeutronSteps[n],pneu,rneu,tneu);
00666       //cout << " Absorber[" << n << "] " << Absorber[n] << endl;
00667       //cout << " NeutronSteps[" << n << "] " << NeutronSteps[n] << endl;
00668     }
00669     //
00670     // set neutron vertex in Event class
00671     //
00672     Rneu[0+n*Event.Rdim] = tneu;
00673     for(int i=1;i<4;i++)Rneu[i+n*Event.Rdim]=rneu[i-1];
00674     double rrneu = sqrt(rneu[0]*rneu[0]+rneu[1]*rneu[1]+rneu[2]*rneu[2]);
00675     Rneu[4+n*Event.Rdim] = rrneu;
00676     Rneu[5+n*Event.Rdim] = rneu[2]/rrneu;
00677     Rneu[6+n*Event.Rdim] = atan2(rneu[1],rneu[0]);
00678     if(Rneu[6+n*Event.Rdim]<0)Rneu[6+n*Event.Rdim]+=2*RC.pi;
00679     Event.SetNeutronVertex(n,Rneu);
00680   }
00681   //  for(int n=0;n<Event.Rdim*Nneutron;n++){
00682   //    cout << " Rneu[" << n << "] " << Rneu[n] << endl;
00683   //  }
00684   // done with neutrons
00685 }
00686 
00687 void ReactorDetector::GenerateResponse(ReactorEvent& Event){
00688 
00689   //cout << "GenerateResponse(Event)" << endl;
00690   //
00691   PHpositron = 0;
00692   PHneutron = 0;
00693   PHposReco = 0;
00694   PHneuReco = 0;
00695   for(int i=0;i<2;i++){
00696     MeanSfactor[i] = 0;
00697     MeanAtten[i] = 0;
00698     MeanNpe[i] = 0;
00699   }
00700   //
00701   //
00702   //
00703   int pmtindex=0;
00704   double* xpmt=Xpmt;
00705   double* ypmt=Ypmt;
00706   double* zpmt=Zpmt;
00707   
00708   PMT* PMTptr = PMTdata;
00709 
00710   //cout << Ngamma << " gammas" << endl;
00711   for(int i=0;i<Ncosbins;i++){
00712     for(int j=0;j<Nphibins;j++){
00713       double rpmt[3];
00714       rpmt[0] = *xpmt++;
00715       rpmt[1] = *ypmt++;
00716       rpmt[2] = *zpmt++;
00717       //for (int l=0;l<3;l++) cout << "  rpmt[" << l << "] " << rpmt[l] << endl;
00718       double r[3];
00719       double dr[3];
00720       double tr[3];
00721       //      
00722       double sumpos[6]={0,0,0,0,0,0};
00723       double sumneu[6]={0,0,0,0,0,0};
00724       //
00725       double* rgptr=Rgamma;
00726       double* egptr=Egamma;
00727       double* tgptr=Tgamma;
00728       char* ogptr=Ogamma;
00729       //
00730       int nposgt0=0;
00731       int nneugt0=0;
00732       //
00733       for(int k=0;k<Ngamma;k++){
00734         //
00735         for (int l=0;l<3;l++)r[l]=*rgptr++;
00736         double rdotr = r[0]*r[0]+r[1]*r[1]+r[2]*r[2];
00737         //cout << i << " " << j << " " << k << "  rdotr " << rdotr << endl;
00738         //
00739         // nothing to do if r>R1: cycle through useless info
00740         //
00741         if(sqrt(rdotr)>R1){
00742           double dummy = *egptr++;
00743           dummy = *tgptr++;
00744           char sdummy = *ogptr++;
00745           continue;
00746         }
00747         //
00748         for (int l=0;l<3;l++)dr[l]=rpmt[l]-r[l];
00749         double ddr = sqrt(dr[0]*dr[0]+dr[1]*dr[1]+dr[2]*dr[2]);
00750         //cout << "  ddr " << ddr;
00751         for (int l=0;l<3;l++)tr[l]=dr[l]/ddr;
00752         double tdotr = r[0]*tr[0]+r[1]*tr[1]+r[2]*tr[2];
00753         //cout << "  tdotr " << tdotr;
00754         //
00755         // solve for intersection with inner radius
00756         //
00757         double sGd;
00758         double sSc;
00759         //
00760         // check for no intersections
00761         //
00762         double test = R0*R0+tdotr*tdotr-rdotr;
00763         bool inter = (test>=0);
00764         //
00765         // A straight line from the interaction vertex to the pmt
00766         // goes through the inner radius at least once.  In this case,
00767         // the light will see Gd-scint. and unloaded scint.
00768         //
00769         //cout << "  " << inter << endl;
00770         if(inter){
00771           double sint1 = -tdotr+sqrt(test);
00772           double sint2 = -tdotr-sqrt(test);
00773           if(sint1>0&&sint2<0){     // 1 intersection at soln 1
00774             sGd = sint1;
00775           }
00776           else if(sint2>0&&sint1<0){     // 1 intersection at soln 2
00777             sGd = sint2;
00778           }
00779           else if(sint2>0&&sint1>0){     // 2 intersections 
00780             sGd = sint1-sint2;
00781             if(sGd<0)sGd*=-1;
00782           }
00783           else{                          // no intersections towards PMT
00784             sGd = 0;
00785           }
00786           sSc = ddr-sGd;
00787         }
00788         //
00789         //  otherwise the light only goes through unloaded scintillator
00790         //
00791         else{
00792           sGd = 0;
00793           sSc = ddr;
00794         }
00795         //cout << "       sGd " << sGd << " sSc " << sSc << endl;
00796         //
00797         //  increment PH-- make atten. relative to center
00798         //
00799         double dsGd = sGd-R0;
00800         double dsSc = sSc-R2+R0;
00801         double atten0 = exp(-sGd/attenlGd-sSc/attenlSc);     
00802         double atten = exp(-dsGd/attenlGd-dsSc/attenlSc);     
00803         //
00804         // solid angle factor
00805         //
00806         double sfactor=0;
00807         for (int l=0;l<3;l++){sfactor+=tr[l]*rpmt[l]/R2;}
00808         sfactor *= R2*R2/ddr/ddr;
00809         //
00810         // photostatistics
00811         //
00812         double phgen = *egptr++;
00813         //cout << "phgen " << phgen << endl;
00814         //
00815         float xpe = (phgen*PhotonsPerMeV);
00816         xpe *= (atten0*sfactor);
00817         xpe *= (PMTcoverage/Npmt*PMTqe);
00818         //cout << "xpe " << xpe << endl;
00819         //
00820         int npe;
00821         int error;
00822         rnpssn_(xpe,npe,error);
00823         //cout << "npe " << npe << endl;
00824         //
00825         double phsmr = npe/PMTqe/PMTcoverage/PhotonsPerMeV;   
00826         //cout << "phsmr " << phsmr << endl;
00827         //        
00828         double tgen = *tgptr++;
00829         //cout << "tgen " << tgen << endl;
00830         double tsmr = refracGd*sGd/RC.c+refracSc*sSc/RC.c + tgen; 
00831         //cout << "tsmr " << tsmr << endl;
00832         //
00833         if(*ogptr++ == 'P'){
00834           nposgt0++;
00835           sumpos[0]+=phsmr;
00836           sumpos[1]+=phgen;
00837           sumpos[2]+=phgen*atten0*sfactor;
00838           sumpos[3]+=npe;
00839           sumpos[4]+=sfactor;
00840           sumpos[5]+=atten;
00841           //
00842           PHpositron+=phsmr;
00843         }
00844         else{
00845           nneugt0++;
00846           sumneu[0]+=phsmr;
00847           sumneu[1]+=phgen;
00848           sumneu[2]+=phgen*atten0*sfactor;
00849           sumneu[3]+=npe;
00850           sumneu[4]+=sfactor;
00851           sumneu[5]+=atten;
00852           //      
00853           PHneutron+=phsmr;
00854         }
00855         //        
00856         PMT PMTtmp;
00857         PMTtmp.npmt = pmtindex;
00858         for(int l=0;l<3;l++)PMTtmp.xyz[l] = rpmt[l];
00859         PMTtmp.PHgen = phgen;
00860         PMTtmp.PHsmr = phsmr;
00861         PMTtmp.PathGd = sGd;
00862         PMTtmp.PathSc = sSc;
00863         PMTtmp.Atten = atten;
00864         PMTtmp.Sfactor = sfactor;
00865         PMTtmp.TimeGen = tgen;
00866         PMTtmp.TimeSmr = tsmr;
00867         PMTtmp.Xpe = xpe;
00868         PMTtmp.Npe = npe;
00869         PMTtmp.Parent = *ogptr;
00870         
00871         if(PMTptr<PMTdata+PMTsize){
00872           *PMTptr++=PMTtmp;
00873           PMTlen++;
00874         }
00875         else{
00876           //
00877           // expand the data array first
00878           //
00879           PMTptr = ResizePMT();
00880           *PMTptr++=PMTtmp;
00881           PMTlen++;
00882         }
00883       }
00884       //cout << "PHpositron " << PHpositron << endl;
00885       //cout << "PHneutron  " << PHneutron << endl;
00886       //
00887       //  Crude estimate of reconstructed PH
00888       //  Includes poisson npe smearing and fluctuation in atten length
00889       //
00890       if(sumpos[2]>0){
00891         PHposReco+=sumpos[0]*sumpos[1]/sumpos[2];
00892         MeanNpe[0]+=sumpos[3]/Npmt;
00893         MeanSfactor[0]+=sumpos[4]/Npmt/nposgt0;
00894         MeanAtten[0]+=sumpos[5]/Npmt/nposgt0;
00895       }
00896       if(sumneu[2]>0){
00897         PHneuReco+=sumneu[0]*sumneu[1]/sumneu[2];
00898         MeanNpe[1]+=sumneu[3]/Npmt;
00899         MeanSfactor[1]+=sumneu[4]/Npmt/nneugt0;
00900         MeanAtten[1]+=sumneu[5]/Npmt/nneugt0;
00901       }
00902       //
00903       // increment PMT index
00904       //
00905       pmtindex++;
00906     }
00907   }
00908 }
00909 
00910 void ReactorDetector::GenerateGammas(ReactorEvent& Event){
00911 
00912   //cout << "GenerateGammas(Event)" << endl;
00913   //
00914   int maxgamma = 25;
00915   int ngamma=0;
00916   double* egamma = new double[maxgamma];
00917   double* tgamma = new double[maxgamma];
00918   double* rgamma = new double[3*maxgamma];
00919   char* ogamma = new char[maxgamma];
00920   //
00921   double* egptr=egamma;
00922   double* rgptr=rgamma;
00923   double* tgptr=tgamma;
00924   char* ogptr=ogamma;
00925   //
00926   // radioactive source gammas
00927   //
00928   if(Event.GetPmtRad() == "on"){
00929 
00930     int Isotope;
00931     //
00932     // thallium 208
00933     Isotope = 208;
00934     MyTlSource Tl208(Isotope);
00935 
00936     // pick a PMT location for the decay
00937     int len = 1;
00938     float r[len];
00939     ranlux_(r,len);
00940     int pmtId = r[0]*Npmt;
00941     float PMTWeight[Tl208.GetNumTlGammas()];
00942 
00943     // loop over the decay gammas
00944     for(int n=0;n<Tl208.GetNumTlGammas();n++){
00945 
00946       // get the energy for each Tl gamma
00947       float e = Tl208.GetTlGammaEnergy(n); 
00948       *egptr++ = e;
00949 
00950       // propogate the gamma to the scintillating region
00951       PMTWeight[n] = 1.;
00952       int attempts = 1;
00953       double r[3];
00954       double time;
00955 
00956       // pick a direction for each gamma
00957       int len=4;
00958       float rv[len];
00959       ranlux_(rv,len);
00960       double cosg = -1+2*rv[0];
00961       double phig = 2*RC.pi*rv[1];
00962       double t[3];
00963       t[0] = cos(phig)*sqrt(1-cosg*cosg);
00964       t[1] = sin(phig)*sqrt(1-cosg*cosg);
00965       t[2] = cosg;
00966       //for(int i=0;i<3;i++) cout << "t["<<i<<"] " << t[i] << " ";
00967       //cout << endl;
00968       /*
00969        * propogate the gamma through the oil buffer: this assumes 
00970        * that the gamma propogates entirely through oil, but the 
00971        * gammas which reach the scint will travel at the end of 
00972        * their path through scint; however, the mineral oil and 
00973        * scint have very similar H and C densities
00974        */
00975       double range;
00976       std::string material = "oil";
00977       range = GammaComptonRange(material,e);
00978       range*=log(1/rv[2]);
00979       //cout << "range " << range << endl;
00980       //
00981       r[0] = Xpmt[pmtId]+range*t[0];
00982       r[1] = Ypmt[pmtId]+range*t[1];
00983       r[2] = Zpmt[pmtId]+range*t[2];
00984       //
00985       double rdotr = r[0]*r[0]+r[1]*r[1]+r[2]*r[2];
00986       if(sqrt(rdotr)<R1){
00987         pmtRadCount++;
00988         cout << "PMTrad " << pmtRadCount << " radius " << sqrt(rdotr) << endl;
00989       }
00990 
00991       // set the position
00992       for(int i=0;i<3;i++) *rgptr++ = r[i];
00993 
00994       // pick a time relative to the neutrino capture, up to 10000 ns
00995       time = rv[3]*10000.;
00996       //cout << "time " << time << endl;
00997       *tgptr++ = time;
00998 
00999       *ogptr++ = 'T';
01000 
01001       PMTWeight[n] = 1./float(attempts);
01002       //cout << "weight " << PMTWeight[n] << endl;
01003 
01004       ngamma++;
01005     }
01006     //
01007     // thallium 210
01008     /*
01009       Isotope = 210;
01010       MyTlSource Tl210(Isotope);
01011 
01012       // pick a PMT location for the decay
01013       ranlux_(r,len);
01014       pmtId = r[0]*Npmt;
01015 
01016       // get the energy for each Tl gamma
01017       for(int n=0;n<Tl210.GetNumTlGammas();n++){
01018 
01019       *rgptr++ = Xpmt[pmtId];
01020       *rgptr++ = Ypmt[pmtId];
01021       *rgptr++ = Zpmt[pmtId];
01022       *tgptr++ = 0; 
01023       *egptr++ = Tl210.GetTlGammaEnergy(n); 
01024       *ogptr++ = 'Tl';
01025 
01026       ngamma++;
01027       }
01028     */
01029   }
01030   //
01031   // positron gammas
01032   //
01033   int Npositron = Event.GetNumPositron();
01034   //cout << Npositron << " positron(s):" << endl;
01035 
01036   // loop over the positrons
01037   for(int n=0;n<Npositron;n++){
01038 
01039     double rpos[3];
01040     for(int i=0;i<3;i++){
01041       rpos[i] = *(Event.GetPositronVertexXYZ()+(i+n*Event.Rdim));
01042       //cout << " rpos[" << i << "] " << rpos[i] << endl;
01043     }
01044     double tpos = Event.GetPositronTime(n);
01045     //cout << " tpos " << tpos << endl;
01046     double kepos = Event.GetPositronKE(n);
01047     //cout << " kepos " << kepos << endl;
01048     //
01049     // the first is a "fake" gamma with E=positron KE generated at positron
01050     // vertex.
01051     //
01052     for(int i=0;i<3;i++)*rgptr++=rpos[i];
01053     *tgptr++ = tpos;
01054     *egptr++ = kepos;
01055     *ogptr++ = 'P';
01056     ngamma++;
01057     //
01058     // Now the two annihilation gammas
01059     //
01060     int len=4;
01061     float rv[4];
01062     ranlux_(rv,len);
01063     double cosg = -1+2*rv[0];
01064     double phig = 2*RC.pi*rv[1];
01065     double t[3];
01066     t[0] = cos(phig)*sqrt(1-cosg*cosg);
01067     t[1] = sin(phig)*sqrt(1-cosg*cosg);
01068     t[2] = cosg;
01069     double range;
01070     for (int i=0;i<2;i++){
01071       std::string material = "scintillator";
01072       range = GammaComptonRange(material,RC.Melectron);
01073       range*=log(1/rv[i+2]);
01074       if(i==0){
01075         for(int j=0;j<3;j++) *rgptr++ = rpos[j]+range*t[j];
01076       }
01077       if(i==1){
01078         for(int j=0;j<3;j++)*rgptr++ = rpos[j]-range*t[j];
01079       }
01080       *egptr++=RC.Melectron;
01081       *tgptr++=tpos+range/RC.c*refracSc;
01082       *ogptr++ = 'P';
01083       ngamma++;
01084     }
01085   } // done with positrons
01086   //cout << "  " << ngamma << " gammas, so far" << endl;
01087   //
01088   // Generate neutron gammas
01089   //
01090   Nneutron = Event.GetNumNeutron();
01091   //cout << Nneutron << " neutron(s):" << endl;
01092 
01093   // loop over the neutrons
01094   for(int n=0;n<Nneutron;n++){
01095 
01096     double rneu[3];
01097     for(int i=0;i<3;i++){
01098       rneu[i] = *(Event.GetNeutronVertexXYZ()+(i+n*Event.Rdim));
01099       //cout << " rneu[" << i << "] " << rneu[i] << endl;
01100     }
01101     double tneu = Event.GetNeutronTime(n);
01102     //cout << " tneu " << tneu << endl;
01103     //
01104     // pick H or Gd, then which Gd peak
01105     //
01106     double emax=RC.Hpeak;
01107     if(FastNeutronOption){
01108       //cout << "in FastNeutronOption" << endl;
01109       Absorber[n]=1;
01110       double rrneu = sqrt(rneu[0]*rneu[0]+rneu[1]*rneu[1]+rneu[2]*rneu[2]);
01111       if(rrneu<R0){//in Gd region
01112         int len=2;
01113         float rv[2];
01114         ranlux_(rv,len);
01115         if(rv[0]<=GdCaptureFraction){
01116           //
01117           // model Gd spectrum by Gd155 + Gd157
01118           //
01119           if(rv[1]<=RC.Gd155frac){
01120             emax = RC.Gd155peak;
01121             Absorber[n]=155;
01122           }
01123           else{
01124             emax = RC.Gd157peak;
01125             Absorber[n]=157;
01126           }
01127         }
01128       }
01129     }
01130     else{
01131       //cout << "Absorber[" << n << "] " << Absorber[n] << endl;
01132       if(Absorber[n]==1)emax=RC.Hpeak;
01133       if(Absorber[n]==12)emax=RC.Cpeak;
01134       if(Absorber[n]==155)emax=RC.Gd155peak;
01135       if(Absorber[n]==157)emax=RC.Gd157peak;
01136     }
01137     //
01138     // One photon from an H or C capture
01139     //
01140     if(emax==RC.Hpeak || emax==RC.Cpeak){
01141       //cout << " H or C gammas" << endl;
01142       int len=3;
01143       float rv[3];
01144       ranlux_(rv,len);
01145       std::string material = "scintillator";
01146       double range = GammaComptonRange(material,emax);
01147       range*=log(1/rv[0]);
01148       double cosg = -1+2*rv[1];
01149       double phig = 2*RC.pi*rv[2];
01150       double t[3];
01151       t[0] = cos(phig)*sqrt(1-cosg*cosg);
01152       t[1] = sin(phig)*sqrt(1-cosg*cosg);
01153       t[2] = cosg;
01154       for(int j=0;j<3;j++)*rgptr++ = rneu[j]+range*t[j];
01155       *egptr++ = emax;
01156       *tgptr++ = tneu+range/RC.c*refracSc;
01157       *ogptr++ = 'N';
01158       ngamma++;
01159       //cout << "  " << ngamma << " gammas" << endl;
01160     }
01161     //
01162     // otherwise model Gd photons
01163     //
01164     else{
01165       //cout << " Gd gammas" << endl;
01166       int ngd;
01167       double pgd[3*maxgamma];
01168       MyGdDecayModel(emax,ngd,pgd);
01169       float rv2[ngd];
01170       ranlux_(rv2,ngd);
01171       double* qgd=pgd;
01172       double check[4]={0,0,0,0};
01173       for(int i=0;i<ngd;i++){
01174         double p[3];
01175         for(int j=0;j<3;j++)p[j]=*qgd++;
01176         double e = sqrt(p[0]*p[0]+p[1]*p[1]+p[2]*p[2]);
01177         std::string material = "scintillator";
01178         double range = GammaComptonRange(material,e);
01179         range*=log(1/rv2[i]);
01180         for(int j=0;j<3;j++)*rgptr++ = rneu[j]+range*p[j]/e;
01181         //
01182         for(int j=0;j<3;j++)check[j]+=p[j];
01183         check[3]+=e;
01184         //
01185         *egptr++ = e;
01186         *tgptr++ = tneu+range/RC.c*refracGd;
01187         *ogptr++ = 'N';
01188         ngamma++;
01189         //cout << "  " << ngamma << " gammas" << endl;
01190       }
01191     }
01192   } // done with neutrons
01193   //cout << "  " << ngamma << " gammas, total" << endl;
01194   //
01195   // Transfer temp data to storage
01196   //
01197   delete[] Rgamma;
01198   delete[] Egamma;
01199   delete[] Tgamma;
01200   delete[] Ogamma;
01201   
01202   Ngamma = ngamma;
01203   Rgamma = new double[3*ngamma];
01204   Egamma = new double[ngamma];
01205   Tgamma = new double[ngamma];
01206   Ogamma = new char[ngamma];
01207 
01208   rgptr=rgamma+3*ngamma;
01209   double* ptr = Rgamma+3*ngamma;
01210   while(ptr>Rgamma)*--ptr=*--rgptr;
01211 
01212   egptr=egamma+ngamma;
01213   ptr = Egamma+ngamma;
01214   while(ptr>Egamma)*--ptr=*--egptr;
01215 
01216   tgptr=tgamma+ngamma;
01217   ptr = Tgamma+ngamma;
01218   while(ptr>Tgamma)*--ptr=*--tgptr;
01219 
01220   ogptr=ogamma+ngamma;
01221   char* qtr = Ogamma+ngamma;
01222   while(qtr>Ogamma)*--qtr=*--ogptr;
01223 
01224   /*
01225   cout << "  " << Ngamma << " gammas" << endl;
01226   for(int n=0;n<Ngamma;n++){
01227     for(int i=0;i<3;i++) cout << "  Rgamma[" << 3*n+i << "] " 
01228                               << Rgamma[3*n+i];
01229     cout << endl;
01230     cout << "  Egamma[" << n << "] " << Egamma[n] 
01231          << "  Tgamma[" << n << "] " << Tgamma[n]
01232          << "  Ogamma[" << n << "] " << Ogamma[n] << endl;
01233   }
01234   */
01235 
01236   delete[] rgamma;
01237   delete[] egamma;
01238   delete[] tgamma;
01239   delete[] ogamma;
01240     
01241 }
01242 
01243 
01244 ReactorDetector::PMT* ReactorDetector::ResizePMT(){
01245 
01246   int oldsize = PMTsize;
01247   int newsize = 2*oldsize;
01248   PMT* PMThold = new PMT[newsize];
01249   PMT* PMTold = PMTdata+oldsize;
01250   PMT* PMTnew = PMThold+oldsize;
01251   while(PMTnew>PMThold)*--PMTnew=*--PMTold;
01252   delete[] PMTdata;
01253   PMTdata = new PMT[newsize];
01254   PMTold = PMThold+newsize;
01255   PMTnew = PMTdata+newsize;
01256   while(PMTnew>PMTdata)*--PMTnew=*--PMTold;
01257   delete[] PMThold;
01258   PMTsize = newsize;
01259   return PMTdata+oldsize;
01260 }
01261 //
01262 // Fetch number of gammas from positron
01263 //
01264 int ReactorDetector::GetNgamma(char parent){
01265   int gamma=0;
01266   for(char* optr=Ogamma;optr<Ogamma+Ngamma;optr++){
01267     if (*optr==parent)gamma++;
01268   }
01269   return gamma;
01270 }
01271 //
01272 // Fetch array of positron gammas
01273 //
01274 void ReactorDetector::GetGamma(char parent,double* xyz){
01275 
01276   double* Rptr=Rgamma;
01277   double* rptr=xyz;
01278   //
01279   for(char* optr=Ogamma;optr<Ogamma+Ngamma;optr++){
01280     if (*optr==parent){
01281       for(int i=0;i<3;i++)*rptr++ = *Rptr++;
01282     }
01283   }
01284 }  
01285 void ReactorDetector::GetGamma(char parent,double* e,
01286                                   double* t,double* r,
01287                                   double* c,double* f){
01288   double* Eptr=Egamma;
01289   double* Rptr=Rgamma;
01290   double* Tptr=Tgamma;
01291   double* eptr=e;
01292   double* rptr=r;
01293   double* tptr=t;
01294   double* cptr=c;
01295   double* fptr=f;
01296   //
01297   for(char* optr=Ogamma;optr<Ogamma+Ngamma;optr++){
01298     if (*optr==parent){
01299       *e++=*Eptr;
01300       *t++=*Tptr;
01301       double x=*(Rptr+0);
01302       double y=*(Rptr+1);
01303       double z=*(Rptr+2);
01304       *r++=sqrt(x*x+y*y+z*z);
01305       *c++=z/(*r);
01306       *f++=atan2(y,x);
01307       if((*f)<0)*f+=2*RC.pi;
01308     }
01309     Eptr++;
01310     Tptr++;
01311     Rptr+=3;
01312   }
01313 }
01314 void ReactorDetector::SetNominalParameters(){
01315   //
01316   // Set nominal detector parameters from ReactorConstants
01317   //
01318   R0 = RC.R0;
01319   R1 = RC.R1;
01320   R2 = RC.R2;
01321   //
01322   GdConcentration=RC.GdConcentration;
01323   //
01324   refracGd = RC.refracGd;
01325   refracSc = RC.refracSc;
01326   //
01327   mfpGd = RC.mfpGd; 
01328   mfpSc = RC.mfpSc;
01329   //
01330   MeanNeuDispl = RC.MeanNeuDispl;
01331   //
01332   FastNeutronOption = RC.FastNeutronOption;
01333   Temperature = RC.Temperature;
01334   //
01335   tGd = RC.tGd;
01336   tSc = RC.tSc;
01337   //
01338   GdCaptureFraction = RC.GdCaptureFraction;
01339   //
01340   // This is an ad-hoc guess for the average number of gammas/per Gd.
01341   // The program in practice generates at least two gammas per capture
01342   // and an additional Poisson fluctuated GammasPerGd-2.
01343   //
01344   GammasPerGd = RC.GammasPerGd;
01345   //
01346   attenlGd = RC.attenlGd;
01347   attenlSc = RC.attenlSc;
01348   //
01349   PhotonsPerMeV = RC.PhotonsPerMeV;
01350   //
01351   ShortPosFrac0 = RC.ShortPosFrac0;
01352   ShortPosFrac1 = RC.ShortPosFrac1;
01353   LongPosFrac = RC.LongPosFrac;
01354   ShortPosTime0 = RC.ShortPosTime0;
01355   ShortPosTime1 = RC.ShortPosTime1;
01356   LongPosTime = RC.LongPosTime;
01357   //
01358   PMTcoverage = RC.PMTcoverage;
01359   PMTdiameter = RC.PMTdiameter;
01360   //
01361   PMTqe = RC.PMTqe;
01362 }
01363 void ReactorDetector::SetPMT(){
01364   //
01365   // determine the number of PMT
01366   //
01367 
01368   Npmt = 16*R2*R2*PMTcoverage/PMTdiameter/PMTdiameter;
01369   Ncosbins = sqrt(Npmt/RC.pi);
01370   Nphibins = sqrt(Npmt*RC.pi);
01371   Npmt = Ncosbins*Nphibins;
01372 
01373   delete[] Xpmt;
01374   delete[] Ypmt;
01375   delete[] Zpmt;
01376 
01377   Xpmt = new double[Npmt];
01378   Ypmt = new double[Npmt];
01379   Zpmt = new double[Npmt];
01380   
01381   //
01382   // Make a guess at PMT size to avoid too much re-sizing
01383   //
01384   delete[] PMTdata;
01385   PMTlen = 0;
01386   PMTsize = 10*Npmt;
01387   PMTdata = new PMT[PMTsize];
01388   //
01389   // loop over cotheta, then phi
01390   //
01391   double* xpmt=Xpmt;
01392   double* ypmt=Ypmt;
01393   double* zpmt=Zpmt;
01394   
01395   double dphi = 2*RC.pi/Nphibins;
01396   double dz = 2.0/Ncosbins;
01397   
01398   for(int i=0;i<Ncosbins;i++){
01399     double z = -1+i*dz+dz/2;
01400     for(int j=0;j<Nphibins;j++){
01401       double phi = j*dphi+dphi/2;
01402       *xpmt++ = R2*sqrt(1-z*z)*cos(phi);
01403       *ypmt++ = R2*sqrt(1-z*z)*sin(phi);
01404       *zpmt++ = R2*z;
01405       //      cout << "z,phi  " << z << " " << phi << endl;
01406     }
01407   }     
01408 }
01409 void ReactorDetector::SetParam_GdConcentration(double x){
01410   GdConcentration =x;
01411   double y =(GdConcentration/RC.GdConcentrationRef);
01412   double z = GdCaptureFraction/(1-GdCaptureFraction);
01413   //
01414   GdCaptureFraction = y*z/(1+y*z);
01415   //
01416   mfpGd*=(1+z)/(1+y*z);
01417   tGd*=(1+z)/(1+y*z);
01418 }
01419 double ReactorDetector::GetHitFrac(char parent){
01420   bool hit[Npmt];
01421   for(int i=0;i<Npmt;i++)hit[i]=0;
01422   for(PMT* pPMT=PMTdata;pPMT<PMTdata+PMTlen;pPMT++){
01423     if(pPMT->Parent==parent&&pPMT->Npe>0)hit[pPMT->npmt]=1;
01424   }
01425   int nhit=0;
01426   for(int i=0;i<Npmt;i++)nhit+=hit[i];
01427   return 1.0*nhit/Npmt;
01428 }
01429 void ReactorDetector::CalculateDipoleMoment(char parent){
01430 
01431   double d[3] = {0,0,0};
01432   double q=0;
01433   for(PMT* pPMT=PMTdata;pPMT<PMTdata+PMTlen;pPMT++){
01434     if(pPMT->Parent==parent&&pPMT->Npe>0){
01435       q+=pPMT->PHsmr;
01436       for(int i=0;i<3;i++)d[i]+=(pPMT->PHsmr)*(pPMT->xyz[i]);
01437     }
01438   }
01439   if(q>0)for(int i=0;i<3;i++)d[i]/=q;
01440 
01441   if(parent=='P'){
01442     for(int i=0;i<3;i++)DipolePositron[i] = d[i];
01443   }
01444   if(parent=='N'){
01445     for(int i=0;i<3;i++)DipoleNeutron[i] = d[i];
01446   }
01447 }
01448 void ReactorDetector::ImproveDipoleMoment(char parent){
01449 
01450   double d[3];
01451   double k;
01452   PMT* qPMT;
01453   if(parent=='P'){
01454     for(int i=0;i<3;i++)d[i]=DipolePositron[i];
01455     k = PHpositron;
01456     qPMT=PMTpositron;
01457   }
01458   if(parent=='N'){
01459     for(int i=0;i<3;i++)d[i]=DipoleNeutron[i];
01460     k = PHneutron;
01461     qPMT=PMTneutron;
01462   }
01463   //
01464   double C= RC.PMTqe*RC.PMTdiameter*RC.PMTdiameter/16*RC.PhotonsPerMeV;
01465   //
01466   double sumlast = 999999;
01467   double test=999999;
01468   double tol=0.01;
01469   int sign=1;
01470   bool first=1;
01471   double dev=0.1;
01472   while(test>tol){
01473   //
01474     double dlast[3];
01475     for(int i=0;i<3;i++)dlast[i]=d[i];
01476     double klast=k;
01477     double sum[3]={0,0,0};
01478     for(PMT* pPMT=qPMT;pPMT<qPMT+Npmt;pPMT++){
01479       if(pPMT->Parent!=parent)continue;
01480       double r[3];
01481       double rn[3];
01482       double t[3];
01483       for(int i=0;i<3;i++)rn[i]=pPMT->xyz[i];
01484       for(int i=0;i<3;i++)r[i]=rn[i]-d[i];
01485       double rdotr = r[0]*r[0]+r[1]*r[1]+r[2]*r[2];
01486       double rdotrn = r[0]*rn[0]+r[1]*rn[1]+r[2]*rn[2];
01487       for(int i=0;i<3;i++)t[i]=r[i]/sqrt(rdotr);
01488       //
01489       double tdotd=d[0]*t[0]+d[1]*t[1]+d[2]*t[2];
01490       double ddotd=d[0]*d[0]+d[1]*d[1]+d[2]*d[2];
01491       double test2=tdotd*tdotd-ddotd+R0*R0;
01492       double sSc;
01493       double sGd;
01494       //
01495       if(test2<0){//no intersections with inner shell
01496         sSc=sqrt(rdotr);
01497         sGd=0;
01498       }
01499       else{
01500         double s1=-tdotd+sqrt(test2);
01501         double s2=-tdotd-sqrt(test2);
01502         if(s1>0&&s2>0){//2 interesections
01503           sSc=sqrt(rdotr)-s1+s2;
01504           sGd=s1-s2;
01505         }
01506         else if(s1>0&&s2<0){//1 interestion
01507           sSc=sqrt(rdotr)-s1;
01508           sGd=s1;
01509         }
01510         else {//no interesctions
01511           sSc=sqrt(rdotr);
01512           sGd=0;
01513         }
01514       }
01515       //
01516       double mn=pPMT->Npe;
01517       double w0=C*rdotrn/R2/sqrt(rdotr)/rdotr*
01518         exp(-sGd/RC.attenlGd-sSc/RC.attenlSc);
01519       sum[0]+=mn;
01520       sum[1]+=w0;
01521       sum[2]+=w0*klast-mn*log(w0*klast);
01522     }
01523     if(first){
01524       k = sum[0]/sum[1];
01525       for(int i=0;i<3;i++)d[i]*=(1+dev);
01526       first=0;
01527     }
01528     else{
01529       k = sum[0]/sum[1];
01530       if(sum[2]<sumlast){
01531         for(int i=0;i<3;i++)d[i]*=(1+sign*dev);
01532       }
01533       else{
01534         sign*=-1;
01535         dev/=2;
01536         for(int i=0;i<3;i++)d[i]*=(1+sign*dev);
01537       }
01538     }
01539     test=1-sum[2]/sumlast;
01540     if(test<0)test*=-1;
01541     sumlast=sum[2];
01542   }
01543   if(parent=='P')for(int i=0;i<3;i++)DipolePositron[i]=d[i];
01544   if(parent=='N')for(int i=0;i<3;i++)DipoleNeutron[i]=d[i];
01545 }  
01546 //
01547 //
01548 //
01549 void ReactorDetector::ConsolidatePMT(){
01550   //
01551   // first sum the total xpe
01552   //
01553   double xpepos[Npmt];
01554   double xpeneu[Npmt];
01555   int subhitspos[Npmt];
01556   int subhitsneu[Npmt];
01557   //
01558   for(int i=0;i<Npmt;i++)xpepos[i]=0;
01559   for(int i=0;i<Npmt;i++)xpeneu[i]=0;
01560   for(int i=0;i<Npmt;i++)subhitspos[i]=0;
01561   for(int i=0;i<Npmt;i++)subhitsneu[i]=0;
01562   //
01563   for(PMT* pPMT=PMTdata;pPMT<PMTdata+PMTlen;pPMT++){
01564     int n=pPMT->npmt;
01565     if(pPMT->Parent=='P'){
01566       xpepos[n]+=pPMT->Npe;
01567       subhitspos[n]++;
01568     }
01569     if(pPMT->Parent=='N'){
01570       xpeneu[n]+=pPMT->Npe;
01571       subhitsneu[n]++;
01572     }
01573   }
01574   //   
01575   delete[] PMTpositron;
01576   PMTpositron = new PMT[Npmt];
01577   delete[] PMTneutron;
01578   PMTneutron = new PMT[Npmt];
01579   //
01580   for(int i=0;i<Npmt;i++){
01581     (*(PMTpositron+i)).npmt=i;
01582     (*(PMTpositron+i)).Parent='P';
01583     (PMTpositron+i)->SetSubHitsPtr(subhitspos[i]);
01584     //
01585     (*(PMTneutron+i)).npmt=i;
01586     (*(PMTneutron+i)).Parent='N';
01587     (PMTneutron+i)->SetSubHitsPtr(subhitsneu[i]);
01588   }
01589   //
01590   for(PMT* pPMT=PMTdata;pPMT<PMTdata+PMTlen;pPMT++){
01591     int n=pPMT->npmt;
01592     PMT* qPMT;
01593     if(pPMT->Parent=='P'){
01594       qPMT = PMTpositron+n;
01595       *qPMT+=*pPMT;
01596     }
01597     if(pPMT->Parent=='N'){
01598       qPMT = PMTneutron+n;
01599       *qPMT+=*pPMT;
01600     }
01601   }
01602   cout;
01603 }    

Generated on Thu Jul 29 14:27:03 2004 for ReactorFsim by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002