Advertisement
phystota

Thermalization_1

Mar 24th, 2025
285
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.56 KB | None | 0 0
  1. #include <iostream>
  2. #include <random>
  3. #include <fstream>
  4. #include <math.h>
  5. #include <time.h>
  6. #include <iomanip>  // For std::fixed and std::setprecision
  7.  
  8. #define n_e 100000
  9. #define V_0 30000.0     // max velocity using to generate random distribution ---- doesn't work -> produces skew distribution???
  10. #define Emin 0.0
  11. #define Emax 100.0
  12. #define bin_width 0.5
  13. #define m_e 9.1E-31 // electron mass in kg
  14. #define k_b 1.38E-23 // Boltzmann constant
  15. #define q 1.6E-19 // elementary charge    
  16. #define N ( (int)((Emax-Emin)/bin_width) ) // add 1 to include E_max if needed?
  17. #define P 0.005
  18. #define steps 100
  19.  
  20. struct Electron {
  21.  
  22.     //velocity components
  23.     double vx = 0.0;
  24.     double vy = 0.0;
  25.     double vz = 0.0;
  26.     //energy in eV
  27.     double energy = 0.0;
  28.     //Collision flag
  29.     bool collided = false;
  30.  
  31.     //initialization function
  32.     void initialize(std::mt19937 gen, std::uniform_real_distribution<double> dis) {
  33.         // velocity angles in spherical coordinates
  34.         double phi = 2*M_PI*dis(gen);
  35.         double sinTheta = dis(gen);
  36.         double cosTheta = sqrt(1.0 - sinTheta*sinTheta);
  37.        
  38.         energy = Emax*dis(gen);
  39.        
  40.         double speed = sqrt(2*energy*k_b/m_e);
  41.  
  42.         vx = speed * sinTheta * cos(phi);
  43.         vy = speed * sinTheta * sin(phi);
  44.         vz = speed * cosTheta;
  45.  
  46.     }
  47.  
  48. };
  49.  
  50. int main() {
  51.  
  52.     double electron_vel[3*n_e];
  53.     double electron_e[n_e];
  54.     int histo_random[N] = {0};
  55.     int histo_maxwell[N] = {0};
  56.     bool collided[n_e] = {0};
  57.  
  58.     clock_t start = clock();
  59.  
  60.     for (int i = 0; i < 3*n_e; i++){
  61.         electron_vel[i] = 0.0;
  62.     }    
  63.  
  64.     for (int i = 0; i < n_e; i++){
  65.         electron_e[i] = 0.0;
  66.     }    
  67.  
  68.  
  69.     std::ofstream file0("velocities.dat");    
  70.     if (!file0.is_open()) {
  71.         std::cerr << "Error opening file!" << std::endl;
  72.         return 1;
  73.     }
  74.  
  75.     std::ofstream file1("energies.dat");    
  76.     if (!file1.is_open()) {
  77.         std::cerr << "Error opening file!" << std::endl;
  78.         return 1;
  79.     }
  80.    
  81.     std::ofstream file2("energies_final.dat");    
  82.     if (!file2.is_open()) {
  83.         std::cerr << "Error opening file!" << std::endl;
  84.         return 1;
  85.     }
  86.  
  87.     std::ofstream file3("histo_random.dat");    
  88.     if (!file3.is_open()) {
  89.         std::cerr << "Error opening file!" << std::endl;
  90.         return 1;
  91.     }
  92.     file3 << std::fixed << std::setprecision(10);
  93.    
  94.     std::ofstream file4("histo_maxwell.dat");    
  95.     if (!file4.is_open()) {
  96.         std::cerr << "Error opening file!" << std::endl;
  97.         return 1;
  98.     }
  99.     file4 << std::fixed << std::setprecision(10);                
  100.  
  101.     std::random_device rd;
  102.     std::mt19937 gen(rd());
  103.     std::uniform_real_distribution<double> dis(0.0, 1.0);
  104.  
  105.     std::random_device rd1;
  106.     std::mt19937 gen1(rd1());
  107.     std::uniform_int_distribution<int> pair(0, n_e-1);
  108.  
  109.  
  110.     for (int i = 0; i < n_e; i++){
  111.  
  112.         double phi = 2*M_PI*dis(gen);
  113.         double sinTheta = dis(gen);
  114.         double cosTheta = sqrt(1.0 - sinTheta*sinTheta);
  115.        
  116.         double energy = Emax*dis(gen);
  117.         double speed = sqrt(2*energy*k_b/m_e);
  118.  
  119.         electron_vel[i*3] = speed * sinTheta * cos(phi); // x component
  120.         electron_vel[i*3+1] = speed * sinTheta * sin(phi); // y component
  121.         electron_vel[i*3+2] = speed * cosTheta; // z component
  122.        
  123.         electron_e[i] = energy;
  124.  
  125.         file0  << i << " " << electron_vel[i*3] << " " << electron_vel[i*3+1] << " " << electron_vel[i*3+2]  << "\n";
  126.  
  127.         file1 << i << " " << electron_e[i] << "\n";
  128.  
  129.         energy = 0.0;
  130.     }
  131.  
  132.     for (int i = 0; i < n_e; i++){
  133.         int bin = (int)( (electron_e[i] - Emin)/bin_width );
  134.         if (bin >=0 && bin < N)
  135.             histo_random[bin]++;
  136.     }
  137.  
  138.     for (int i = 0; i < N; i++){
  139.         double bin_start = Emin + i*bin_width;
  140. //        printf("%5.1f - %5.1f\t%d\n", bin_start, bin_start + bin_width, histo_random[i]);
  141.         file3 << i*bin_width << " " <<  static_cast<double>(histo_random[i]) << "\n"; // dividing by n_e to get normalized distribution
  142.     }
  143.  
  144.  
  145.     for (int t = 0; t < steps; t++){
  146.  
  147.         std::ostringstream filename;
  148.         filename << "data/distribution_" << std::setw(4) << std::setfill('0') << t << ".dat";
  149.  
  150.         std::ofstream file(filename.str());
  151.         if (!file.is_open()){
  152.         std::cerr << "Error opening file: " << filename.str() << std::endl;
  153.         return 1;
  154.         }
  155.  
  156.         // setting flags to false each timestep
  157.         for (int j = 0; j < n_e; j++){
  158.             collided[j] = false;
  159.         }
  160.  
  161.         for (int i = 0 ; i < n_e; i++){
  162.             if (dis(gen) < P) {
  163.                 int partner = -1;
  164.                 int attempts = 0;
  165.  
  166.                 while (attempts < n_e){
  167.                     int candidate = pair(gen1);
  168.                     if (candidate != i && !collided[candidate]){
  169.                         partner = candidate;
  170.                         break;
  171.                     }
  172.                     attempts++;
  173.                 }
  174.  
  175.                 if (partner != -1) {
  176.                     collided[i] = true;
  177.                     collided[partner] = true;
  178.                 }
  179.  
  180.                 // ----   Collision energy redistribution module
  181.  
  182.                 // first particle X Y Z initial velocities
  183.                 double V0_x_1 = electron_vel[i*3 + 0];
  184.                 double V0_y_1 = electron_vel[i*3 + 1];
  185.                 double V0_z_1 = electron_vel[i*3 + 2];
  186.  
  187.                 // second particle X Y Z initial velocities
  188.                 double V0_x_2 = electron_vel[partner*3 + 0];
  189.                 double V0_y_2 = electron_vel[partner*3 + 1];
  190.                 double V0_z_2 = electron_vel[partner*3 + 2];
  191.  
  192.                 // initial relative velocity X Y Z (must be equal to final relative velocity in center-of-mass frame)
  193.  
  194.                 double V0_rel_x = (V0_x_1 - V0_x_2)/2.0;
  195.                 double V0_rel_y = (V0_y_1 - V0_y_2)/2.0;
  196.                 double V0_rel_z = (V0_z_1 - V0_z_2)/2.0;
  197.  
  198.                 double V0_rel = sqrt(V0_rel_x*V0_rel_x + V0_rel_y*V0_rel_y + V0_rel_z*V0_rel_z);
  199.  
  200.                 // center-of-mass frame initial velocity (magnitude of it must be equal to the counterpart in this frame)
  201.  
  202.                 double V_cm_x = (V0_x_1 + V0_x_2)/2.0;
  203.                 double V_cm_y = (V0_y_1 + V0_y_2)/2.0;
  204.                 double V_cm_z = (V0_z_1 + V0_z_2)/2.0;
  205.  
  206.                 double V_cm = sqrt(V_cm_x*V_cm_x + V_cm_y*V_cm_y + V_cm_z*V_cm_z);
  207.  
  208.                 // generating random variables to calculate random direction of center-of-mass after the collision
  209.  
  210.                 double R1 = dis(gen);
  211.                 double R2 = dis(gen);
  212.  
  213.                 // calculating spherical angles for center-of-mass random direction
  214.                 double theta = acos(1.0- 2.0*R1);
  215.                 double phi = 2*M_PI*R2;
  216.  
  217.                 //calculating final relative velocity with random direction
  218.  
  219.                 double V_rel_x = V0_rel*sin(theta)*cos(phi);
  220.                 double V_rel_y = V0_rel*sin(theta)*sin(phi);
  221.                 double V_rel_z = V0_rel*cos(theta);
  222.  
  223.                 double V_rel = sqrt(V_rel_x*V_rel_x + V_rel_y*V_rel_y + V_rel_z*V_rel_z);
  224.  
  225.                 //calculating final velocity of first particle
  226.  
  227.                 double V_x_1 = V_cm_x + V_rel_x/2.0;
  228.                 double V_y_1 = V_cm_y + V_rel_y/2.0;
  229.                 double V_z_1 = V_cm_z + V_rel_z/2.0;
  230.  
  231.                 double V_1 = sqrt(V_x_1*V_x_1 + V_y_1*V_y_1 + V_z_1*V_z_1);
  232.  
  233.                 //calculating final velocity of second particle
  234.  
  235.                 double V_x_2 = V_cm_x - V_rel_x/2.0;
  236.                 double V_y_2 = V_cm_y - V_rel_y/2.0;
  237.                 double V_z_2 = V_cm_z - V_rel_z/2.0;
  238.  
  239.                 double V_2 = sqrt(V_x_2*V_x_2 + V_y_2*V_y_2 + V_z_2*V_z_2);\
  240.  
  241.                 // calculating final energies of first and second colliding particles
  242.  
  243.                 electron_e[i] = V_1*V_1*m_e/(2.0*k_b);
  244.                 electron_e[partner] = V_2*V_2*m_e/(2.0*k_b);          
  245.  
  246.                 // --- collision energy redistrubution module ends    
  247.  
  248.             }
  249.         }
  250.  
  251.         for (int i = 0; i < n_e; i++){
  252. //        filename << i << " " << electron_e[i] << "\n";
  253.         int bin = (int)( (electron_e[i] - Emin)/bin_width );
  254.         if (bin >=0 && bin < N)
  255.             histo_maxwell[bin]++;
  256.         }
  257.  
  258.         for (int i = 0; i < N; i++){
  259.             double bin_start = Emin + i*bin_width;
  260.             file << i*bin_width << " " <<  static_cast<double>(histo_maxwell[i]) << "\n"; // later need to divide by total partcles number to get normalized distribution
  261.             histo_maxwell[i] = 0;
  262.         }
  263.  
  264.         file.close();
  265.  
  266.     }
  267. //     for (int i = 0; i < n_e; i++){
  268.  
  269. //         file2 << i << " " << electron_e[i] << "\n";
  270.  
  271. //         int bin = (int)( (electron_e[i] - Emin)/bin_width );
  272. //         if (bin >=0 && bin < N)
  273. //             histo_maxwell[bin]++;
  274. //     }
  275.  
  276. //     for (int i = 0; i < N; i++){
  277. //         double bin_start = Emin + i*bin_width;
  278. // //        printf("%5.1f - %5.1f\t%d\n", bin_start, bin_start + bin_width, histo_maxwell[i]);
  279. //         file4 << i*bin_width << " " <<  static_cast<double>(histo_maxwell[i]) << "\n"; // dividing by partcles number to get normalized distribution
  280. //     }
  281.  
  282.  
  283.     file0.close();
  284.     file1.close();
  285.     file2.close();
  286.     file3.close();
  287.     file4.close();
  288.  
  289.     clock_t end = clock();
  290.  
  291.     double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
  292.  
  293.     std::cout << "Energies written successfuly\n";
  294.     std::cout << "Elapsed time: %f seconds " << elapsed << "\n";
  295.  
  296.  
  297.     return 0;
  298.  
  299.  
  300. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement