#include #include #include #include #include #include #include #include #include #include "Garfield/ComponentGrid.hh" #include "Garfield/MediumMagboltz.hh" #include "Garfield/Sensor.hh" #include "Garfield/AvalancheMicroscopic.hh" #include "Garfield/AvalancheMC.hh" #include "Garfield/Random.hh" #include "Garfield/ComponentAnalyticField.hh" #include "Garfield/RandomEngineRoot.hh" using namespace Garfield; enum class BeamShape { Square, Circle }; int main(int argc, char *argv[]) { //const int seed = 123456; //Garfield::RandomEngineRoot randomEngine(seed); //Garfield::Random::SetEngine(randomEngine); TApplication app("app", &argc, argv); auto start = std::chrono::high_resolution_clock::now(); const bool debug = false; const bool storeEndpoints = false; // -- Gas parameters -- // const double temperature = 293.15; // [K] const double pressure = 760.; // [Torr] const double fN2 = 77.; // [%] const double fO2 = 21.; // [%] const double fAr = 1.; // [%] const double fH2O = 1.; // [%] // -- Chamber geometry -- // const double xChamberGap = 0.1; // [cm] const double yChamberLength = 2.; // [cm] const double zChamberLength = 2.; // [cm] const double highVoltage = 500.; // [V] // -- Pulse parameters -- // const int nPairs = 1e4; // [1] const double tStartPulse = 0.0; // [ns] start of pulse const double tEndPulse = 0.0; // [ns] end of pulse 10 μs of Protheus ONE const double beamCrossSection = 1.; // [cm^2] BeamShape shape = BeamShape::Square; // Beam shape: Square or Circle // -- Drift parameters -- // const double tStartSimu = 0.; const double tEndSimu = 4600; // [ns] end of simulation (no more overlap region) const double dt = 50.; // [ns] density map update time const bool withIonRecombination = true; const bool withDensityMap = true; const bool withIonDiffusion = true; const double alpha = 1.72e-15; // [cm^3/ns] ion-ion recombination coefficient // -- Grid parameters -- // const double sigma = 0.0107566; // [cm] const double pad = 3 * sigma; const int nx = 20, ny = 20, nz = 20; double densityTarget; // [cm^-3] for (int i = 1; i < argc; i++) { std::string arg = argv[i]; if (arg == "--density" && i + 1 < argc) { densityTarget = std::stod(argv[++i]); } else if (arg == "--help") { std::cout << "Usage: ./AskedDensity [options]\n" << "Options:\n" << " --density in [cm^-3]\n"; return 0; } } struct P { double x, y, z, t; size_t w; }; MediumMagboltz gas; gas.SetComposition("O2", fO2, "Ar", fAr, "H2O", fH2O, "N2", fN2); gas.SetTemperature(temperature); // [K] gas.SetPressure(pressure); // [Torr] gas.LoadIonMobility("IonMobility_N2+_N2.txt"); gas.LoadNegativeIonMobility("NegIonMobility_O2-_air.txt"); gas.Initialise(true); ComponentAnalyticField cmp; cmp.SetMedium(&gas); cmp.AddPlaneX(0, 0, "cathode"); cmp.AddPlaneX(xChamberGap, highVoltage, "anode"); const double side = std::sqrt(beamCrossSection); const double xMinGrid = 0., xMaxGrid = xChamberGap; const double yMinGrid = -(side/2. + pad); const double yMaxGrid = (side/2. + pad); const double zMinGrid = -(side/2. + pad); const double zMaxGrid = (side/2. + pad); ComponentGrid grid; grid.SetMesh(nx, ny, nz, xMinGrid, xMaxGrid, yMinGrid, yMaxGrid, zMinGrid, zMaxGrid); grid.SetMedium(&gas); grid.SetUniformElectricField(0., 0., 0.); //grid.SaveElectricField(&grid, "field_map.txt","XYZ"); if (debug) { unsigned int nxx, nyy, nzz; double xmin, xmax, ymin, ymax, zmin, zmax; if (grid.GetMesh(nxx, nyy, nzz, xmin, xmax, ymin, ymax, zmin, zmax)) { std::cout << "Mesh dimensions:" << std::endl; std::cout << " nx = " << nxx << ", ny = " << nyy << ", nz = " << nzz << std::endl; std::cout << "Bounding box:" << std::endl; std::cout << " xmin = " << xmin << ", xmax = " << xmax << std::endl; std::cout << " ymin = " << ymin << ", ymax = " << ymax << std::endl; std::cout << " zmin = " << zmin << ", zmax = " << zmax << std::endl; } else { std::cerr << "Erreur : GetMesh a échoué." << std::endl; } } Sensor sensor; sensor.AddComponent(&cmp); sensor.AddComponent(&grid); sensor.SetArea(0, -yChamberLength/2, -zChamberLength/2, xChamberGap, yChamberLength/2, zChamberLength/2); std::vector

electrons; std::vector

ions; std::vector

negions; int nAttaElectrons = 0; int nRecombIons = 0; int nRecombNegions = 0; const size_t multiplicity = densityTarget * beamCrossSection * xChamberGap / nPairs; // multiplicity of pairs created for (int i = 0; i < nPairs; i++) { double t = tStartPulse + (static_cast(i) / (nPairs - 1)) * (tEndPulse - tStartPulse); double x0, y0, z0; switch (shape) { case BeamShape::Square: { x0 = Garfield::RndmUniform() * xChamberGap; y0 = (Garfield::RndmUniform() - 0.5) * sqrt(beamCrossSection); z0 = (Garfield::RndmUniform() - 0.5) * sqrt(beamCrossSection); break; } case BeamShape::Circle: { const double CrossSectionRadius = sqrt(beamCrossSection / Pi); x0 = Garfield::RndmUniform() * xChamberGap; double r = CrossSectionRadius * sqrt(Garfield::RndmUniform()); double theta = TwoPi * Garfield::RndmUniform(); y0 = r * cos(theta); z0 = r * sin(theta); break; } } electrons.push_back(P{x0, y0, z0, t, multiplicity}); ions.push_back(P{x0, y0, z0, t, multiplicity}); } // -- Simulation -- // // Create buffers const int T = omp_get_max_threads(); std::vector> electrons_b(T); std::vector> ions_b(T); std::vector> negions_b(T); double t = tStartSimu; while (t < tEndSimu) { for (int k=0;k duration = end - start; auto now = std::chrono::system_clock::now(); std::time_t currentTime = std::chrono::system_clock::to_time_t(now); std::tm localTime = *std::localtime(¤tTime); // -- Print and save results -- // std::ostringstream oss; oss << "Duration : " << duration.count() << " seconds" << std::endl; oss << "Number of threads used: " << T << std::endl; oss << "Number of pairs simulated: " << nPairs << std::endl; oss << "Multiplicity: " << multiplicity << std::endl; oss << "Ionisation density: " << densityTarget << " [cm^-3]" << std::endl; oss << "Number of e- attached: " << nAttaElectrons << std::endl; oss << "Number of i+ recombined: " << nRecombIons << std::endl; oss << "Number of i- recombined: " << nRecombNegions << std::endl; oss << "FEF: " << 1 - ((double)nAttaElectrons / nPairs) << std::endl; oss << "CCE: " << 1 - ((double)nRecombIons / nPairs) << std::endl; oss << "--------------------------------" << std::endl; oss << "Time : " << std::put_time(&localTime, "%H:%M:%S") << std::endl; oss << "Duration : " << duration.count() << " seconds" << std::endl; std::cout << oss.str(); app.Run(); return 0; } // OMP_NUM_THREADS=6 ./AskedDensity_mt --density 1e10