SHARE
    TWEET
    phystota

    nu_max_recalculation_same_mean_energy_problem

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

    AltStyle によって変換されたページ (->オリジナル) /