Main Page   Compound List   File List   Compound Members   File Members  

MuonPropagator.cpp

Go to the documentation of this file.
00001 
00006 #include <math.h>
00007 #include <iostream.h>
00008 #include <fstream.h>   // file I/O
00009 #include <iomanip.h>   // format manipulation
00010 #include <string>
00011 #include "ReactorConstants.hh"
00012 #include "ReactorFortran.hh"
00013 #include "MuonPropagator.hh"
00014 #include "MyHeSource.hh"
00015 #include "MyLiSource.hh"
00016 
00017 MuonPropagator::MuonPropagator(int newRmaxgen, double newDepth){
00018 
00019   Rmaxgen = newRmaxgen;
00020   Depth = newDepth;
00021 
00022   //cout << "MuonPropagator::MuonPropagator(" << Rmaxgen << "," 
00023   //     << Depth << ")" << endl;
00024 
00025   static double re  = k.Relectron;
00026   static double pi  = k.pi;
00027   static double me  = k.Melectron;
00028   static double mmu = k.Mmuon;
00029   static double Na  = k.Navogadro;
00030   static double c   = k.c;
00031   static double density = k.density;
00032   //
00033   // For electron density
00034   //
00035   static double nel[2];
00036   static double A[2] = {k.A0,k.A1};
00037   static double Z[2] = {k.Z0,k.Z1};
00038   static double f[2] = {k.f0,k.f1};
00039   static double I[2] = {k.I0,k.I1};
00040   //
00041   static double ncar;
00042   //
00043   // create the energy and cosine of zenith angle (theta) arrays
00044   bool static first = true;
00045   double static Energy[Mdim],CosTheta[Mdim];
00046   double flux;
00047   float static fspace[200];
00048   if(first){
00049 
00050     if(Depth == 500){
00051       // read in the muon energy in GeV and angle
00052       fstream fin("data/Totb500a.dat", ios::in);
00053       //cout << "setup file: data/Totb500a.dat" << endl;
00054 
00055       double dummy;
00056       for(int i=0;i<Mdim;i++){
00057         fin >> dummy >> Energy[i] >> dummy >> dummy >> dummy >> CosTheta[i];
00058         //cout << i << "  " << Energy[i] << "  " << CosTheta[i] << endl;
00059       }
00060 
00061       flux = 0.145;  // per m**2 per sec
00062     }
00063     else{
00064       cout << "  ERROR: no muon data for depth of " << Depth << " mwe" << endl;
00065       return;
00066     }
00067 
00068     // electron density
00069     for(int i=0;i<2;i++) nel[i] = Na*density*f[i]*Z[i]/A[i];
00070     //cout << " nel " << nel[0]+nel[1] << endl;
00071 
00072     // 12C atom density
00073     ncar = Na*density*f[1]/A[1];
00074     //cout << " ncar " << ncar << endl;
00075 
00076     // prepare the lateral activation profile
00077     float xlo = 0.;
00078     float xhi = 50.;
00079     float q = 0.;
00080     funlxp_(IsotopeDistance,fspace,xlo,xhi);
00081 
00082     Weight = 0.;
00083 
00084     first = false;
00085   }
00086 
00087   /* get the muon energy and cosine of the zenith angle
00088      the spectra in Totb500a.dat are random so start 
00089      with the first entry and cycle through the file
00090   */
00091   static int index = 0;
00092   if(index < Mdim){
00093     //
00094     // muon energy in MeV
00095     energy = Energy[index]*1000.;
00096     cosg = CosTheta[index];
00097     //cout << " muon energy " << energy << " MeV, cos(theta) " << cosg << endl;
00098     index++;
00099   }
00100   else{
00101     cout << "  WARNING: end of muon input file reached at index " << index 
00102          << ".  Starting over." << endl;
00103     index = 0;
00104   }
00105 
00106   /* pick a starting point: define a square above the detector
00107      through which the muons must pass.  The square is centered 
00108      on the z-axis at Rmaxgen and the area is A = (Rmaxgen+delta)**2.  
00109      Randomly pick a point on the square to start the muon and use 
00110      cos(theta) and a randomly selected azimuthal angle to decide
00111      how the muon hits the detector.  Only keep events where the
00112      muon hits the scint.
00113   */
00114   int inter;
00115   double r[6],t[3];
00116   double x[2],y[2],z[2];
00117   double delta = Rmaxgen*20;
00118   bool passed = false;
00119   //
00120   while(!passed){
00121 
00122     int len=3;
00123     float rv[len];
00124     ranlux_(rv,len);
00125     r[0] = (2*rv[0]-1)*delta;
00126     r[1] = (2*rv[1]-1)*delta;
00127     r[2] = Rmaxgen;
00128     phig = 2*k.pi*rv[2];
00129 
00130     // pick the direction
00131     t[0] = cos(phig)*sqrt(1-cosg*cosg);
00132     t[1] = sin(phig)*sqrt(1-cosg*cosg);
00133     t[2] = cosg;
00134     //for(int i=0;i<3;i++) cout << "t["<<i<<"] " << t[i] << " ";
00135     //cout << endl;
00136 
00137     // find the far end of the line a unit distance
00138     // from (x,y,z) along the t direction
00139     for(int i=0;i<3;i++) r[i+3] = r[i]-t[i];
00140     //
00141     //for(int i=0;i<6;i++) cout << "r["<<i<<"] " << r[i] << " ";
00142     //cout << endl;
00143 
00144     // solve for intersections with the scint region
00145     double* p;
00146     int num;
00147 
00148     p = Intersection(r[0], r[1], r[2],  // first end of line
00149                      r[3], r[4], r[5],  // second end of line
00150                      0, 0, 0, Rmaxgen); // detector centered at 0
00151 
00152     num = (int)*p++;
00153     if(num>1){
00154 
00155       inter = 2;
00156       for(int i=0; i<inter; i++){
00157         x[i] = *p++;
00158         y[i] = *p++;
00159         z[i] = *p++;
00160       }
00161       passed = true;
00162     }
00163   }
00164   /*
00165   for(int i=0; i<inter; i++){
00166     cout << " X-coordinate of point " << i << " : " << x[i] << endl;
00167     cout << " Y-coordinate of point " << i << " : " << y[i] << endl;
00168     cout << " Z-coordinate of point " << i << " : " << z[i] << endl;
00169   }
00170   */
00171   // path length
00172   double L = sqrt((x[1]-x[0])*(x[1]-x[0])+
00173                   (y[1]-y[0])*(y[1]-y[0])+
00174                   (z[1]-z[0])*(z[1]-z[0]));
00175   //cout << " path length " << L << endl;
00176 
00177   /* iterate through the muon energy loss dE/dx in dx cm steps,
00178      making a gamma at the center of the dx cm segment of the 
00179      line along the muon path equal to the energy lost in that 
00180      segment; always check that the muon is still in the 
00181      detector and has not stopped
00182   */
00183   double step=5.0;
00184   double Emin=0.01;
00185   //
00186   double range = 0;
00187   double time = 0;
00188   //
00189   // define energy and position arrays
00190   //
00191   int maxgammafromisotope = 5;
00192   int maxgamma = int(Rmaxgen*2/step)+maxgammafromisotope;
00193   double* egamma = new double[maxgamma];
00194   double* rgamma = new double[maxgamma*3];
00195   double* tgamma = new double[maxgamma];
00196   //
00197   double* egptr=egamma;
00198   double* rgptr=rgamma;
00199   double* tgptr=tgamma;
00200   //
00201   // Begin energy loss loop
00202   //
00203   double dE=0;
00204   double eloss;
00205   int ngamma = 0;
00206   //
00207   bool done = false;
00208   while(!done){
00209 
00210     // zero the energy loss for this segment
00211     eloss = 0;
00212     //
00213     // check that the muon hasn't stopped
00214     //
00215     if(energy-dE > Emin){
00216       //
00217       // check that we aren't leaving the detector
00218       //
00219       if(range+step < L){
00220         //
00221         // iterate range and time
00222         //
00223         double gamma = 1+(energy-dE)/mmu;
00224         double beta = sqrt(1-1/gamma/gamma);
00225         range+=step;
00226         time+=step/beta/c;
00227         //
00228         // increment energy loss
00229         //
00230         double te = gamma-1;
00231         double tc = Emin/mmu;
00232         double tmax = te;
00233         double tup = tc;
00234         if(tc>tmax)tup=tmax;
00235         //
00236         for (int k=0;k<2;k++){
00237           eloss+=2*pi*re*re*me*nel[k]*step/beta/beta*
00238             (log(2*(gamma+1)/(I[k]*I[k]/me/me))
00239              +RadCorr(te,tup));
00240         }
00241         //
00242         // add the energy loss to dE and set the "photon" energy
00243         //
00244         if(dE+eloss > energy){
00245           *egptr++=energy-dE; // the muon stops, limit dE and egamma
00246           dE=energy;
00247         }
00248         else{
00249           *egptr++=eloss; // the muon is still travelling
00250           dE+=eloss;
00251         }
00252         //
00253         // put the photon at the center of the segment
00254         //
00255         *rgptr++ = x[1] - (range-(step/2))*t[0];
00256         *rgptr++ = y[1] - (range-(step/2))*t[1];
00257         *rgptr++ = z[1] - (range-(step/2))*t[2];
00258         //
00259         *tgptr++ = time;
00260         //
00261         // count the photon
00262         ngamma++;
00263       }
00264       else{
00265         /* we have reached the end of the detector; put one final 
00266            gamma to cover the last remaining segment of energy loss
00267         */
00268         double laststep = L-range;
00269         //
00270         double gamma = 1+(energy-dE)/mmu;
00271         double beta = sqrt(1-1/gamma/gamma);
00272         range+=laststep;
00273         time+=laststep/beta/c;
00274         //
00275         // increment energy loss
00276         //
00277         double te = gamma-1;
00278         double tc = Emin/mmu;
00279         double tmax = te;
00280         double tup = tc;
00281         if(tc>tmax)tup=tmax;
00282         //
00283         for (int k=0;k<2;k++){
00284           eloss+=2*pi*re*re*me*nel[k]*laststep/beta/beta*
00285             (log(2*(gamma+1)/(I[k]*I[k]/me/me))
00286              +RadCorr(te,tup));
00287         }
00288         //
00289         // add the energy loss to dE and set the "photon" energy
00290         //
00291         if(dE+eloss > energy){
00292           *egptr++=energy-dE; // the muon stops, limit dE and egamma
00293           dE=energy;
00294         }
00295         else{
00296           *egptr++=eloss; // the muon is still travelling
00297           dE+=eloss;
00298         }
00299         //
00300         // put the photon at the center of the segment
00301         //
00302         *rgptr++ = x[1] - (range-(laststep/2))*t[0];
00303         *rgptr++ = y[1]- (range-(laststep/2))*t[1];
00304         *rgptr++ = z[1]- (range-(laststep/2))*t[2];
00305         //
00306         *tgptr++ = time;
00307         //
00308         // count the last photon
00309         ngamma++;
00310         //
00311         // finish the loop
00312         done = true;
00313       }
00314     }
00315     else{
00316       /* the muon has stopped in the detector, make one last photon
00317          with energy equal the mass of the muon
00318       */
00319 
00320       // set the "photon" energy
00321       //
00322       *egptr++=mmu;
00323       //
00324       // put the photon at point the muon stopped
00325       //
00326       *rgptr++ = x[1] - range*t[0];
00327       *rgptr++ = y[1] - range*t[1];
00328       *rgptr++ = z[1] - range*t[2];
00329       //
00330       *tgptr++ = time;
00331       //
00332       // count the last photon
00333       ngamma++;
00334       //
00335       // finish the loop
00336       done = true;
00337     }
00338   }
00339   //cout << " muon range " << range << " cm, time " << time 
00340   //     << " ns and energy loss " << dE << " MeV" << endl;
00341 
00342   /* now deal with isotope production; start with the cross-section 
00343      for 9Li+8He prodution (as a function of incident muon energy 
00344      in MeV) and generate an isotope; this isn't perfect because the 
00345      muon changes energy throughout its path, altering the XC, but 
00346      it's okay for now
00347    */
00348   double XC;
00349   double mfp;
00350   double alpha = 0.73; // from the Hagner paper
00351   double XCmeas = 2.12;
00352   double Emeas = 190000.; // 190 GeV
00353   double ubarntocmsq = 1e-30;
00354   //cout << " sf " << (XCmeas/pow(Emeas,alpha))*ubarntocmsq << endl;
00355   //
00356   XC = (XCmeas/pow(Emeas,alpha))*pow(energy,alpha)*ubarntocmsq;
00357   //cout << " XC " << XC << " cm^2" << endl;
00358   //
00359   // compute mean free path to produce 9Li+8He
00360   //
00361   mfp = 1/ncar/XC;
00362   //
00363   int ntrial = 0;
00364   passed = false;
00365   while(!passed){
00366 
00367     int len=1;
00368     float rv[len];
00369     ranlux_(rv,len);
00370     mfp*=log(1/rv[0]);
00371 
00372     // check that the isotope is inside the detector
00373     if(mfp < L) passed = true;
00374 
00375     // count the attempt
00376     ntrial++;
00377   }
00378   //cout << " mfp " << mfp << " cm" << endl;
00379 
00380   /* start at the mean free path distance from where the muon 
00381      entered the detector along the muon track in the direction 
00382      of the muon flight to produce the isotope; define a new 
00383      coordinate system with the muon track being the +z'-axis, 
00384      find the perpendicular distance from the muon track via 
00385      Hagner, and pick a random azimuthal angle; thus the 
00386      perpendicular distance and azimuthal angle give the new 
00387      x' and y' values for the isotope and the point of isotope 
00388      production along the muon track is z' = 0; then rotate the 
00389      new coordinate system into the detector x, y, and z
00390   */
00391   double ri[3];
00392   ri[0] = x[1] - mfp*t[0];
00393   ri[1] = y[1] - mfp*t[1];
00394   ri[2] = z[1] - mfp*t[2];
00395   //
00396   // pick the direction, relative to point ri
00397   //
00398   int len=2;
00399   float rw[len];
00400   ranlux_(rw,len);
00401 
00402   double newphig = 2*k.pi*rw[0];
00403   double newcosg = 0.;
00404   double newt[3];
00405   newt[0] = cos(newphig)*sqrt(1-newcosg*newcosg);
00406   newt[1] = sin(newphig)*sqrt(1-newcosg*newcosg);
00407   newt[2] = newcosg;
00408   //
00409   // select the lateral distance from the muon track, relative to ri
00410   //
00411   float lateraldistance;
00412   len = 1;
00413   funlux_(fspace,lateraldistance,len);
00414   //
00415   // define point rt by x',y', and z' in the new coordinate system
00416   //
00417   double rt[3];
00418   rt[0] = lateraldistance*newt[0];
00419   rt[1] = lateraldistance*newt[1];
00420   rt[2] = lateraldistance*newt[2];
00421 
00422   /* always assume that the x'-axis of the new coordinate system is 
00423      in the direction chosen by angle phig of the muon track above; 
00424      thus we rotate point rt around the y'-axis (which is now chosen 
00425      always perpendicular to the detector coordinate system's x-y 
00426      plane) by the angle given by cosg above subtracted from pi; we 
00427      then rotate the new point qt around the z'-axis by angle pi 
00428      minus phig to get the new point pt, which is rt in the 
00429      detector coordinate system
00430   */
00431   double angle = pi - acos(cosg);
00432   double* qt;
00433   qt = Rotate('Y',angle,rt[0],rt[1],rt[2]);
00434   //
00435   // second rotation
00436   //
00437   angle = pi - phig;
00438   double* pt;
00439   pt = Rotate('Z',angle,qt[0],qt[1],qt[2]);
00440   //
00441   // add the new lateral displacement to the point on the muon 
00442   // track at which the isotope is produced
00443   //
00444   for(int i=0; i<3; i++)ri[i] += pt[i];
00445   //
00446   // decide if we have 9Li or 8He
00447   //
00448   char* isotope;
00449   if(rw[1] <= 0.5) 
00450     isotope = "9Li";
00451   else
00452     isotope = "8He";
00453   //
00454   // make energy and position arrays
00455   //
00456   int maxneutron = 1;
00457   double* eneutron = new double[maxneutron];
00458   double* rneutron = new double[maxneutron*3];
00459   double* tneutron = new double[maxneutron];
00460   //
00461   double* enptr = eneutron;
00462   double* rnptr = rneutron;
00463   double* tnptr = tneutron;
00464   //
00465   int maxelectron = 1;
00466   double* eelectron = new double[maxelectron];
00467   double* relectron = new double[maxelectron*3];
00468   double* telectron = new double[maxelectron];
00469   //
00470   double* eeptr = eelectron;
00471   double* reptr = relectron;
00472   double* teptr = telectron;
00473   //
00474   // let the isotope decay
00475   //
00476   int nneutron = 0;
00477   int nelectron = 0;
00478   //
00479   if(isotope == "9Li"){
00480     MyLiSource LiSource(9,Rmaxgen);
00481 
00482     nneutron = 1;
00483     *enptr++ = LiSource.GetLiNeutronEnergy();
00484     for(int i=0; i<3; i++) *rnptr++ = ri[i];
00485     *tnptr++ = LiSource.GetLiDecayTime();
00486 
00487     nelectron = 1;
00488     *eeptr++ = LiSource.GetLiBetaEnergy();
00489     for(int i=0; i<3; i++) *reptr++ = ri[i];
00490     *teptr++ = LiSource.GetLiDecayTime();
00491 
00492     Weight = 1./float(ntrial)*LiSource.GetLiWeight()*flux;
00493   }
00494   else if(isotope == "8He"){
00495     MyHeSource HeSource(8,Rmaxgen);
00496 
00497     nneutron = 1;
00498     *enptr++ = HeSource.GetHeNeutronEnergy();
00499     for(int i=0; i<3; i++) *rnptr++ = ri[i];
00500     *tnptr++ = HeSource.GetHeDecayTime();
00501 
00502     nelectron = 1;
00503     *eeptr++ = HeSource.GetHeBetaEnergy();
00504     for(int i=0; i<3; i++) *reptr++ = ri[i];
00505     *teptr++ = HeSource.GetHeDecayTime();
00506 
00507     Weight = 1./float(ntrial)*HeSource.GetHeWeight()*flux;
00508   }
00509   else{
00510     cout << "  ERROR: unknown isotope " << isotope 
00511          << ".  Options are '9Li' and '8He'." << endl;
00512   }
00513   //
00514   // transfer temp data to storage
00515   //
00516   Nneutron = nneutron;
00517   Nelectron = nelectron;
00518   Ngamma   = ngamma;
00519 
00520   Eneutron = new double[nneutron];
00521   Rneutron = new double[nneutron*3];
00522   Tneutron = new double[nneutron];
00523 
00524   Eelectron = new double[nelectron];
00525   Relectron = new double[nelectron*3];
00526   Telectron = new double[nelectron];
00527 
00528   Egamma = new double[ngamma];
00529   Rgamma = new double[ngamma*3];
00530   Tgamma = new double[ngamma];
00531 
00532   double* ptr;
00533 
00534   ptr = Eneutron+nneutron;
00535   while(ptr>Eneutron)*--ptr=*--enptr;
00536 
00537   ptr = Rneutron+3*nneutron;
00538   while(ptr>Rneutron)*--ptr=*--rnptr;
00539 
00540   ptr = Tneutron+nneutron;
00541   while(ptr>Tneutron)*--ptr=*--tnptr;
00542 
00543   ptr = Eelectron+nelectron;
00544   while(ptr>Eelectron)*--ptr=*--eeptr;
00545 
00546   ptr = Relectron+3*nelectron;
00547   while(ptr>Relectron)*--ptr=*--reptr;
00548 
00549   ptr = Telectron+nelectron;
00550   while(ptr>Telectron)*--ptr=*--teptr;
00551 
00552   ptr = Egamma+ngamma;
00553   while(ptr>Egamma)*--ptr=*--egptr;
00554 
00555   ptr = Rgamma+3*ngamma;
00556   while(ptr>Rgamma)*--ptr=*--rgptr;
00557 
00558   ptr = Tgamma+ngamma;
00559   while(ptr>Tgamma)*--ptr=*--tgptr;
00560 
00561   /*
00562   cout << Nneutron << " neutrons" << endl;
00563   for(int n=0; n<Nneutron; n++){
00564     cout << " neutron " << n << " energy " << Eneutron[n] << " MeV, and x, y, z:";
00565     for(int i=0; i<3; i++) cout << "  " << Rneutron[3*n+i];
00566     cout << endl << " and time " << Tneutron[n] << " nsec" << endl;
00567   }
00568 
00569   cout << Nelectron << " electrons" << endl;
00570   for(int n=0; n<Nelectron; n++){
00571     cout << " electron " << n << " energy " << Eelectron[n] << " MeV, and x, y, z:";
00572     for(int i=0; i<3; i++) cout << "  " << Relectron[3*n+i];
00573     cout << endl << " and time " << Telectron[n] << " nsec" << endl;
00574   }
00575 
00576   cout << Ngamma << " photons" << endl;
00577   for(int n=0; n<Ngamma; n++){
00578     cout << " photon " << n << " energy " << Egamma[n] << " MeV, and x, y, z:";
00579     for(int i=0; i<3; i++) cout << "  " << Rgamma[3*n+i];
00580     cout << endl << " and time " << Tgamma[n] << " nsec" << endl;
00581   }
00582   */
00583 
00584   // clean up
00585   delete[] eneutron;
00586   delete[] rneutron;
00587   delete[] tneutron;
00588   delete[] eelectron;
00589   delete[] relectron;
00590   delete[] telectron;
00591   delete[] egamma;
00592   delete[] rgamma;
00593   delete[] tgamma;
00594 }
00595 
00596 MuonPropagator::~MuonPropagator(){
00597   delete[] Eneutron;
00598   delete[] Rneutron;
00599   delete[] Tneutron;
00600   delete[] Eelectron;
00601   delete[] Relectron;
00602   delete[] Telectron;
00603   delete[] Egamma;
00604   delete[] Rgamma;
00605   delete[] Tgamma;
00606 }
00607 
00608 MuonPropagator::MuonPropagator(const MuonPropagator& Muon){
00609 
00610   Rmaxgen = Muon.Rmaxgen;
00611 
00612   Nmuon = Muon.Nmuon;
00613   energy = Muon.energy;
00614   cosg = Muon.cosg;
00615   phig = Muon.phig;
00616 
00617   Nneutron = Muon.Nneutron;
00618   Nelectron = Muon.Nelectron;
00619   Ngamma = Muon.Ngamma;
00620 
00621   double* pold;
00622   double* pnew;
00623 
00624   Eneutron = new double[Nneutron];
00625   pold = Muon.Eneutron+Nneutron;
00626   pnew = Eneutron+Nneutron;
00627   while(pnew>Eneutron)*--pnew=*--pold;
00628 
00629   Rneutron = new double[3*Nneutron];
00630   pold = Muon.Rneutron+3*Nneutron;
00631   pnew = Rneutron+3*Nneutron;
00632   while(pnew>Rneutron)*--pnew=*--pold;
00633 
00634   Tneutron = new double[Nneutron];
00635   pold = Muon.Tneutron+Nneutron;
00636   pnew = Tneutron+Nneutron;
00637   while(pnew>Tneutron)*--pnew=*--pold;
00638 
00639   Eelectron = new double[Nelectron];
00640   pold = Muon.Eelectron+Nelectron;
00641   pnew = Eelectron+Nelectron;
00642   while(pnew>Eelectron)*--pnew=*--pold;
00643 
00644   Relectron = new double[3*Nelectron];
00645   pold = Muon.Relectron+3*Nelectron;
00646   pnew = Relectron+3*Nelectron;
00647   while(pnew>Relectron)*--pnew=*--pold;
00648 
00649   Telectron = new double[Nelectron];
00650   pold = Muon.Telectron+Nelectron;
00651   pnew = Telectron+Nelectron;
00652   while(pnew>Telectron)*--pnew=*--pold;
00653 
00654   Egamma = new double[Ngamma];
00655   pold = Muon.Egamma+Ngamma;
00656   pnew = Egamma+Ngamma;
00657   while(pnew>Egamma)*--pnew=*--pold;
00658 
00659   Rgamma = new double[3*Ngamma];
00660   pold = Muon.Rgamma+3*Ngamma;
00661   pnew = Rgamma+3*Ngamma;
00662   while(pnew>Rgamma)*--pnew=*--pold;
00663 
00664   Tgamma = new double[Ngamma];
00665   pold = Muon.Tgamma+Ngamma;
00666   pnew = Tgamma+Ngamma;
00667   while(pnew>Tgamma)*--pnew=*--pold;
00668 
00669   Weight = Muon.Weight;
00670 }    
00671 
00672 MuonPropagator& MuonPropagator::operator=(const MuonPropagator& rhs){
00673 
00674   if(this == &rhs)return *this;
00675 
00676   Rmaxgen = rhs.Rmaxgen;
00677 
00678   Nmuon = rhs.Nmuon;
00679   energy = rhs.energy;
00680   cosg = rhs.cosg;
00681   phig = rhs.phig;
00682 
00683   Nneutron = rhs.Nneutron;
00684   Nelectron = rhs.Nelectron;
00685   Ngamma = rhs.Ngamma;
00686 
00687   double* pold;
00688   double* pnew;
00689 
00690   delete[] Eneutron;
00691   Eneutron = new double[Nneutron];
00692   pold = rhs.Eneutron+Nneutron;
00693   pnew = Eneutron+Nneutron;
00694   while(pnew>Eneutron)*--pnew=*--pold;
00695 
00696   delete[] Rneutron;
00697   Rneutron = new double[3*Nneutron];
00698   pold = rhs.Rneutron+3*Nneutron;
00699   pnew = Rneutron+3*Nneutron;
00700   while(pnew>Rneutron)*--pnew=*--pold;
00701 
00702   delete[] Tneutron;
00703   Tneutron = new double[Nneutron];
00704   pold = rhs.Tneutron+Nneutron;
00705   pnew = Tneutron+Nneutron;
00706   while(pnew>Tneutron)*--pnew=*--pold;
00707 
00708   delete[] Eelectron;
00709   Eelectron = new double[Nelectron];
00710   pold = rhs.Eelectron+Nelectron;
00711   pnew = Eelectron+Nelectron;
00712   while(pnew>Eelectron)*--pnew=*--pold;
00713 
00714   delete[] Relectron;
00715   Relectron = new double[3*Nelectron];
00716   pold = rhs.Relectron+3*Nelectron;
00717   pnew = Relectron+3*Nelectron;
00718   while(pnew>Relectron)*--pnew=*--pold;
00719 
00720   delete[] Telectron;
00721   Telectron = new double[Nelectron];
00722   pold = rhs.Telectron+Nelectron;
00723   pnew = Telectron+Nelectron;
00724   while(pnew>Telectron)*--pnew=*--pold;
00725 
00726   delete[] Egamma;
00727   Egamma = new double[Ngamma];
00728   pold = rhs.Egamma+Ngamma;
00729   pnew = Egamma+Ngamma;
00730   while(pnew>Egamma)*--pnew=*--pold;
00731 
00732   delete[] Rgamma;
00733   Rgamma = new double[3*Ngamma];
00734   pold = rhs.Rgamma+3*Ngamma;
00735   pnew = Rgamma+3*Ngamma;
00736   while(pnew>Rgamma)*--pnew=*--pold;
00737 
00738   delete[] Tgamma;
00739   Tgamma = new double[Ngamma];
00740   pold = rhs.Tgamma+Ngamma;
00741   pnew = Tgamma+Ngamma;
00742   while(pnew>Tgamma)*--pnew=*--pold;
00743 
00744   Weight = rhs.Weight;
00745 
00746   return *this;
00747 }
00748 
00749 double* MuonPropagator::Intersection(double x1, double y1, double z1,
00750                                      double x2, double y2, double z2,
00751                                      double x3, double y3, double z3, double r){
00752 
00753   // x1,y1,z1  P1 coordinates (point of line)
00754   // x2,y2,z2  P2 coordinates (point of line)
00755   // x3,y3,z3, r  P3 coordinates and radius (sphere)
00756   // x,y,z   intersection coordinates
00757   //
00758   // This function returns a pointer array which first index indicates
00759   // the number of intersection point, followed by coordinate pairs.
00760 
00761   double x , y , z;
00762   double a, b, c, mu, i ;
00763   // array containing number of points and its coordinates
00764   double* p;
00765   p = (double*) malloc(7*sizeof(double));
00766 
00767   a = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1);
00768   b = 2*((x2-x1)*(x1-x3) + (y2-y1)*(y1-y3) + (z2-z1)*(z1-z3));
00769   c = (x3*x3 + y3*y3 + z3*z3 + x1*x1 + y1*y1 + z1*z1 - 
00770        2*(x3*x1 + y3*y1 + z3*z1) - r*r);
00771   i = b*b - 4*a*c;
00772   //cout << "intersection " << i << endl;
00773 
00774   if(i < 0.0){
00775     // no intersection
00776     p[0] = 0.0;
00777     return(p);
00778   }
00779   if(i ==0.0){
00780     // one intersection
00781     p[0] = 1.0;
00782 
00783     mu = -b/(2*a) ;
00784     p[1] = x1 + mu*(x2-x1);
00785     p[2] = y1 + mu*(y2-y1);
00786     p[3] = z1 + mu*(z2-z1);
00787     return(p);
00788   }
00789   if(i>0.0){
00790     // two intersections
00791     p[0] = 2.0;
00792 
00793     // first intersection
00794     mu = (-b + sqrt(b*b - 4*a*c))/(2*a);
00795     p[1] = x1 + mu*(x2-x1);
00796     p[2] = y1 + mu*(y2-y1);
00797     p[3] = z1 + mu*(z2-z1);
00798 
00799     // second intersection
00800     mu = (-b - sqrt(b*b - 4*a*c))/(2*a);
00801     p[4] = x1 + mu*(x2-x1);
00802     p[5] = y1 + mu*(y2-y1);
00803     p[6] = z1 + mu*(z2-z1);
00804 
00805     return(p);
00806   }
00807 }
00808 
00809 double* MuonPropagator::Rotate(char axis,double angle,
00810                                double x1, double y1, double z1){
00811 
00812   // axis      axis about which to rotate
00813   // angle     angle of rotation in radians
00814   // x1,y1,z1  cartesian coordinates of point to rotate
00815 
00816   double x2,y2,z2;
00817   double * p;
00818   p = (double*) malloc(3*sizeof(double));
00819 
00820   if(axis == 'X'){
00821     x2 = x1;
00822     y2 = cos(angle)*y1-sin(angle)*z1;
00823     z2 = sin(angle)*y1+cos(angle)*z1;
00824   }
00825   else if(axis == 'Y'){
00826     x2 = cos(angle)*x1+sin(angle)*z1;
00827     y2 = y1;
00828     z2 = -sin(angle)*x1+cos(angle)*z1;
00829   }
00830   else if(axis == 'Z'){
00831     x2 = cos(angle)*x1-sin(angle)*y1;
00832     y2 = sin(angle)*x1+cos(angle)*y1;
00833     z2 = z1;
00834   }
00835   else{
00836     cout << "ERROR: Unknown axis " << axis 
00837          << ".  Axis of rotation must be 'X', 'Y', or 'Z'." << endl;
00838     x2 = 0;
00839     y2 = 0;
00840     z2 = 0;
00841   }
00842 
00843   p[0] = x2;
00844   p[1] = y2;
00845   p[2] = z2;
00846 
00847   return(p);
00848 }
00849 double MuonPropagator::RadCorr(double t,double tup){
00850 
00851   if(t<=0 || tup<=0 || t<=tup) return 0;
00852   //
00853   double y = 1/(2+t);
00854   //
00855   return log(t*tup)
00856     -tup*tup*(t+2*tup-3*tup*tup*y/2
00857               -(tup-exp(3*log(tup))/3)*y*y
00858               -(tup*tup/2
00859                 -t*exp(3*log(tup))/2
00860                 +exp(4*log(tup))/4)*exp(3*log(y)));
00861 }
00862 
00863 float MuonPropagator::IsotopeDistance(const float& r){
00864 
00865   // from Hagner et al, Astropart Phys 14, 37 (2000)
00866   float phi = 1/166.0*exp(-0.0403*r*r)+1/1223.0*exp(-0.098*r);
00867   return phi;
00868 }

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