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

Generated on Fri Oct 22 13:56:25 2004 for ReactorFsim by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002