The magnitudes of induced signal from DriftLineRKF, AvalancheMC and AvalancheMicroscopic class are not consistent

For same case, DriftLineRKF AvalancheMC and AvalancheMicroscopic classes are used to drift electrons and ions, but the magnitudes of induced signal are not consistent.

the signal from DriftLineRKF class is:

the signal from AvalancheMC class is:

and the signal from AvalancheMicroscopic class is:

the related files are attached:

Alpha_in_Ar_90_CH4_10_1bar.txt (7.3 KB)

AvalancheMicroscopic.C (4.4 KB)

AvalancheMC.C (4.0 KB)

DriftLineRKF.C (3.9 KB)

somethings are wrong with the codes or it is normal?

sorry, the gas file is wrong, here is the right one:

Ar90_CH4_10_1bar.gas.txt (73.1 KB)

Dear @newconcept1979 ,

Just for to get more information so we can more effectively help you. The three signals you show are from three independent events: one using DriftLineRKF, AvalancheMC, and AvalancheMicroscopic?

Kind regards,

Djunes

@djjansse, there are 3 c++ source files i uploaded, DriftLineRKF.C, AvalancheMC.C and AvalancheMicroscopic.C, they are independent.

in DriftLineRKF.C file, DriftLineRKF class is used to drift electrons and ions;

in AvalancheMC.C file, AvalancheMC class is used to drift electrons and ions;

in AvalancheMicroscopic.C file, AvalancheMicroscopic class is used to drift electrons and ions.

but they are for the same case.

@djjansse, the code files of DriftLineRKF.C AvalancheMC.C and AvalancheMicroscopic.C are for the same case, so most codes are same:

TApplication app("app", &argc, argv);
 
  // Make a gas medium.
  MediumMagboltz gas;
  gas.LoadGasFile("Ar90_CH4_10_1bar.gas");
  auto installdir = std::getenv("GARFIELD_INSTALL");
  if (!installdir) {
    std::cerr << "GARFIELD_INSTALL variable not set.\n";
    return 1;
  }
  const std::string path = installdir;
  gas.LoadIonMobility(path + "/share/Garfield/Data/IonMobility_Ar+_Ar.txt");

  // Make a component with analytic electric field.
  ComponentAnalyticField cmp;
  cmp.SetMedium(&gas);
  // Wire radius [cm]
  const double rWire = 25.e-4;
  // Outer radius of the tube [cm]
  const double rTube = 0.71;
  // Voltages
  const double vWire = 1500;
  const double vTube = 0.;
  // Add the wire in the centre.
  cmp.AddWire(0, 0, 2 * rWire, vWire, "s");
  // Add the tube.
  cmp.AddTube(rTube, vTube, 0);

  // Make a sensor.
  Sensor sensor;
  sensor.AddComponent(&cmp);
  sensor.AddElectrode(&cmp, "s");
  const double tstep = 2.;
  const double tmin = -0.5 * tstep;
  const unsigned int nbins = 1000;
  sensor.SetTimeWindow(tmin, tstep, nbins);
  
  TCanvas *cDrift=new TCanvas("","",1200,1200);

  ViewDrift driftview;
  driftview.SetCanvas(cDrift);

  TrackHeed track;
  track.SetParticle("electron");
  track.SetKineticEnergy(1.e11);
  track.SetSensor(&sensor);
  track.EnablePlotting(&driftview);

  const double rTrack = 0.3;
  const double x0 = rTrack;
  const double y0 = -sqrt(rTube * rTube - rTrack * rTrack);
  const unsigned int nTracks = 1;

for DriftLineRKF.C file, the DriftLineRKF class is used to transport electrons and ions, the codes are:

  // RKF integration.
  DriftLineRKF drift(&sensor);
  drift.EnablePlotting(&driftview);
  drift.EnableSignalCalculation();
  drift.EnableIonTail();
  
  for (unsigned int j = 0; j < nTracks; ++j) {
    sensor.ClearSignal();
    track.NewTrack(x0, y0, 0, 0, 0, 1, 0);
    for (const auto& cluster : track.GetClusters()) {
      for (const auto&electrn:cluster.electrons) {
          drift.DriftElectron(electrn.x, electrn.y, electrn.z, electrn.t);
          double ne,ni;
          drift.GetAvalancheSize(ne,ni);
          std::cout<<"ne==   "<<ne<<"ni==   "<<ni<<std::endl;
      }
      for(const auto&ion:cluster.ions)
      {
          drift.DriftIon(ion.x,ion.y,ion.z,ion.t);
      }
    } 
      cmp.PlotCell(cDrift);
      constexpr bool twod = true;
      constexpr bool drawaxis = false;
      driftview.Plot(twod, drawaxis);
      cDrift->Print("drift.png");
    }  
  TCanvas* cS = new TCanvas("cS", "", 1200, 1200);  
  sensor.PlotSignal("s", cS);
  cS->Print("signal.png");

