Advertisement
BorrowTheProgrammer

anton

Dec 17th, 2022
844
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.22 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <cmath>
  4. #define CUBE
  5.  
  6. constexpr double EPS = 1e-16,CUB=2.966181e-8;
  7. constexpr double X_BEGIN = - 12.0;
  8. constexpr double X_END = 1;
  9. constexpr size_t ELEMS_NUM = 20;
  10. constexpr double L = (X_END - X_BEGIN) / ELEMS_NUM;
  11. constexpr double a=11.0,B=0.0,C=-3.0,D=4.0,usl_left=-2.0, usl_right=10.0;
  12.  
  13. std::vector<double> solve_with_gauss(std::vector<std::vector<double>>& A, std::vector<double>& b){
  14.     size_t row_size = A.size();
  15.     size_t col_size = A.back().size();
  16.     // Прямой ход Гаусса
  17.     double pivot = 0.0;
  18.     for (size_t i = 0; i < row_size; i++) {
  19.         for (size_t j = i + 1; j < col_size; j++) {
  20.             if (std::abs(A.at(j).at(i)) < EPS) {
  21.                 continue;
  22.             }
  23.             pivot = A.at(j).at(i) / A.at(i).at(i);
  24.             b.at(j) -= pivot * b.at(i);
  25.             for (size_t k = 0; k < row_size; k++) {
  26.                 A.at(j).at(k) -= pivot * A.at(i).at(k) ;
  27.             }
  28.         }
  29.     }
  30.     // Обратный ход Гаусса
  31.     std::vector<double> x(row_size);
  32.     for (int i = row_size - 1.0; i >= 0; i--) {
  33.         x.at(i) = b.at(i);
  34.         for (size_t j = i + 1; j < row_size; j++) {
  35.             x.at(i) -= x.at(j) * A.at(i).at(j);
  36.         }
  37.         x.at(i) /= A.at(i).at(i);
  38.     }
  39.     return x;
  40. }
  41.  
  42. double analytical_solution(double x) {
  43.     double a=2*sqrt(33)*exp(sqrt(3.0/11.0)*x)+2*sqrt(33)*exp(sqrt(3.0/11.0)*x+26*sqrt(3.0/11.0))-33*exp(2*sqrt(3.0/11.0)*x+12*sqrt(3.0/11.0))+13*sqrt(33)*exp(2*sqrt(3.0/11.0)*x+25*sqrt(3.0/11.0)) + 13*sqrt(33)*exp(sqrt(3.0/11.0))+33*exp(14*sqrt(3.0/11.0));
  44.    
  45.     double b=3*sqrt(33)*(1+exp(26*sqrt(3.0/11.0)));
  46.     double rez=2*exp(-sqrt(3.0/11.0)*x)*a/b;
  47.    
  48.     return rez;
  49. }
  50.  
  51. std::vector<double> build_analytical_solution(std::vector<double>& x_vec) {
  52.     size_t x_vec_size = x_vec.size();
  53.     std::vector<double> y_vec = std::vector<double>(x_vec_size);
  54.     for (size_t i = 0; i < x_vec_size; i++) {
  55.         y_vec.at(i) = analytical_solution(x_vec.at(i));
  56.     }
  57.     return y_vec;
  58. }
  59.  
  60. std::vector<double> build_linear_solution(size_t elems_num) {
  61.     double L = (X_END - X_BEGIN) / elems_num;
  62.     size_t size = elems_num + 1;
  63.     std::vector< std::vector<double> > A(size, std::vector<double>(size));
  64.     std::vector<double> b(size);
  65.    
  66.     // Локальная матрица жесткости для линейного КЭ
  67.     std::vector< std::vector<double> > local_matrix = {
  68.         { a/L - C * L/3, -a/L - C * L/6},
  69.         { -a/L - C * L/6, a/L - C*L/3},
  70.     };
  71.    
  72.     // Ансамблирование и получение глобальной матрицы жесткости для линейного КЭ
  73.     for (size_t i = 0; i < elems_num; i++) {
  74.         for (size_t j = 0; j < 2; j++) {
  75.             for (size_t k = 0; k < 2; k++) {
  76.                 A.at(i + j).at(i + k) += local_matrix.at(j).at(k);
  77.             }
  78.         }
  79.     }
  80.    
  81.         for (size_t i = 0; i < size ; i++) {
  82.         b.at(i) = D * L;
  83.     }
  84.    
  85.     // Учет ГУ
  86.     b.at(0) = D*L/2 -a*usl_left;
  87.  
  88.     b.at(size - 1) = usl_right;
  89.     A.at(size - 1).at(size - 1) = 1;
  90.     A.at(size - 1).at(size - 2)=0;
  91.  
  92.    
  93.     // Решение полученной СЛАУ методом Гаусса
  94.     std::vector<double> res = solve_with_gauss(A, b);
  95.     return res;
  96. }
  97.  
  98. std::vector<double> build_cube_solution(size_t elems_num) {
  99.     double L = (X_END - X_BEGIN) / elems_num;
  100.     size_t size = elems_num + 1;
  101.     std::vector< std::vector<double> > A(size,std::vector<double>(size));
  102.     std::vector<double> b(size);
  103.    
  104.     // Локальная матрица жесткости для кубического КЭ
  105.     std::vector< std::vector<double> > local_matrix = {
  106.  
  107.         {  a*37.0/(10.0*L) - C*8*L/105.0 ,     -a*189.0/(40.0*L) - C*33*L/560.0,    a*27.0/(20.0*L) + C*3*L/140.0,   -a*13.0/(40.0*L) -  C*19.0*L/1680.0},
  108.         { -a*189.0/(40.0*L) - C*33*L/560.0,     a*54.0/(5.0*L)-C*27*L/70.0,        -a*297.0/(40*L) + C*27*L/560.0,    a*27.0/(20.0*L) +  C*3*L/140.0},
  109.         {  a*27.0/(20.0*L) + C*3*L/140.0,      -a*297.0/(40.0*L) + C*27*L/560.0,     a*54.0/(5.0*L) - C*27*L/70.0,    -a*189.0/(40.0*L) - C*33*L/560.0},
  110.         { -a*13.0/(40.0*L) - C*19.0*L/1680.0,   a*27.0/(20.0*L) + C*3*L/140.0,     -a*189.0/(40.0*L) - C*33*L/560.0,  a*37.0/(10.0*L) - C*8*L/105.0}
  111.        
  112.    };
  113.    
  114.     // Локальный вектор нагрузок (дополнительные слагаемые для первого и последнего элементов учитываются далее)
  115.     std::vector<double> local_b = { D * L / 8.0,
  116.                                     D*3.0 * L / 8.0,
  117.                                     D*3.0 * L / 8.0,
  118.                                     D * L / 8.0 };
  119.  
  120.    
  121.     // Производим матричные преобразования для обнуления элементов локальной матрицы жесткости, относящихся к внутренним узлам
  122.     for (size_t i = 1; i < 3; i++) {
  123.         for (size_t j = 0; j < 4; j++) {
  124.             if (std::fabs(local_matrix.at(j).at(i)) > EPS && i != j) {
  125.                 double  val = local_matrix.at(j).at(i) /local_matrix.at(i).at(i);
  126.                 local_b.at(j) -= val * local_b.at(i);
  127.                 for (size_t k = 0; k < 4; k++) {
  128.                     local_matrix.at(j).at(k) -= val *local_matrix.at(i).at(k);
  129.                 }
  130.             }
  131.             continue;
  132.         }
  133.     }
  134.    
  135.    
  136.     // Исключаем внутренние узлы из рассмотрения
  137.     std::vector< std::vector<double> >  local_matrix_mod  = {{ local_matrix.at(0).at(0), local_matrix.at(0).at(3) },
  138.                                                              { local_matrix.at(3).at(0), local_matrix.at(3).at(3) }};
  139.     std::vector<double> local_b_mod = { local_b.at(0),
  140.                                         local_b.at(3)};
  141.    
  142.     // Ансамблирование и получение глобальной матрицы жесткости для кубического КЭ
  143.     for (size_t i = 0; i < elems_num; i++) {
  144.         for (size_t j = 0; j < 2; j++) {
  145.             for (size_t k = 0; k < 2; k++) {
  146.                 A.at(i + j).at(i + k) += local_matrix_mod.at(j).at(k);
  147.             }
  148.         }
  149.     }
  150.         for (size_t i = 0; i < elems_num; i++) {
  151.         b.at(i) += local_b_mod.at(0);
  152.         b.at(i+1) += local_b_mod.at(1);
  153.     }
  154.        
  155.     // Учет ГУ
  156.     b.at(0) =local_b_mod.at(0) - a*usl_left;
  157.     b.at(elems_num) = usl_right;
  158.     A.at(elems_num).at(elems_num) = 1.0;
  159.     A.at(elems_num).at(elems_num - 1)=0.0;
  160.    
  161.     // Решение полученной СЛАУ методом Гаусса
  162.     std::vector<double> res = solve_with_gauss(A, b);
  163.     return res;
  164. }
  165.  
  166. double calc_abs_error(const std::vector<double>& y_real, const std::vector<double>& y) {
  167.     double max_err = 0.0;
  168.     for (size_t i = 0; i < y_real.size(); i++) {
  169.         double err = std::fabs(y_real.at(i) - y.at(i));
  170.         if (err > max_err) {
  171.             max_err = err;
  172.         }
  173.     }
  174.     return max_err;
  175. }
  176.  
  177. int main() {
  178.  
  179. //     std::vector<double> x(ELEMS_NUM + 1);
  180. //     for (size_t i = 0; i < x.size(); i++) {
  181. //         x.at(i) = X_BEGIN + i * L;
  182. //     }
  183. //     size_t x_size = x.size();
  184. //    
  185. // #ifdef CUBE
  186. //     std::vector<double> y = build_cube_solution(ELEMS_NUM);
  187. //    
  188. // #else
  189. //     std::vector<double> y = build_linear_solution(ELEMS_NUM);
  190. // #endif
  191. //     std::vector<double> y_real = build_analytical_solution(x);
  192. //    
  193. //
  194. //     FILE* gp = popen("gnuplot -persist", "w");
  195. //     fprintf(gp, "$predict << EOD\n");
  196. //     for (size_t i = 0; i < x_size; i++) {
  197. //         fprintf(gp, "%lf %lf\n", x.at(i), y.at(i));
  198. //     }
  199. //     fprintf(gp, "EOD\n");
  200. //     fprintf(gp, "$real << EOD\n");
  201. //     for (size_t i = 0; i < x_size; i++) {
  202. //         fprintf(gp, "%lf %lf\n", x.at(i), y_real.at(i));
  203. //     }
  204. //     fprintf(gp, "EOD\n");
  205. //     fprintf(gp, "set grid\n");
  206. //      fprintf(gp, "plot '$predict' using 1:2 with lp lc '#20155e' lw 1.5 pt 7 ps 0.5 title 'МКЭ-решение (%zu КЭ)'," "'$real' using 1:2 with lines lc rgb '#c93c20' lt 1 lw 2 title 'аналитическое решение (%zu КЭ)',\n", ELEMS_NUM, ELEMS_NUM);
  207. //     printf("Абсолютная погрешность: %e\n", calc_abs_error(y_real, y));
  208.    
  209.     //нахождение количества линейных КЭ
  210.     int N=ELEMS_NUM,n=0;
  211.     double err=10;
  212.    
  213.     while (err>CUB){
  214.         double L = (X_END - X_BEGIN) / N;
  215.         std::vector<double> x(N + 1);
  216.         for (size_t i = 0; i < x.size(); i++) {
  217.             x.at(i) = X_BEGIN + i * L;
  218.         }
  219.        
  220.         std::vector<double> y_r(N + 1);
  221.         std::vector<double> y(N + 1);
  222.        
  223.         y = build_linear_solution(N);
  224.         y_r = build_analytical_solution(x);
  225.        
  226.         err=calc_abs_error(y_r, y);
  227.         printf("Абсолютная погрешность: %e\n", calc_abs_error(y_r, y));
  228.         N+=1;
  229.         //n+=1;
  230.     }
  231.     std::cout<<"Количество линейных КЭ "<<N-1<<std::endl;
  232.     printf("Абсолютная погрешность: %e\n", err);
  233.  
  234.  
  235.     return 0;
  236. }
  237.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement