Main Page   File List  

ReactorDetector.cpp

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

Generated on Sat Jul 17 14:45:42 2004 for ReactorFsim by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002