Advertisement
BorrowTheProgrammer

lab4

Jun 5th, 2022
869
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.26 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include <unistd.h>
  3. #include <time.h>
  4. #include <stdio.h>
  5. #include <math.h>
  6. #include <mpi.h>
  7. #include <sys/time.h>
  8.  
  9. #define MAKE_GNUPLOT
  10. #define r 1000
  11. #define C 1e-6
  12. #define T_MAX 0.0001
  13. #define delta_t 0.00000001
  14. #define num_I 175
  15.  
  16. int main(int argc, char **argv)
  17. {
  18.     int myrank, total;
  19.  
  20.     // создание группы процессов
  21.     // создание области связи, описываемая коммуникатором MPI_COMM_WORLD, которая объединяет все процессы
  22.     // MPI_COMM_SELF - область для каждого из процессов
  23.     // MPI_SELF - для одного процесса
  24.     // MPI_COMM_WORLD - автоматически создаваемая общая область связи;дескриптор коммуникатора
  25.     MPI_Init(&argc, &argv); // Инициализация коммуникационных средств MPI
  26.  
  27.     int NumberOfNodes = atoi(argv[1]);
  28.  
  29.     if (NumberOfNodes % 8 != 0)
  30.     {
  31.         MPI_Finalize();
  32.         printf("NumberOfNodes  / 8 = 0\n");
  33.         exit(-1);
  34.     }
  35.  
  36.     double *prev_u, *u;
  37.     double *prev_U, *U, *T;
  38.     double prev, final1, delta_T, U_const;
  39.     struct timeval tv1, tv2, dtv;
  40.     struct timezone tz;
  41.     FILE *file, *file2;
  42.     int start_time, end_time;
  43.     int n, m, num_all;
  44.     MPI_Status status; // Информация о принятом сообщении
  45.     int i;
  46.     int intBuf[2];
  47.  
  48.     // определение числа процессов в области связи коммуникатора
  49.     MPI_Comm_size(MPI_COMM_WORLD, &total); // общее количество параллельных процессов в группе
  50.  
  51.     // возвращает номер процесса, вызвавшего эту функцию
  52.     MPI_Comm_rank(MPI_COMM_WORLD, &myrank); // идентификатор (номера) процесса в группе
  53.  
  54.     if (!myrank)
  55.     {
  56.         file = fopen("data_test.txt", "w+");
  57.         file2 = fopen("test_static.txt", "w+");
  58.         num_all = NumberOfNodes;
  59.         prev_U = (double *)malloc(sizeof(double) * num_all);
  60.         U = (double *)malloc(sizeof(double) * num_all);
  61.         T = (double *)malloc(sizeof(double) * (T_MAX / (10 * delta_t)));
  62.         intBuf[0] = num_all;               // общее кол-во узлов
  63.         intBuf[1] = NumberOfNodes / total; // кол-во узлов, расчитывающихся на 1 процессе
  64.     }
  65.  
  66.     // в лекциях; широковещательная посылка данных посылает сообщение из корневого процесса всем процессам группы, включая себя
  67.     MPI_Bcast((void *)intBuf, 2, MPI_INT, 0, MPI_COMM_WORLD);
  68.     n = intBuf[0];
  69.  
  70.     m = intBuf[1];
  71.     prev_u = (double *)malloc(sizeof(double) * (m));
  72.     u = (double *)malloc(sizeof(double) * (m));
  73.     prev = final1 = 0;
  74.  
  75.     for (i = 0; i < m; i++)
  76.     {
  77.         prev_u[i] = 0;
  78.     }
  79.  
  80.     // MPI_PROC_NULL - нуль процесс
  81.     int NextProcNum = (myrank == total - 1) ? MPI_PROC_NULL : myrank + 1;
  82.     int PrevProcNum = (myrank == 0) ? MPI_PROC_NULL : myrank - 1;
  83.  
  84.     if (!myrank)
  85.         gettimeofday(&tv1, &tz);
  86.     int j = 0;
  87.     for (delta_T = delta_t; delta_T <= T_MAX; delta_T += delta_t, j++)
  88.     {
  89.         i = 0;
  90.         U_const = 1;
  91.         u[i] = prev_u[i] - ((2 * prev_u[i]) / r) * (delta_T / C);
  92.         if (!myrank)
  93.             u[i] = 100;
  94.         else
  95.             u[i] += ((prev + prev_u[i + 1]) / r) * (delta_T / C);
  96.         for (i = 1; i < m - 1; i++)
  97.         {
  98.             if (myrank != 0 && i == 1)
  99.             {
  100.                 u[i] = -50;
  101.             }
  102.             else
  103.             {
  104.                 u[i] = ((prev_u[i - 1] - prev_u[i]) / r - (prev_u[i] - prev_u[i + 1]) / r) * (delta_T / C) + prev_u[i];
  105.             }
  106.         }
  107.         u[i] = prev_u[i] - ((2 * prev_u[i]) / r) * (delta_T / C);
  108.         if (myrank == total - 1)
  109.         {
  110.             u[i] = 0;
  111.         }
  112.         else
  113.         {
  114.             u[i] += ((prev_u[i - 1] + final1) / r) * (delta_T / C);
  115.         }
  116.         fflush(stdout);
  117.         //        MPI_Sendrecv - прием и передача сообщений
  118.         if (myrank != total - 1)
  119.             MPI_Sendrecv(&u[m - 1], 1, MPI_DOUBLE, NextProcNum, 2, &final1, 1, MPI_DOUBLE, NextProcNum, 2,
  120.                          MPI_COMM_WORLD, &status);
  121.         fflush(stdout);
  122.         if (myrank != 0)
  123.             MPI_Sendrecv(&u[0], 1, MPI_DOUBLE, PrevProcNum, 2, &prev, 1, MPI_DOUBLE, PrevProcNum, 2,
  124.                          MPI_COMM_WORLD, &status);
  125.         // MPI_Gather - для сбора однородных данных со всех процессов группы; из u -> U; m - кол-во узлов
  126.         MPI_Gather((void *)u, m, MPI_DOUBLE, (void *)U, m, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  127.  
  128. #ifdef MAKE_GNUPLOT
  129.         if (!myrank && (j % 10 == 0))
  130.         {
  131.             for (int i = 0; i < n; i++)
  132.                 fprintf(file, "%d %.10f\n", i, U[i]);
  133.             fprintf(file, "\n\n");
  134.         }
  135.  
  136.         // dop
  137.         if (!myrank && (j % 200 == 0))
  138.         {
  139.             for (int i = 0; i < n; i++)
  140.             {
  141.                 fprintf(file2, "%.10f %d %.10f\n", delta_T, i, U[i]);
  142.             }
  143.  
  144.             fprintf(file2, "\n");
  145.         }
  146.  
  147. #endif
  148.         for (i = 0; i < m; i++)
  149.             prev_u[i] = u[i];
  150.     }
  151.     if (!myrank)
  152.     {
  153.         gettimeofday(&tv2, &tz);
  154.         dtv.tv_sec = tv2.tv_sec - tv1.tv_sec;
  155.         dtv.tv_usec = tv2.tv_usec - tv1.tv_usec;
  156.         if (dtv.tv_usec < 0)
  157.         {
  158.             dtv.tv_usec += 1000000;
  159.             --dtv.tv_sec;
  160.         }
  161.         printf("%ld s %ld ms\n", dtv.tv_sec, dtv.tv_usec);
  162.     }
  163. #ifdef MAKE_GNUPLOT
  164.     if (!myrank)
  165.     {
  166.         FILE *fid = fopen("comm_test.gnu", "w+");
  167.         fprintf(fid, "set terminal gif animate loop 0\n");
  168.         fprintf(fid, "set output 'lab4.gif'\n");
  169.         fprintf(fid, "set xrange[0:%d]\n", n - 1);
  170.         fprintf(fid, "set yrange[-200:200]\n");
  171.         fprintf(fid, "set grid ytics mytics\n");
  172.         fprintf(fid, "set grid xtics mytics\n");
  173.         fprintf(fid, "set mytics 1\n");
  174.         fprintf(fid, "set grid \n");
  175.         fprintf(fid, "do for [i=0:%d]{\n", (int)(T_MAX / (10 * delta_t)));
  176.         fprintf(fid, "plot 'data_test.txt' index i using 1:2 smooth bezier\npause 0.1}\npause -1\n");
  177.         fclose(fid);
  178.     }
  179.  
  180.     // dop
  181.     if (!myrank)
  182.     {
  183.         FILE *comm_static = fopen("comm_static.gnu", "w+");
  184.         fprintf(comm_static, "set cbrange [-50:100]\n");
  185.         fprintf(comm_static, "plot 'test_static.txt' using 2:1:3 with image\n");
  186.         fprintf(comm_static, "pause(100)\n");
  187.  
  188.         FILE *comm_balls = fopen("comm_balls", "w+");
  189.         fprintf(comm_balls, "set style fill transparent solid 1 noborder\n");
  190.         fprintf(comm_balls, "set style circle radius 0.3\n");
  191.         fprintf(comm_balls, "set cbrange [-50:100]\n");
  192.         fprintf(comm_balls, "plot 'test_static.txt' using 2:1:3 with circles palette\n");
  193.         fprintf(comm_balls, "pause(100)\n");
  194.     }
  195.  
  196. #endif
  197.     if (!myrank)
  198.         fclose(file);
  199.     MPI_Finalize(); // MPI_Finalize - окончание работы
  200.     exit(0);
  201. }
  202.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement