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

Generated on Mon Dec 27 11:10:13 2004 for ReactorFsim by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002