for AvalancheMC.C file, the AvalancheMC class is used to transport electrons and ions, the codes are:

  int status;
  double xx,yy,zz,tt,ee,dxx,dyy,dzz;
  double xx1,yy1,zz1,tt1;
  for (unsigned int j = 0; j < nTracks; ++j) {
    sensor.ClearSignal();
    track.NewTrack(x0, y0, 0, 0, 0, 1, 0);
    
    for (const auto& cluster : track.GetClusters()) {            
      for(int jj=0;jj<cluster.electrons.size();++jj)
        {
          xx=cluster.electrons[jj].x;
          yy=cluster.electrons[jj].y;
          zz=cluster.electrons[jj].z;
          tt=cluster.electrons[jj].t;
          mc.AvalancheElectron(xx,yy,zz,tt);
          std::size_t ne,ni;
          mc.GetAvalancheSize(ne,ni);     
          std::cout<<"ne==   "<<ne<<" ||| "<<"ni==   "<<ni<<std::endl;
        }
        for(const auto&ion:cluster.ions)
        {
          mc.DriftIon(ion.x,ion.y,ion.z,ion.t);
        }          
    }
  }
  double x1,y1,z1,t1,x2,y2,z2,t2;
  std::size_t num_tracks;
  num_tracks=mc.GetNumberOfElectronEndpoints();
  for(std::size_t i=0;i<num_tracks;i++)
  {
      mc.GetElectronEndpoint(i,x1,y1,z1,t1,x2,y2,z2,t2,status);
      mc.DriftIon(x1,y1,z1,t1);
  } 
      cmp.PlotCell(cDrift);
      constexpr bool twod = true;
      constexpr bool drawaxis = false;
      driftview.Plot(twod, drawaxis);
      cDrift->Print("drift.png");
 
  TCanvas* cS = new TCanvas("cS", "", 1200, 1200);  
  sensor.PlotSignal("s", cS);
  cS->Print("signal.png");

for AvalancheMicroscopic.C file, the AvalancheMicroscopic class is used to transport electrons and ions, the codes are:

AvalancheMicroscopic micro;
  micro.SetSensor(&sensor);
  micro.EnableSignalCalculation();
  micro.EnablePlotting(&driftview);

  AvalancheMC mc;
  mc.SetSensor(&sensor);
  mc.EnableSignalCalculation();
  mc.EnablePlotting(&driftview);
 
  for (unsigned int j = 0; j < nTracks; ++j) {
    sensor.ClearSignal();
    track.NewTrack(x0, y0, 0, 0, 0, 1, 0);
    for (const auto& cluster : track.GetClusters()) {
      for (const auto& electron : cluster.electrons) {
        // micro.DriftElectron(electron.x, electron.y, electron.z, electron.t,electron.e);
        micro.AvalancheElectron(electron.x, electron.y, electron.z, electron.t,electron.e);
        int ne,ni;
        micro.GetAvalancheSize(ne,ni);
        std::cout<<"ne==   "<<ne<<" ||| "<<"ni==   "<<ni<<std::endl;
      }
      for(const auto&ion:cluster.ions)
      {
          mc.DriftIon(ion.x,ion.y,ion.z,ion.t);
      }
    }
    double x1,y1,z1,t1,e1,x2,y2,z2,t2,e2;
    int status;
    int num_electrons=micro.GetNumberOfElectronEndpoints();
    for(int ii=0;ii<num_electrons;++ii)
    {
        micro.GetElectronEndpoint(ii,x1,y1,z1,t1,e1,x2,y2,z2,t2,e2,status);
        mc.DriftIon(x1,y1,z1,t1);
    }
      cmp.PlotCell(cDrift);
      constexpr bool twod = true;
      constexpr bool drawaxis = false;
      driftview.Plot(twod, drawaxis);
      cDrift->Print("drift.png");
    }  
  TCanvas* cS = new TCanvas("cS", "", 1200, 1200);  
  sensor.PlotSignal("s", cS);
  cS->Print("signal.png");

but the induced electric currents are different, the results have attached.

Dear @newconcept1979,

Unless I am missing something, you are looking at three independent events inside your detector that will have a different primary ionization pattern and different gain development for those primary charges. If you run one of the scripts a couple of times it will give a different induced current as well, reflecting the stochastic nature of the processes involved.

If you’d like to do a comparison, I would recomend looking at the induced current averaged over many events.

Kind regards,

Djunes

@djjansse, thanks for your reply, but i have 2 question?

  1. The same incident particle (an electron in this case) and the same component, why the ionization patterns are different?
  2. The mean currents will be consistent if many events are involved?

Dear @newconcept1979,

It is inherently a statistical process governed by a probability distributions dictating the number of primary clusters and the cluster size. Then there is the avalanche development that is Polya distributed. So even though it is the same conditions, the events will differ. On average you should get the same outcome.

However, I do see an unexpected difference in the ion tails between the different methods.

Kind regards,

Djunes

@djjansse, as your opinion, the magnitudes of the signals have big difference by different events , in the pulse amplitude spectrum measured, the FWHM of the energy peak will be large, this seems not the fact.