tulen_pod_soysom

Untitled

Nov 1st, 2023
788
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.28 KB | None | 0 0
  1. #pragma once
  2. #include <vector>
  3. #include <boost/numeric/odeint.hpp>
  4. //#include "../myodeint/boost/numeric/odeint.hpp"
  5.  
  6. static constexpr double PI = 3.14159265358979323;
  7.  
  8. struct well_function
  9. {
  10.     double width = 1;
  11.     double u0 = 1;
  12.  
  13.     double A = 1, sigma = 0.1, mean = 0;
  14.    
  15.     double operator() (double x)
  16.     {
  17.         if (x > -width / 2.0 && x < width / 2.0)
  18.         return -u0 + A/sqrt(2*PI*sigma) * exp(-(x-mean)*(x - mean) / (2*sigma*sigma));
  19.         else return 0;
  20.     }
  21.  
  22.     well_function(double width, double u0, double A, double sigma, double mean) : width(width), u0(u0), A(A), sigma(sigma), mean(mean) {}
  23.  
  24.     double left_bound() { return -width / 2.0; }
  25.     double right_bound() { return width / 2.0; }
  26. };
  27.  
  28. struct phase_integrator
  29. {
  30.     double& E;
  31.     well_function& well_f;
  32.  
  33.     void operator () (double& phase, double& d_phase_dx, double x)
  34.     {
  35.         d_phase_dx = (well_f(x) - E) * pow(cos(phase), 2) - pow(sin(phase), 2);
  36.     }
  37. };
  38.  
  39. struct wave_function_value : public std::array<double,2>
  40. {
  41.     double& r() { return (*this)[0]; }
  42.     double& phase() { return (*this)[1]; }
  43. };
  44.  
  45. struct radial_integrator
  46. {
  47.     double& E;
  48.     well_function& well_f;
  49.  
  50.     void operator () (wave_function_value& phi, wave_function_value& d_phi_dx, double x)
  51.     {
  52.         d_phi_dx.r() = (1 + well_f(x) - E) * phi.r() * cos(phi.phase()) * sin(phi.phase());
  53.         d_phi_dx.phase() = (well_f(x) - E) * pow(cos(phi.phase()), 2) - pow(sin(phi.phase()), 2);
  54.     }
  55. };
  56.  
  57. template<typename T = double>
  58. std::pair<T, T> divide_by_two_method(std::function<T(T)> f, T left, T right, T epsilon, T compare_to)
  59. {
  60.     T c;
  61.     do
  62.     {
  63.         c = (right + left) / 2.0;
  64.         if ((f(c) - compare_to) * (f(left) - compare_to) < 0)
  65.         {
  66.             right = c;
  67.         }
  68.         else
  69.         {
  70.             left = c;
  71.         }
  72.     } while (abs(right - left) >= epsilon);
  73.     return { f(c),c };
  74. }
  75.  
  76. class Program
  77. {
  78. public:
  79.     well_function well_f;
  80.  
  81.     std::vector<double> phase_E;
  82.     std::vector<double> Ek;
  83.     std::vector<double> appropriate_phases;
  84.  
  85.     size_t chosen_k = 0;
  86.     std::vector<wave_function_value> wave_function;
  87.  
  88.     double E_loop_size = 2048;
  89.     double x_step = 0.01;
  90.  
  91.     double R = 3.0;
  92.  
  93.     void evaluate_ek()
  94.     {
  95.         phase_E.resize(E_loop_size);
  96.  
  97.         boost::numeric::odeint::runge_kutta4<double> stepper;
  98.         for (int i = 0; i < E_loop_size; i++)
  99.         {
  100.             double E = -well_f.u0 + i / (double)E_loop_size * well_f.u0;
  101.             double phase = PI / 2.0;
  102.  
  103.             boost::numeric::odeint::integrate_const(
  104.                 stepper,
  105.                 phase_integrator{ E,well_f },
  106.                 phase,
  107.                 well_f.left_bound() - R,
  108.                 well_f.right_bound() + R,
  109.                 x_step
  110.             );
  111.             phase_E[i] = phase;
  112.         }
  113.  
  114.         double phase_min, phase_max;
  115.         int k_min, k_max;
  116.         phase_min = *std::min_element(phase_E.begin(), phase_E.end());
  117.         phase_max = *std::max_element(phase_E.begin(), phase_E.end());
  118.  
  119.  
  120.         k_min = 0;
  121.         k_max = floor((-2 * phase_min / PI - 1) / 2.0);
  122.         k_max = k_max > 0 ? k_max : 0;
  123.  
  124.         Ek.resize(k_max - k_min);
  125.  
  126.         appropriate_phases.resize(k_max - k_min);
  127.         for (size_t i = k_min; i < k_max; i++)
  128.         {
  129.             appropriate_phases[i] = (2 * i + 1) / 2.0 * (-PI);
  130.         }
  131.  
  132.         for (size_t i = 0; i < Ek.size(); i++)
  133.         {
  134.             double appropriate_phase = (2 * i + 1) / 2.0 * (-PI);
  135.  
  136.             Ek[i] = divide_by_two_method<double>(
  137.                 [&](double E)
  138.                 {
  139.                     double phase = PI / 2.0;
  140.                     boost::numeric::odeint::integrate_const(
  141.                         stepper,
  142.                         phase_integrator{ E,well_f },
  143.                         phase,
  144.                         well_f.left_bound() - R,
  145.                         well_f.right_bound() + R,
  146.                         x_step
  147.                     );
  148.                     return phase;
  149.                 },
  150.                 -well_f.u0,
  151.                 0,
  152.                 1e-5,
  153.                 appropriate_phase
  154.             ).second;
  155.         }
  156.     }
  157.  
  158.     void evaluate_wave_function()
  159.     {
  160.         wave_function.clear();
  161.        
  162.         wave_function_value start_value;
  163.         start_value.r() = 1.0;
  164.         start_value.phase() = PI / 2.0;
  165.  
  166.         wave_function.push_back(start_value);
  167.  
  168.         boost::numeric::odeint::runge_kutta4<wave_function_value> stepper;
  169.         boost::numeric::odeint::integrate_const(
  170.             stepper,
  171.             radial_integrator{ Ek[chosen_k],well_f },
  172.             start_value,
  173.             well_f.left_bound() - R,
  174.             well_f.right_bound() + R,
  175.             x_step,
  176.             [&](const wave_function_value& phi, double x) { wave_function.push_back(phi);}
  177.         );
  178.  
  179.         auto norm = sqrt(std::accumulate(wave_function.begin(), wave_function.end(),0.0, [&](auto& a, auto& b) {return a + b.r() * b.r() * x_step; }));
  180.         for (auto& i : wave_function) {i.r() *=well_f.u0 / norm;}
  181.     }
  182.  
  183.     Program() : well_f(1,1,1,1,0){}
  184. };
  185.  
  186.  
  187.  
Advertisement
Add Comment
Please, Sign In to add comment