Advertisement
phystota

excitation_radiative_decay_added

Apr 19th, 2025
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 43.76 KB | None | 0 0
  1. #include <iostream>
  2. #include <random>
  3. #include <fstream>
  4. #include <assert.h>
  5.  
  6. #include <math.h>
  7. #include <time.h>
  8. #include <iomanip>  // For std::fixed and std::setprecision
  9.  
  10. #include <algorithm>  // For std::shuffle
  11. #include <numeric>    // For std::iota
  12.  
  13. //physical constants
  14.  
  15. #define m_e 9.1093837E-31 // electron mass in kg
  16. #define M_n 6.6464731E-27 // Helium atom mass
  17. #define k_b 1.380649E-23 // Boltzmann constant
  18. #define q 1.602176634E-19 // elementary charge    - eV -> J transfer param
  19. #define Coulomb_log 15.87 // Coulomb logarithm
  20. #define epsilon_0 8.854188E-12 // Vacuum permittivity
  21. #define Coulomb_const pow(q,4)/(pow(4.0*M_PI*epsilon_0,2)) // e^4/(4*pi*eps0)^2
  22. #define thresh1 19.82 // threshold energy excitation tripet state
  23. #define thresh2 20.61 // threshold energy excitation singlet state
  24. #define tau_singlet 0.0195
  25.  
  26. // simulation parameters
  27.  
  28. #define n_e 50000
  29. // #define N_He 1000000 // Helium neutrals number
  30. #define T_n 2.0 // Helium neutral temperature in eV
  31. #define T_e 5.0    // electron Maxwell initial distribution
  32. #define Emin 0.0
  33. #define Emax 3000.0
  34. #define Volume 1.0E-12 // Volume to calculate netral density and collision frequency
  35. #define time 1.0E-3 // 500 microsec time to equalibrate the system
  36. #define dopant 1.0E-5 // addition to avoid zero
  37. #define E_reduced 0.0 // constant electrin field along z-axis
  38.  
  39. #define bin_width 0.05 // keep energy step ~ this to maintain cross-section clarity (Ramsauer minimum etc)
  40. #define N ( (int)((Emax-Emin)/bin_width) + 1) // add 1 to include E_max if needed?
  41.  
  42. // handling final energy bin
  43.  
  44. #define bin_width_smooth 0.05 // energy bin for smooth final distribution
  45. #define N_smooth ( (int)((Emax-Emin)/bin_width_smooth) )
  46.  
  47.  
  48.  
  49. double solve_A(double s) { // Netwon method solver
  50.  
  51.     if (s > 3) {
  52.         return 3*exp(-s);
  53.     }
  54.     if (s < 0.01) {
  55.         return 1.0/s;
  56.     }
  57.    
  58.     double A0 = 0.01; // initial guess
  59.     double A = A0;  //starting with initial guess
  60.     double tol = 1.0E-7; // accuracy
  61.  
  62.              
  63.     for (int i = 0; i < 1000; i++){
  64.  
  65.         double tanhA = tanh(A);
  66.         // Avoid division by an extremely small tanh(A)
  67.         if (fabs(tanhA) < 1e-12) {
  68.             std::cerr << "tanh(A) too small, returning fallback at iteration " << i << "\n";
  69.             return 1.0E-7;
  70.         }        
  71.  
  72.         double f = 1.0 / tanhA - 1.0 / A - exp(-s);
  73.         if (fabs(f) < tol)
  74.             break;
  75.  
  76.         double sinhA = sinh(A);
  77.         if (fabs(sinhA) < 1e-12) {
  78.             std::cerr << "sinh(A) too small, returning fallback at iteration " << i << "\n";
  79.             return 1.0E-5;
  80.         }
  81.  
  82.         double dfdA = -1.0/(sinh(A)*sinh(A)) + 1.0/(A*A);
  83.  
  84.         // Check if derivative is too close to zero to avoid huge updates
  85.         if (fabs(dfdA) < 1e-12) {
  86.             std::cerr << "dfdA is too small at iteration " << i << ", returning fallback\n";
  87.             if (s < 0.01) {
  88. //                std::cout << "Small s! Huge A!" << "\n";
  89.                 return 1.0/s;
  90.             }
  91.             if (s > 3) {
  92.                 return 3.0*exp(-s);
  93.             }
  94.         }        
  95.  
  96.         A -= f/dfdA;
  97.  
  98.         // Early check for numerical issues
  99.         if (std::isnan(A) || std::isinf(A)) {
  100.             std::cerr << "Numerical error detected, invalid A at iteration " << i << "\n";
  101.             return (A > 0) ? 1.0E-5 : -1.0E-5;  // Fallback value based on sign
  102.         }        
  103.  
  104.  
  105.     }
  106.  
  107.     return A;
  108. }
  109.  
  110. struct Electron {
  111.  
  112.     //velocity components
  113.     double vx = 0.0;
  114.     double vy = 0.0;
  115.     double vz = 0.0;
  116.     //energy in eV
  117.     double energy = 0.0;
  118.     //Collision flag
  119.     bool collided_en = false;
  120.     bool collided_ee = false;
  121.  
  122.     // initializing Maxwell-Boltzmann distribution with T_e
  123.     void initialize(std::mt19937& gen, std::uniform_real_distribution<double>& dis, std::gamma_distribution<double>& maxwell) {
  124.  
  125.         double R = dis(gen);
  126.  
  127.         // velocity angles in spherical coordinates
  128.         double phi = 2*M_PI*dis(gen);
  129.         double cosTheta = 2.0*dis(gen) - 1.0;
  130.         double sinTheta = sqrt(1.0 - cosTheta*cosTheta);
  131.  
  132.            
  133.         energy = maxwell(gen); // neutrals energies sampled as Maxwell distribution in eV
  134.            
  135.         double speed = sqrt(2*energy*q/m_e);
  136.  
  137.         //velocity components of neutrals in m/s
  138.         vx = speed * sinTheta * cos(phi);
  139.         vy = speed * sinTheta * sin(phi);
  140.         vz = speed * cosTheta;
  141.     }
  142.  
  143.  
  144. };
  145.  
  146. struct CrossSection {
  147.     double energy;
  148.     double sigma;
  149. };
  150.  
  151. double interpolate (double energy, const std::vector<CrossSection>& CS) {
  152.  
  153.  
  154.     if (energy < CS.front().energy) {
  155. //        std::cout << " required energy value lower than range of cross-section data at energy: " << energy << "\n";
  156.         return 0.0;
  157.     }
  158.     if (energy > CS.back().energy) {
  159. //        std::cout << " required energy value higher than range of cross-section data" << "\n";
  160.         return 0.0;        
  161.     }
  162.  
  163.     int step = 0;  
  164.         while (step < CS.size() && energy > CS[step].energy) {
  165.             step++;
  166.         }
  167.  
  168.     double k = (CS[step].sigma - CS[step-1].sigma)/(CS[step].energy - CS[step-1].energy);
  169.     double m = CS[step].sigma - k*CS[step].energy;
  170.    
  171.     return k*energy + m;
  172. }
  173.  
  174.  
  175. struct NeutralParticle {
  176.  
  177.     double energy = 0.0;
  178.     double vx = 0.0;
  179.     double vy = 0.0;
  180.     double vz = 0.0;
  181.  
  182.     void initialize(std::mt19937& gen, std::uniform_real_distribution<double>& dis, std::gamma_distribution<double>& maxwell) {
  183.  
  184.         double R = dis(gen);
  185.  
  186.         // velocity angles in spherical coordinates
  187.         double phi = 2*M_PI*dis(gen);
  188.         double cosTheta = 2.0*dis(gen) - 1.0;
  189.         double sinTheta = sqrt(1.0 - cosTheta*cosTheta);
  190.  
  191.            
  192.         energy = maxwell(gen); // neutrals energies sampled as Maxwell distribution in eV
  193.            
  194.         double speed = sqrt(2*energy*q/M_n);
  195.  
  196.         //velocity components of neutrals in m/s
  197.         vx = speed * sinTheta * cos(phi);
  198.         vy = speed * sinTheta * sin(phi);
  199.         vz = speed * cosTheta;
  200.     }
  201.    
  202. };
  203.  
  204. struct Excited_neutral {
  205.  
  206.     double energy;
  207.     double vx;
  208.     double vy;
  209.     double vz;
  210.    
  211. };
  212.  
  213.  
  214.  
  215. int main() {
  216.  
  217.     clock_t start = clock();
  218.  
  219.     int N_He = 10000000;
  220.  
  221.     std::vector<Electron> electrons(n_e); // better to use vector instead of simple array as it's dynamically allocated (beneficial for ionization)
  222. //    std::vector<NeutralParticle> neutrals(N_He); // I don't need a vector of neutrals bcs it's like a backhround in MCC-simulation
  223.  
  224.     std::vector<int> histo_random(N, 0); // initialize N size zero-vector for random (initial) histogram
  225.     std::vector<int> histo_maxwell(N, 0); // initialize N size zero-vector for maxwellian histogram
  226.     std::vector<int> histo_neutral(N, 0); // initialize N size zero-vector for neutral distribution histogram
  227.     std::vector<int> histo_excited(N, 0); // initialize N size zero-vector for excited He distribution histogram
  228.  
  229.     std::vector<double> elastic_vec(N, 0); // precompiled elastic cross-section-energy vector
  230.     std::vector<double> inelastic1_vec(N, 0); // precompiled inelastic(triplet excitation) cross-section-energy vector
  231.     std::vector<double> inelastic2_vec(N, 0); // precompiled inelastic(singlet excitation) cross-section-energy vector    
  232.     std::vector<double> superelastic1_vec(N, 0); // precompiled superelastic(triplet de-excitation) cross-section-energy vector
  233.     std::vector<double> superelastic2_vec(N, 0); // precompiled superelastic(triplet de-excitation) cross-section-energy vector
  234.  
  235.     std::random_device rd;
  236.     std::mt19937 gen(rd());
  237.     std::uniform_real_distribution<double> dis(0.0, 1.0);
  238.     std::gamma_distribution<double> maxwell_neutral(1.5, T_n);
  239.     std::gamma_distribution<double> maxwell_electron(1.5, T_e);
  240.  
  241.     std::ifstream elastic_cs_dat("cross_sections/elastic.dat");
  242.     if (!elastic_cs_dat.is_open()) {
  243.         std::cerr << "Error opening elastic cross-sections file!" << std::endl;
  244.         return 1;
  245.     }    
  246.  
  247.     std::ifstream excitation1_cs_dat("cross_sections/inelastic_triplet.dat");
  248.     if (!excitation1_cs_dat.is_open()) {
  249.         std::cerr << "Error opening inelastic triplet cross-sections file!" << std::endl;
  250.         return 1;
  251.     }
  252.  
  253.     std::ifstream excitation2_cs_dat("cross_sections/inelastic_singlet.dat");
  254.     if (!excitation2_cs_dat.is_open()) {
  255.         std::cerr << "Error opening inelastic singlet cross-sections file!" << std::endl;
  256.         return 1;
  257.     }
  258.  
  259.     // --- starts reading cross section datafiles
  260.  
  261. //-----------------elastic---------------------------//
  262.     std::vector<CrossSection> elastic_CS_temp;
  263.  
  264.     double energy, sigma;
  265.  
  266.     while (elastic_cs_dat >> energy >> sigma) {
  267.         elastic_CS_temp.push_back({energy, sigma});
  268.     }    
  269.     elastic_cs_dat.close();
  270.  
  271.     energy = 0.0;
  272.     sigma = 0.0;
  273. //-----------------triplet excitation---------------------------//
  274.     std::vector<CrossSection> inelastic1_CS_temp;
  275.  
  276.     while (excitation1_cs_dat >> energy >> sigma) {
  277.         inelastic1_CS_temp.push_back({energy, sigma});
  278.     }    
  279.     excitation1_cs_dat.close();    
  280. //-----------------singlet excitation---------------------------//
  281.     energy = 0.0;
  282.     sigma = 0.0;
  283.  
  284.     std::vector<CrossSection> inelastic2_CS_temp;
  285.  
  286.     while (excitation2_cs_dat >> energy >> sigma) {
  287.         inelastic2_CS_temp.push_back({energy, sigma});
  288.     }    
  289.     excitation2_cs_dat.close();    
  290.  
  291.     // --- finish reading cross-section datafiles  
  292.  
  293.     std::ofstream file0("output_files/velocities.dat");    
  294.     std::ofstream file1("output_files/energies.dat");        
  295.     std::ofstream file2("output_files/energies_final.dat");    
  296.     std::ofstream file3("output_files/histo_random.dat");    
  297.     file3 << std::fixed << std::setprecision(10);
  298.    
  299.     std::ofstream file4("output_files/histo_maxwell.dat");
  300.     file4 << std::fixed << std::setprecision(10);          
  301.    
  302.     std::ofstream file5("output_files/neutral_distribution.dat");    
  303.     std::ofstream file6("output_files/E*f(E).dat");    
  304.     std::ofstream file7("output_files/nu_max.dat");
  305.     std::ofstream file8("output_files/electron_mean_energy.dat");
  306.     std::ofstream file9("output_files/nu_elastic_average_initial.dat");
  307.     std::ofstream file10("output_files/nu_inelastic1_average_initial.dat");
  308.     std::ofstream file11("output_files/nu_elastic_average_final.dat");
  309.     std::ofstream file12("output_files/nu_inelastic1_average_final.dat");
  310.     std::ofstream file13("output_files/log_output.dat");  
  311.     std::ofstream file14("output_files/excited_energies.dat");      
  312.     std::ofstream file15("output_files/excited_histo.dat");            
  313.     std::ofstream file_temp("output_files/collision_rates.dat");
  314.     std::ofstream file16("output_files/energy_gain.dat");  
  315.  
  316.     // Initialize all electrons
  317.     for (auto& e : electrons) {
  318.         e.initialize(gen, dis, maxwell_electron);
  319.     }
  320.  
  321.     // precalculate cross-sections for each energy bin
  322.     for (int i = 0; i < N; i++){
  323.         elastic_vec[i] = interpolate(bin_width*(i+0.5), elastic_CS_temp); //elastiuc
  324.         inelastic1_vec[i] = interpolate(bin_width*(i+0.5), inelastic1_CS_temp); //triplet excitation
  325.         inelastic2_vec[i] = interpolate(bin_width*(i+0.5), inelastic2_CS_temp); //singlet excitation
  326.     }
  327.  
  328.     // precalculate superelastic cross-section (triplet -> ground) for each energy bin
  329.     // detailed balance gives: sigma_j_i(E) = (g_i/g_j)*((E+theshold)/E)*sigma_i_j(E+theshold)
  330.     for (int i = 0; i < N; i++){
  331.         double energy = Emin + (i + 0.5) * bin_width;
  332.         int thresh_bin = (int)( (thresh1 - Emin)/bin_width ); // calculating bin for threshold energy
  333.         superelastic1_vec[i] = (1.0/3.0)*((energy + thresh1)/energy)*interpolate(energy + thresh1, inelastic1_CS_temp); // using detailed balance, calculating backward deexcitation cross-section
  334.         superelastic2_vec[i] = (1.0/1.0)*((energy + thresh2)/energy)*interpolate(energy + thresh2, inelastic2_CS_temp);
  335.     }
  336.  
  337.     for (int i = 0; i < n_e; i++){
  338.         file1 << i << " " << electrons.at(i).energy << "\n";
  339.         file0 << i << " " << electrons[i].vx << " " << electrons[i].vy << " " << electrons[i].vz << "\n";
  340.     }
  341.  
  342.     // -----initial electrons energy distribution starts------------////
  343.     for (int i = 0; i < n_e; i++){
  344.         int bin = (int)( (electrons[i].energy - Emin)/bin_width );
  345.         if (bin >=0 && bin < histo_random.size())
  346.             histo_random[bin]++;
  347.     }
  348.  
  349.     for (int i = 0; i < histo_random.size(); i++){
  350.         double bin_center = Emin + (i + 0.5) * bin_width;
  351.         file3 << bin_center << " " <<  static_cast<double>(histo_random[i])/(electrons.size()*bin_width) << "\n"; // this is electron normalized distribution function
  352.     }
  353.  
  354.  
  355.  
  356.     //calculating excited specied population
  357.  
  358.     /*From Boltzman distribution y_k = g_k*exp(-E_k/kT)/norm, where g_k - stat weight of k-state,
  359.     E_k - threshold energy for k-state, norm is a total partition function or normaliztion factor     */
  360.  
  361.     double part_ground = 1.0*exp(-0.0/T_n); // partition function for ground state
  362.     double part_triplet = 3.0*exp(-thresh1/T_n); // partition function for triplet excited state
  363.     double part_singlet = 1.0*exp(-thresh2/T_n); // partition function for singlet excited state
  364.     double part_func_total = part_ground + part_triplet + part_singlet; // total partition function
  365.     double N_trpilet = (part_triplet/part_func_total)*N_He; // population of tripet state
  366.     double N_singlet = (part_singlet/part_func_total)*N_He; // population of singlet state
  367.  
  368.     std::vector<Excited_neutral> exc_1(static_cast<int>(N_trpilet));  // vector to track triplet excited atoms of Helium
  369.     std::vector<Excited_neutral> exc_2(static_cast<int>(N_singlet));  // vector to track singlet excited atoms of Helium    
  370.  
  371.     // adjusting neutrals number:
  372.  
  373.     N_He -= (N_trpilet + N_singlet);
  374.  
  375.     std::cout << N_He << "\n";
  376.  
  377.     // initializing excited species with Maxwellian distribution
  378.  
  379.     for (auto& exc : exc_1) {
  380.     NeutralParticle tmp_neutral;
  381.     tmp_neutral.initialize(gen, dis, maxwell_neutral);
  382.     exc.energy = tmp_neutral.energy;
  383.     exc.vx = tmp_neutral.vx;
  384.     exc.vy = tmp_neutral.vy;
  385.     exc.vz = tmp_neutral.vz;
  386.     }
  387.  
  388.     for (auto& exc : exc_2) {
  389.     NeutralParticle tmp_neutral;
  390.     tmp_neutral.initialize(gen, dis, maxwell_neutral);
  391.     exc.energy = tmp_neutral.energy;
  392.     exc.vx = tmp_neutral.vx;
  393.     exc.vy = tmp_neutral.vy;
  394.     exc.vz = tmp_neutral.vz;
  395.     }
  396.  
  397.     std::cout << "Triplet population initialized: " << exc_1.size() << "\n";
  398.     std::cout << "Singlet population initialized: " << exc_2.size() << "\n";    
  399.  
  400.     // calculating excited specied population finished //
  401.  
  402.  
  403.     //----- calculating number to calculate nu-average (both elastic/inelastic )from our electron distribution starts---------///
  404.     // --- calculating nu(E)*f(E) for later external integration, using initial f(E)
  405.     for (int i = 0; i < N; i++){
  406.         double bin_center = Emin + (i + 0.5) * bin_width;
  407.         file9 << bin_center << " " << (N_He/Volume)*elastic_vec[i] * sqrt(2.0*bin_center*q/m_e)*static_cast<double>(histo_random[i])/(electrons.size()*bin_width) << "\n";
  408.         file10 << bin_center << " " << (N_He/Volume)*inelastic1_vec[i] * sqrt(2.0*bin_center*q/m_e)*static_cast<double>(histo_random[i])/(electrons.size()*bin_width) << "\n";
  409.     }
  410.     //----- calculating nu-average from our electron distribution ends ---------///    
  411.  
  412.     // double dt = 0.1/nu_max;   // minimum should be 0.1/nu_max to get acceptable numerical error range see Vahedi Surrendra 1995
  413.     // double steps = static_cast<int>(time/dt);
  414.  
  415.     // std::cout << steps << "\n";
  416.     // std::cout << dt << "\n";
  417.  
  418.     // //using  null-collision technique, getting the number of particles colliding each step: P_collision = 1 - exp(-nu_max*dt)
  419.     // int Ne_collided = (1.0-exp(-1.0*dt*nu_max))*n_e;
  420.  
  421.     // std::cout << "Ne_collided:" << Ne_collided << "\n";
  422.  
  423.     int print_interval = 10;
  424.     int el_coll_counter = 0; // track all elastic collisions
  425.     int exc1_coll_counter = 0; // track all triplet excitation collisions
  426.     int exc2_coll_counter = 0; // track all singlet excitation collisions
  427.     int null_coll_counter = 0; // track null-collisions
  428.     int ee_coll_counter = 0; //track e-e Coulomb collisions
  429.     int super1_coll_counter = 0; // track superelastic triplet collisions
  430.     int super2_coll_counter = 0; // track superelastic triplet collisions    
  431.  
  432.  
  433.     double a_z = ((-1.0)*q * E_reduced) / m_e;
  434.     double mass_ratio = 2.0*(m_e/M_n);
  435.     double charge_mass_ratio = 0.5*m_e/q;
  436.     double sqrt_charge_mass = sqrt(2*q/m_e);
  437.     double C1 = -1.0*q*E_reduced;
  438.     double C2 = 0.5*C1*C1/m_e;
  439.  
  440.     double total_time = 5.0E-2; // total calculation time
  441.     double t_elapsed = 0.0;
  442.  
  443.     std::cout << C1 << "    " << C2 << "\n";
  444.  
  445.  
  446.     // -----calculating nu-max for null-collision method starts ------------////
  447.     double nu_max = 0.0;
  448.     double nu_max_temp = 0.0;
  449.     double sigma_total = 0.0;
  450.    
  451.     for (int i = 0; i < N; i++){
  452.         // Get initial densities
  453.         double n_ground = N_He / Volume;
  454.         double n_excited1 = exc_1.size() / Volume;
  455.         double n_excited2 = exc_2.size() / Volume;
  456.  
  457.         double energy = Emin + (i + 0.5) * bin_width;
  458.  
  459.         // Total collision frequency for this energy bin
  460.         double sigma_total =
  461.             elastic_vec[i] * n_ground +
  462.             inelastic1_vec[i] * n_ground +
  463.             inelastic2_vec[i] * n_ground +
  464.             superelastic1_vec[i] * n_excited1 +
  465.             superelastic2_vec[i] * n_excited2;
  466.  
  467.         double v = sqrt(2 * energy * q / m_e);
  468.         double nu_temp = sigma_total * v;
  469.        
  470.         if (nu_temp > nu_max) nu_max = nu_temp;
  471.     }
  472.  
  473.     std::cout << "initial nu_max: " <<nu_max << "\n";
  474.     // -----calculating nu-max for null-collision method ends ------------////    
  475.  
  476.     double dt = 0.1/nu_max;   // minimum should be 0.1/nu_max to get acceptable numerical error range see Vahedi Surrendra 1995
  477.  
  478.  
  479.     while (t_elapsed < total_time) {
  480.         // Handle edge case for final step
  481.         if (t_elapsed + dt > total_time) {
  482.             dt = total_time - t_elapsed;
  483.         }    
  484.  
  485.  
  486.         //using  null-collision technique, getting the number of particles colliding each step: P_collision = 1 - exp(-nu_max*dt)
  487.         int Ne_collided = (1.0-exp(-1.0*dt*nu_max))*n_e;  
  488.  
  489.         // Generate shuffled list of electron indices
  490.         int reshuffle_interval = 1;
  491.         std::vector<int> electron_indices(n_e);
  492.         std::iota(electron_indices.begin(), electron_indices.end(), 0); // fill with index
  493.  
  494.  
  495.         for (int i = 0; i < Ne_collided; ++i) {
  496.             int j = i + std::uniform_int_distribution<int>(0, n_e - i - 1)(gen);
  497.             std::swap(electron_indices[i], electron_indices[j]);
  498.         }
  499.  
  500.         int exc1_coll_counter_temp = 0;
  501.         int super1_coll_counter_temp = 0;
  502.         int exc2_coll_counter_temp = 0;
  503.         int super2_coll_counter_temp = 0;
  504.         int null_coll_counter_temp = 0;
  505.  
  506.         double energy_exc = 0.0; // calculating excitation losses each timestep
  507.         double energy_sup = 0.0; // calculating superelastic gains each timestep
  508.         double energy_Efield = 0.0; // calculating field gains/losses each timestep
  509.  
  510.  
  511.         // std::cout << "Progress: " << (t_elapsed/total_time)*100 << "\n";
  512.  
  513.         // setting flags to false each timestep
  514.         for (auto& e : electrons) e.collided_en = false;
  515.         for (auto& e : electrons) e.collided_ee = false;        
  516.  
  517.         int collision_counter_en = 0; // electron-neutral collision counter
  518.         int collision_counter_ee = 0; // e-e collisoin counter
  519.  
  520.         /// -- electrin field heating along E-Z axis begin--- /// -- first half!!!
  521.         for (int idx : electron_indices) {
  522.             double half_dt = dt/2.0;
  523.             energy_Efield += ( C1*electrons[idx].vz*half_dt + C2*half_dt*half_dt )/q; // dividing by q to get eV            
  524.             // Update velocity component due to electric field
  525.             // double a_z = ((-1.0)*q * E_reduced) / m_e; // acceleration in z-direction, m/s^2
  526.             electrons[idx].vz += a_z * (dt*0.5); // only half timestep
  527.  
  528.             // Recalculate energy from updated velocity
  529.             double vx = electrons[idx].vx;
  530.             double vy = electrons[idx].vy;
  531.             double vz = electrons[idx].vz;
  532.             electrons[idx].energy = (vx*vx + vy*vy + vz*vz)*charge_mass_ratio;
  533.         }
  534.         // -------------------------------------------- filed heating ends ------------------------//  
  535.  
  536.  
  537.         for (int idx : electron_indices) {
  538.  
  539.             if (collision_counter_en >= Ne_collided) break; // quit if reached all collisions
  540.  
  541.             Electron& e = electrons[idx];
  542.             if (e.collided_en) continue;  // Skip already collided electrons
  543.  
  544.             double dens_neutrals = (N_He/Volume);
  545.             double dens_exc_1 = (exc_1.size()/Volume);
  546.             double dens_exc_2 = (exc_2.size()/Volume);
  547.             double speed = sqrt_charge_mass*sqrt(e.energy);
  548.  
  549.             int bin_energy = static_cast<int>(e.energy / bin_width);
  550.             double nu_elastic = dens_neutrals * elastic_vec[bin_energy] * speed;
  551.             double nu_inelastic1 = dens_neutrals * inelastic1_vec[bin_energy] * speed;
  552.             double nu_superelastic1 = dens_exc_1 * superelastic1_vec[bin_energy] * speed;
  553.             double nu_inelastic2 = dens_neutrals * inelastic2_vec[bin_energy] * speed;
  554.             double nu_superelastic2 = dens_exc_2 * superelastic2_vec[bin_energy] * speed;
  555.  
  556.             double r = dis(gen);
  557.  
  558.             double P0 = nu_elastic/nu_max;
  559.             double P1 = (nu_elastic + nu_inelastic1)/nu_max;
  560.             double P2 = (nu_elastic + nu_inelastic1 + nu_superelastic1)/nu_max;
  561.             double P3 = (nu_elastic + nu_inelastic1 + nu_superelastic1 + nu_inelastic2)/nu_max;
  562.             double P4 = (nu_elastic + nu_inelastic1 + nu_superelastic1 + nu_inelastic2 + nu_superelastic2)/nu_max;            
  563.  
  564.             if (r < P0) {
  565.  
  566.                 // elastic collision happens
  567.  
  568.                 // ----   Collision energy redistribution module
  569.  
  570.  
  571.                 // electron particle X Y Z initial velocities and energy
  572.                 double V0_x = e.vx;
  573.                 double V0_y = e.vy;
  574.                 double V0_z = e.vz;
  575.                 double E_0 = e.energy;
  576.                
  577.                 // neutral that collides with electron
  578.  
  579.                 // randomize particles each collision
  580.  
  581.                 NeutralParticle tmp_neutral;
  582.                 tmp_neutral.initialize(gen, dis, maxwell_neutral);
  583.                 double V_x_n = tmp_neutral.vx;
  584.                 double V_y_n = tmp_neutral.vy;
  585.                 double V_z_n = tmp_neutral.vz;
  586.                 double E_n = tmp_neutral.energy;
  587.  
  588.  
  589.                 double V0 = sqrt(V0_x*V0_x + V0_y*V0_y + V0_z*V0_z);
  590.                
  591.                 // generating random variables to calculate random direction of center-of-mass after the collision
  592.  
  593.                 double R1 = dis(gen);
  594.                 double R2 = dis(gen);
  595.  
  596.                 //// calculating spherical angles for center-of-mass random direction
  597.                 // double theta = acos(1.0- 2.0*R1);
  598.                 // double phi = 2*M_PI*R2;
  599.                 double cos_khi = (2.0 + E_0 - 2.0*pow((1+E_0), R1))/E_0;
  600.                 if (cos_khi >= 1)
  601.                     cos_khi = 1.0 - dopant;
  602.                 if (cos_khi <= -1)
  603.                     cos_khi = -1.0 + dopant;
  604.                                      
  605.                 double sin_khi = sqrt(1.0 - cos_khi*cos_khi);
  606.  
  607.                 double phi = 2.0*M_PI*R2;
  608.                 double cos_theta = V0_x/V0;
  609.                 double sin_theta = sqrt(1.0 - cos_theta*cos_theta);
  610.                 // //calculating final relative velocity with random direction
  611.  
  612.                 //calculating final velocity of electron
  613.  
  614.                 double i_scat = (V0_x/V0)*cos_khi + (1.0 - (V0_x/V0)*(V0_x/V0))*(sin_khi*cos(phi)/sin_theta);
  615.                 double j_scat = (V0_y/V0)*cos_khi +  (V0_z/V0)*sin_khi*sin(phi)/sin_theta - (V0_x/V0)*(V0_y/V0)*sin_khi*cos(phi)/sin_theta;
  616.                 double k_scat = (V0_z/V0)*cos_khi - (V0_y/V0)*sin_khi*sin(phi)/sin_theta - (V0_x/V0)*(V0_z/V0)*sin_khi*cos(phi)/sin_theta;
  617.  
  618.                 //updating electron energy and velocities  
  619.  
  620.                 double delta_E = mass_ratio*(1.0 - cos_khi)*E_0;
  621.                 if (e.energy < delta_E) {
  622.                     null_coll_counter++;
  623.                     collision_counter_en++;
  624.                     e.collided_en = true;
  625.                     continue;
  626.                 }    
  627.                 else {                          
  628.                     e.energy = E_0 - delta_E;
  629.                 }
  630.                
  631.                 double speed = sqrt_charge_mass*sqrt(e.energy);
  632.  
  633.                 e.vx = speed*i_scat;
  634.                 e.vy = speed*j_scat;
  635.                 e.vz = speed*k_scat;              
  636.  
  637.                 collision_counter_en++;
  638.                 el_coll_counter++;
  639.  
  640.                 e.collided_en = true;
  641.             }        
  642.  
  643.             else if (r < P1) {
  644.  
  645.                 //inelastic 1(triplet) collision happens
  646.  
  647.                 // ----   Collision energy redistribution module
  648.  
  649.                 // electron particle X Y Z initial velocities and energy
  650.                 double V0_x = e.vx;
  651.                 double V0_y = e.vy;
  652.                 double V0_z = e.vz;
  653.                 double E_0 = e.energy;
  654.                
  655.                 // neutral that collides with electron
  656.  
  657.                 // randomize particles each collision
  658.  
  659.                 NeutralParticle tmp_neutral;
  660.                 tmp_neutral.initialize(gen, dis, maxwell_neutral);
  661.                 double V_x_n = tmp_neutral.vx;
  662.                 double V_y_n = tmp_neutral.vy;
  663.                 double V_z_n = tmp_neutral.vz;
  664.                 double E_n = tmp_neutral.energy;
  665.  
  666.  
  667.                 double V0 = sqrt(V0_x*V0_x + V0_y*V0_y + V0_z*V0_z);
  668.                
  669.                 // generating random variables to calculate random direction of center-of-mass after the collision
  670.  
  671.                 double R1 = dis(gen);
  672.                 double R2 = dis(gen);
  673.  
  674.                 //// calculating spherical angles for center-of-mass random direction
  675.                 // double theta = acos(1.0- 2.0*R1);
  676.                 // double phi = 2*M_PI*R2;
  677.                 double cos_khi = (2.0 + E_0 - 2.0*pow((1+E_0), R1))/E_0;
  678.                 double sin_khi = sqrt(1.0 - cos_khi*cos_khi);
  679.  
  680.                 double phi = 2.0*M_PI*R2;
  681.                 double cos_theta = V0_x/V0;
  682.                 double sin_theta = sqrt(1.0 - cos_theta*cos_theta);
  683.                 // //calculating final relative velocity with random direction
  684.  
  685.                 //calculating final velocity of electron
  686.  
  687.                 double i_scat = (V0_x/V0)*cos_khi + (1.0 - (V0_x/V0)*(V0_x/V0))*(sin_khi*cos(phi)/sin_theta);
  688.                 double j_scat = (V0_y/V0)*cos_khi +  (V0_z/V0)*sin_khi*sin(phi)/sin_theta - (V0_x/V0)*(V0_y/V0)*sin_khi*cos(phi)/sin_theta;
  689.                 double k_scat = (V0_z/V0)*cos_khi - (V0_y/V0)*sin_khi*sin(phi)/sin_theta - (V0_x/V0)*(V0_z/V0)*sin_khi*cos(phi)/sin_theta;
  690.  
  691.                 //updating electron energy and velocities        
  692.                
  693.                 if (e.energy < thresh1) {
  694.                     null_coll_counter++;
  695.                     collision_counter_en++;
  696.                     e.collided_en = true;
  697.                     continue;
  698.                 }
  699.                 else {
  700.                     e.energy = E_0 - thresh1;
  701.  
  702.                     double speed = sqrt_charge_mass*sqrt(e.energy);
  703.  
  704.                     e.vx = speed*i_scat;
  705.                     e.vy = speed*j_scat;
  706.                     e.vz = speed*k_scat;
  707.  
  708.                     collision_counter_en++;  
  709.                     exc1_coll_counter++;
  710.                     exc1_coll_counter_temp++;
  711.  
  712.                     e.collided_en = true;
  713.  
  714.                     // pushing this neutral to an array of excited species exc_1
  715.                     if (N_He > 0) {
  716.                         exc_1.push_back({E_n, V_x_n, V_y_n, V_z_n});
  717.                         N_He--;
  718.                     }
  719.                 }
  720.             }    
  721.  
  722.             else if (r < P2) {
  723.  
  724.                 //superelastic 1(triplet -> ground state) collision happens
  725.  
  726.                 if (exc_1.empty()) {
  727.                     null_coll_counter++;
  728.                     collision_counter_en++;
  729.                     e.collided_en = true;
  730.                     continue;            
  731.                 }
  732.  
  733.                 // ----   Collision energy redistribution module
  734.  
  735.                 // electron particle X Y Z initial velocities and energy
  736.                 double V0_x = e.vx;
  737.                 double V0_y = e.vy;
  738.                 double V0_z = e.vz;
  739.                 double E_0 = e.energy;
  740.  
  741.                 double V0 = sqrt(V0_x*V0_x + V0_y*V0_y + V0_z*V0_z);
  742.  
  743.                 // neutral that collides with electron
  744.                 // taking particles from dynamic array of excited neutrals
  745.  
  746.                 int index = std::uniform_int_distribution<int>(0, exc_1.size()-1)(gen);
  747.                 Excited_neutral& exc = exc_1[index];
  748.                 double V_x = exc.vx;
  749.                 double V_y = exc.vy;
  750.                 double V_z = exc.vz;
  751.                 double E = exc.energy;
  752.                
  753.                 // generating random variables to calculate random direction of center-of-mass after the collision
  754.  
  755.                 double R1 = dis(gen);
  756.                 double R2 = dis(gen);
  757.  
  758.                 //// calculating spherical angles for center-of-mass random direction
  759.                 // double theta = acos(1.0- 2.0*R1);
  760.                 // double phi = 2*M_PI*R2;
  761.                 double cos_khi = (2.0 + E_0 - 2.0*pow((1+E_0), R1))/E_0;
  762.                 double sin_khi = sqrt(1.0 - cos_khi*cos_khi);
  763.  
  764.                 double phi = 2.0*M_PI*R2;
  765.                 double cos_theta = V0_x/V0;
  766.                 double sin_theta = sqrt(1.0 - cos_theta*cos_theta);
  767.                 // //calculating final relative velocity with random direction
  768.  
  769.                 //calculating final velocity of electron
  770.  
  771.                 double i_scat = (V0_x/V0)*cos_khi + (1.0 - (V0_x/V0)*(V0_x/V0))*(sin_khi*cos(phi)/sin_theta);
  772.                 double j_scat = (V0_y/V0)*cos_khi +  (V0_z/V0)*sin_khi*sin(phi)/sin_theta - (V0_x/V0)*(V0_y/V0)*sin_khi*cos(phi)/sin_theta;
  773.                 double k_scat = (V0_z/V0)*cos_khi - (V0_y/V0)*sin_khi*sin(phi)/sin_theta - (V0_x/V0)*(V0_z/V0)*sin_khi*cos(phi)/sin_theta;
  774.  
  775.                 //updating electron energy and velocities        
  776.                
  777.                 e.energy = E_0 + thresh1;
  778.  
  779.                 double speed = sqrt_charge_mass*sqrt(e.energy);
  780.  
  781.                 e.vx = speed*i_scat;
  782.                 e.vy = speed*j_scat;
  783.                 e.vz = speed*k_scat;
  784.  
  785.                 //counting collisions, working with flags, popping atom out of the vector
  786.                 if (!exc_1.empty()) {
  787.                     std::swap(exc_1[index], exc_1.back());
  788.                     exc_1.pop_back();
  789.                     N_He++;
  790.                 }
  791.                 collision_counter_en++;  
  792.                 super1_coll_counter++;
  793.                 super1_coll_counter_temp++;
  794.                 energy_sup += thresh1;
  795.  
  796.                 e.collided_en = true;
  797.             }  
  798.  
  799.             else if (r < P3) {
  800.  
  801.                 //inelastic 1(singlet) excitation collision happens
  802.  
  803.                 // ----   Collision energy redistribution module
  804.  
  805.                 // electron particle X Y Z initial velocities and energy
  806.                 double V0_x = e.vx;
  807.                 double V0_y = e.vy;
  808.                 double V0_z = e.vz;
  809.                 double E_0 = e.energy;
  810.                
  811.                 // neutral that collides with electron
  812.  
  813.                 // randomize particles each collision
  814.  
  815.                 NeutralParticle tmp_neutral;
  816.                 tmp_neutral.initialize(gen, dis, maxwell_neutral);
  817.                 double V_x_n = tmp_neutral.vx;
  818.                 double V_y_n = tmp_neutral.vy;
  819.                 double V_z_n = tmp_neutral.vz;
  820.                 double E_n = tmp_neutral.energy;
  821.  
  822.  
  823.                 double V0 = sqrt(V0_x*V0_x + V0_y*V0_y + V0_z*V0_z);
  824.                
  825.                 // generating random variables to calculate random direction of center-of-mass after the collision
  826.  
  827.                 double R1 = dis(gen);
  828.                 double R2 = dis(gen);
  829.  
  830.                 //// calculating spherical angles for center-of-mass random direction
  831.                 // double theta = acos(1.0- 2.0*R1);
  832.                 // double phi = 2*M_PI*R2;
  833.                 double cos_khi = (2.0 + E_0 - 2.0*pow((1+E_0), R1))/E_0;
  834.                 double sin_khi = sqrt(1.0 - cos_khi*cos_khi);
  835.  
  836.                 double phi = 2.0*M_PI*R2;
  837.                 double cos_theta = V0_x/V0;
  838.                 double sin_theta = sqrt(1.0 - cos_theta*cos_theta);
  839.                 // //calculating final relative velocity with random direction
  840.  
  841.                 //calculating final velocity of electron
  842.  
  843.                 double i_scat = (V0_x/V0)*cos_khi + (1.0 - (V0_x/V0)*(V0_x/V0))*(sin_khi*cos(phi)/sin_theta);
  844.                 double j_scat = (V0_y/V0)*cos_khi +  (V0_z/V0)*sin_khi*sin(phi)/sin_theta - (V0_x/V0)*(V0_y/V0)*sin_khi*cos(phi)/sin_theta;
  845.                 double k_scat = (V0_z/V0)*cos_khi - (V0_y/V0)*sin_khi*sin(phi)/sin_theta - (V0_x/V0)*(V0_z/V0)*sin_khi*cos(phi)/sin_theta;
  846.  
  847.                 //updating electron energy and velocities        
  848.                
  849.                 if (e.energy < thresh2) {
  850.                     null_coll_counter++;
  851.                     collision_counter_en++;
  852.                     e.collided_en = true;
  853.                     continue;
  854.                 }
  855.                 else {
  856.                     e.energy = E_0 - thresh2;
  857.  
  858.                     double speed = sqrt_charge_mass*sqrt(e.energy);
  859.  
  860.                     e.vx = speed*i_scat;
  861.                     e.vy = speed*j_scat;
  862.                     e.vz = speed*k_scat;
  863.  
  864.                     collision_counter_en++;  
  865.                     exc2_coll_counter++;
  866.                     exc2_coll_counter_temp++;
  867.  
  868.                     e.collided_en = true;
  869.  
  870.                     // pushing this neutral to an array of excited species exc_2
  871.  
  872.                     if (N_He > 0) {
  873.                         exc_2.push_back({E_n, V_x_n, V_y_n, V_z_n});
  874.                         N_He--;
  875.                     }
  876.                 }
  877.             }
  878.  
  879.             else if (r < P4) {
  880.  
  881.                 //supernelastic 1(singlet -> ground state) collision happens
  882.  
  883.                 if (exc_2.empty()) {
  884.                     null_coll_counter++;
  885.                     collision_counter_en++;
  886.                     e.collided_en = true;
  887.                     continue;            
  888.                 }
  889.  
  890.                 // ----   Collision energy redistribution module
  891.  
  892.                 // electron particle X Y Z initial velocities and energy
  893.                 double V0_x = e.vx;
  894.                 double V0_y = e.vy;
  895.                 double V0_z = e.vz;
  896.                 double E_0 = e.energy;
  897.  
  898.                 double V0 = sqrt(V0_x*V0_x + V0_y*V0_y + V0_z*V0_z);
  899.  
  900.                 // neutral that collides with electron
  901.                 // taking particles from dynamic array of excited neutrals
  902.  
  903.                 int index = std::uniform_int_distribution<int>(0, exc_2.size()-1)(gen);
  904.                 Excited_neutral& exc = exc_2[index];
  905.                 double V_x = exc.vx;
  906.                 double V_y = exc.vy;
  907.                 double V_z = exc.vz;
  908.                 double E = exc.energy;
  909.                
  910.                 // generating random variables to calculate random direction of center-of-mass after the collision
  911.  
  912.                 double R1 = dis(gen);
  913.                 double R2 = dis(gen);
  914.  
  915.                 //// calculating spherical angles for center-of-mass random direction
  916.                 // double theta = acos(1.0- 2.0*R1);
  917.                 // double phi = 2*M_PI*R2;
  918.                 double cos_khi = (2.0 + E_0 - 2.0*pow((1+E_0), R1))/E_0;
  919.                 double sin_khi = sqrt(1.0 - cos_khi*cos_khi);
  920.  
  921.                 double phi = 2.0*M_PI*R2;
  922.                 double cos_theta = V0_x/V0;
  923.                 double sin_theta = sqrt(1.0 - cos_theta*cos_theta);
  924.                 // //calculating final relative velocity with random direction
  925.  
  926.                 //calculating final velocity of electron
  927.  
  928.                 double i_scat = (V0_x/V0)*cos_khi + (1.0 - (V0_x/V0)*(V0_x/V0))*(sin_khi*cos(phi)/sin_theta);
  929.                 double j_scat = (V0_y/V0)*cos_khi +  (V0_z/V0)*sin_khi*sin(phi)/sin_theta - (V0_x/V0)*(V0_y/V0)*sin_khi*cos(phi)/sin_theta;
  930.                 double k_scat = (V0_z/V0)*cos_khi - (V0_y/V0)*sin_khi*sin(phi)/sin_theta - (V0_x/V0)*(V0_z/V0)*sin_khi*cos(phi)/sin_theta;
  931.  
  932.                 //updating electron energy and velocities        
  933.                
  934.                 e.energy = E_0 + thresh2;
  935.  
  936.                 double speed = sqrt_charge_mass*sqrt(e.energy);
  937.  
  938.                 e.vx = speed*i_scat;
  939.                 e.vy = speed*j_scat;
  940.                 e.vz = speed*k_scat;
  941.  
  942.                 //counting collisions, working with flags, popping atom out of the vector
  943.  
  944.                 if (!exc_2.empty()) {
  945.                     std::swap(exc_2[index], exc_2.back());
  946.                     exc_2.pop_back();
  947.                     N_He++;
  948.                 }
  949.  
  950.                 collision_counter_en++;  
  951.                 super2_coll_counter++;
  952.                 super2_coll_counter_temp++;
  953.                 energy_sup += thresh2;
  954.  
  955.                 e.collided_en = true;
  956.             }              
  957.  
  958.             else {
  959.                 // null-collision
  960.                 collision_counter_en++;
  961.                 null_coll_counter++;
  962.                 e.collided_en = true;
  963.             }
  964.         }
  965.  
  966.  
  967.         /// -- electrin field heating along E-Z axis begin--- /// -- second half!!!
  968.         for (int idx : electron_indices) {
  969.             double half_dt = dt/2.0;
  970.             energy_Efield += ( C1*electrons[idx].vz*half_dt + C2*half_dt*half_dt )/q; //dividing by q to get eV
  971.             // Update velocity component due to electric field
  972.             // double a_z = ((-1.0)*q * E_reduced) / m_e; // acceleration in z-direction, m/s^2
  973.             electrons[idx].vz += a_z * (dt*0.5); // only half timestep
  974.  
  975.             // Recalculate energy from updated velocity
  976.             double vx = electrons[idx].vx;
  977.             double vy = electrons[idx].vy;
  978.             double vz = electrons[idx].vz;
  979.             electrons[idx].energy = (vx*vx + vy*vy + vz*vz) * charge_mass_ratio;
  980.         }
  981.         // -------------------------------------------- filed heating ends ------------------------////////////////
  982.  
  983.         int decay_counter = 0;
  984.  
  985.         // // Iterate backwards to safely remove elements
  986.         // for (int i = exc_2.size() - 1; i >= 0; --i) {
  987.         //     if (dis(gen) < dt / tau_singlet) {
  988.         //         // Swap with last element and pop (like your superelastic code)
  989.         //         std::swap(exc_2[i], exc_2.back());
  990.         //         exc_2.pop_back();
  991.         //         N_He++;
  992.         //         decay_counter++;
  993.         //     }
  994.         // }
  995.  
  996.  
  997.         t_elapsed += dt; // Advance time
  998.  
  999.         // Recalculate nu_max periodically (e.g., every 100 steps)
  1000.         static int recalc_counter = 0;
  1001.         if (++recalc_counter >= 10000) {
  1002.            
  1003.             recalc_counter = 0;
  1004.  
  1005.             // Recalculate nu_max with CURRENT densities
  1006.             nu_max = 0.0;
  1007.             for (int i = 0; i < N; i++) {
  1008.                 double energy = Emin + (i + 0.5) * bin_width;
  1009.                
  1010.                 // Get current densities
  1011.                 double n_ground = N_He / Volume;
  1012.                 double n_excited1 = exc_1.size() / Volume;
  1013.                 double n_excited2 = exc_2.size() / Volume;
  1014.                
  1015.                 // Total collision frequency for this energy bin
  1016.                 double sigma_total =
  1017.                     elastic_vec[i] * n_ground +
  1018.                     inelastic1_vec[i] * n_ground +
  1019.                     inelastic2_vec[i] * n_ground +
  1020.                     superelastic1_vec[i] * n_excited1 +
  1021.                     superelastic2_vec[i] * n_excited2;
  1022.  
  1023.                 double speed = sqrt_charge_mass*sqrt(energy);
  1024.                 double nu_temp = sigma_total * speed;
  1025.                
  1026.                 if (nu_temp > nu_max) nu_max = nu_temp;
  1027.             }
  1028.  
  1029.  
  1030.  
  1031.             // Update dt based on new nu_max
  1032.             dt = 0.1 / nu_max;        
  1033.         }  
  1034.  
  1035.         // calculating mean energy
  1036.         if (static_cast<int>(t_elapsed/dt)%print_interval == 0) {
  1037.             double total_energy = 0.0;
  1038.             for (const auto& e : electrons) total_energy += e.energy;
  1039.             double mean_energy = total_energy / n_e;
  1040.             file8 << t_elapsed << " " << mean_energy << "\n";            
  1041.             file_temp << t_elapsed << " " << exc_1.size() << " " << exc_2.size() << "\n";
  1042.             std::cout << "Progress: " << (t_elapsed/total_time)*100 << "%" << " ";
  1043.             std::cout << "   nu_max: " << nu_max << "    " << "dt: " << dt << " " << "decay counter: " << decay_counter <<   "\n";
  1044.             file16 << t_elapsed << " " << energy_Efield/n_e << " " << energy_sup/n_e << "\n";
  1045.         }        
  1046.  
  1047.     }
  1048.  
  1049.     // ----- final electron energies distribution begins
  1050.     for (int i = 0; i < n_e; i++){
  1051.  
  1052.         file2 << i << " " << electrons[i].energy << "\n";
  1053.  
  1054.         int bin = static_cast<int>( (electrons[i].energy - Emin)/bin_width_smooth);
  1055.         if (bin >=0 && bin < histo_maxwell.size())
  1056.             histo_maxwell[bin]++;
  1057.     }
  1058.  
  1059.     int check = 0;
  1060.     for (int i = 0; i < N_smooth; i++){
  1061.         check += histo_maxwell[i];
  1062.         double bin_center = Emin + (i + 0.5) * bin_width_smooth;
  1063.         file4 << bin_center << " " <<  static_cast<double>(histo_maxwell[i])/(electrons.size()*bin_width_smooth) << "\n"; // getting f(E)
  1064.     }
  1065.  
  1066.         std::cout << "Total # of electrons in a final histogram: " << check << "\n";
  1067.         std::cout << "Final nu max: " << nu_max << "\n";
  1068.  
  1069.     // ----- final electron energies distribution ends
  1070.  
  1071.  
  1072.     file0.close();
  1073.     file1.close();
  1074.     file2.close();
  1075.     file3.close();
  1076.     file4.close();
  1077.     file5.close();
  1078.     file6.close();
  1079.     file7.close();
  1080.     file8.close();
  1081.     file9.close();
  1082.     file10.close();
  1083.     file11.close();
  1084.     file12.close();
  1085.     file13.close();
  1086.     file14.close();
  1087.     file15.close();
  1088.     file_temp.close();
  1089.     file16.close();
  1090.  
  1091.     clock_t end = clock();
  1092.  
  1093.     double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
  1094.  
  1095.     // std::cout << "# of steps: " << steps << "\n";
  1096.     // std::cout << "# of electrons collided each timesteps:" << Ne_collided << "\n";
  1097.    
  1098.     // std::cout << "Average elastic collisions per timestep: " << static_cast<int>(el_coll_counter/steps) << "\n";
  1099.     // std::cout << "Average null collisions per timestep: " << static_cast<int>(null_coll_counter/steps) << "\n";
  1100.     // std::cout << "\n";
  1101.  
  1102.     // std::cout << "triplet:________" << "\n";
  1103.     // std::cout << "Average triplet excitation collisions per timestep: " << static_cast<int>(exc1_coll_counter/steps) << "\n";
  1104.     // std::cout << "\n";
  1105.     // std::cout << "Average superelastic triplet collisions per timestep: " << static_cast<int>(super1_coll_counter/steps) << "\n";
  1106.     // std::cout << "\n";
  1107.  
  1108.     // std::cout << "singlet:________" << "\n";
  1109.     // std::cout << "Average singlet excitation collisions per timestep: " << static_cast<int>(exc2_coll_counter/steps) << "\n";
  1110.     // std::cout << "\n";
  1111.     // std::cout << "Average superelastic singlet collisions per timestep: " << static_cast<int>(super2_coll_counter/steps) << "\n";
  1112.     // std::cout << "\n";    
  1113.  
  1114.     // std::cout << "Average e-e collisions per timestep: " << static_cast<int>(ee_coll_counter/steps) << "\n";
  1115.  
  1116.     std::cout << "Elapsed time: %f seconds " << elapsed << "\n";
  1117.  
  1118.  
  1119.     return 0;
  1120.  
  1121. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement