#include #include #include #include #include #include "Garfield/ComponentAnsys123.hh" #include "Garfield/ViewField.hh" #include "Garfield/ViewFEMesh.hh" #include "Garfield/MediumMagboltz.hh" #include "Garfield/Sensor.hh" #include "Garfield/AvalancheMicroscopic.hh" #include "Garfield/AvalancheMC.hh" #include "Garfield/Random.hh" #include "Garfield/Plotting.hh" using namespace Garfield; int main(int argc, char * argv[]) { TApplication app("app", &argc, argv); plottingEngine.SetDefaultStyle(); const bool debug = true; // Load the field map. ComponentAnsys123 fm; fm.Initialise("ELIST.lis", "NLIST.lis", "MPLIST.lis", "PRNSOL.lis", "mm"); fm.EnableMirrorPeriodicityX(); fm.EnableMirrorPeriodicityY(); fm.PrintRange(); // Dimensions of the GEM [cm] constexpr double pitch = 0.014; ViewField fieldView; constexpr bool plotField = true; if (plotField) { fieldView.SetComponent(&fm); // Set the normal vector of the viewing plane (xz plane). fieldView.SetPlane(0, -1, 0, 0, 0, 0); // Set the plot limits in the current viewing plane. fieldView.SetArea(-0.5 * pitch, -0.02, 0.5 * pitch, 0.02); fieldView.SetVoltageRange(-160., 160.); TCanvas* cf = new TCanvas("cf", "", 600, 600); cf->SetLeftMargin(0.16); fieldView.SetCanvas(cf); fieldView.PlotContour(); } // Setup the gas. MediumMagboltz gas; gas.SetComposition("fr", 80., "iC4H10", 20.); gas.SetTemperature(20); gas.SetPressure(760.); gas.Initialise(true); // done by me for electron energy gas.SetMaxElectronEnergy(200.); // Set the Penning transfer efficiency. constexpr double rPenning = 0.51; constexpr double lambdaPenning = 0.; gas.EnablePenningTransfer(rPenning, lambdaPenning, "fr"); // Load the ion mobilities. const std::string path = getenv("GARFIELD_HOME"); gas.LoadIonMobility(path + "/Data/IonMobility_Fr+_Fr.txt"); // Associate the gas with the corresponding field map material. const unsigned int nMaterials = fm.GetNumberOfMaterials(); for (unsigned int i = 0; i < nMaterials; ++i) { const double eps = fm.GetPermittivity(i); if (eps == 1.) fm.SetMedium(i, &gas); } fm.PrintMaterials(); // Create the sensor. Sensor sensor; sensor.AddComponent(&fm); sensor.SetArea(-5 * pitch, -5 * pitch, -0.01, 5 * pitch, 5 * pitch, 0.025); AvalancheMicroscopic aval; aval.SetSensor(&sensor); AvalancheMC drift; drift.SetSensor(&sensor); drift.SetDistanceSteps(2.e-4); ViewDrift driftView; constexpr bool plotDrift = true; if (plotDrift) { aval.EnablePlotting(&driftView); drift.EnablePlotting(&driftView); } const int nEvents = 10; for (int i = nEvents; i--;) { if (debug || i % 10 == 0) std::cout << i << "/" << nEvents << "\n"; // Randomize the initial position. const double x0 = -0.5 * pitch + RndmUniform() * pitch; const double y0 = -0.5 * pitch + RndmUniform() * pitch; const double z0 = 0.02; const double t0 = 0.; const double e0 = 0.1; aval.AvalancheElectron(x0, y0, z0, t0, e0, 0., 0., 0.); int ne = 0, ni = 0; aval.GetAvalancheSize(ne, ni); const int np = aval.GetNumberOfElectronEndpoints(); double xe1, ye1, ze1, te1, e1; double xe2, ye2, ze2, te2, e2; double xi1, yi1, zi1, ti1; double xi2, yi2, zi2, ti2; int status; for (int j = np; j--;) { aval.GetElectronEndpoint(j, xe1, ye1, ze1, te1, e1, xe2, ye2, ze2, te2, e2, status); drift.DriftIon(xe1, ye1, ze1, te1); drift.GetIonEndpoint(0, xi1, yi1, zi1, ti1, xi2, yi2, zi2, ti2, status); } } if (plotDrift) { TCanvas* cd = new TCanvas(); constexpr bool plotMesh = true; if (plotMesh) { ViewFEMesh* meshView = new ViewFEMesh(); meshView->SetArea(-2 * pitch, -2 * pitch, -0.02, 2 * pitch, 2 * pitch, 0.02); meshView->SetCanvas(cd); meshView->SetComponent(&fm); // x-z projection. meshView->SetPlane(0, -1, 0, 0, 0, 0); meshView->SetFillMesh(true); meshView->SetColor(0, kGray); // Set the color of the kapton. meshView->SetColor(2, kYellow + 3); meshView->EnableAxes(); meshView->SetViewDrift(&driftView); meshView->Plot(); } else { driftView.SetPlane(0, -1, 0, 0, 0, 0); driftView.SetArea(-2 * pitch, -0.02, 2 * pitch, 0.02); driftView.SetCanvas(cd); constexpr bool twod = true; driftView.Plot(twod); } } app.Run(kTRUE); }