Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdlib.h>
- #include <unistd.h>
- #include <time.h>
- #include <stdio.h>
- #include <math.h>
- #include <mpi.h>
- #include <sys/time.h>
- #define MAKE_GNUPLOT
- #define r 1000
- #define C 1e-6
- #define T_MAX 0.0001
- #define delta_t 0.00000001
- #define num_I 175
- int main(int argc, char **argv)
- {
- int myrank, total;
- // создание группы процессов
- // создание области связи, описываемая коммуникатором MPI_COMM_WORLD, которая объединяет все процессы
- // MPI_COMM_SELF - область для каждого из процессов
- // MPI_SELF - для одного процесса
- // MPI_COMM_WORLD - автоматически создаваемая общая область связи;дескриптор коммуникатора
- MPI_Init(&argc, &argv); // Инициализация коммуникационных средств MPI
- int NumberOfNodes = atoi(argv[1]);
- if (NumberOfNodes % 8 != 0)
- {
- MPI_Finalize();
- printf("NumberOfNodes / 8 = 0\n");
- exit(-1);
- }
- double *prev_u, *u;
- double *prev_U, *U, *T;
- double prev, final1, delta_T, U_const;
- struct timeval tv1, tv2, dtv;
- struct timezone tz;
- FILE *file, *file2;
- int start_time, end_time;
- int n, m, num_all;
- MPI_Status status; // Информация о принятом сообщении
- int i;
- int intBuf[2];
- // определение числа процессов в области связи коммуникатора
- MPI_Comm_size(MPI_COMM_WORLD, &total); // общее количество параллельных процессов в группе
- // возвращает номер процесса, вызвавшего эту функцию
- MPI_Comm_rank(MPI_COMM_WORLD, &myrank); // идентификатор (номера) процесса в группе
- if (!myrank)
- {
- file = fopen("data_test.txt", "w+");
- file2 = fopen("test_static.txt", "w+");
- num_all = NumberOfNodes;
- prev_U = (double *)malloc(sizeof(double) * num_all);
- U = (double *)malloc(sizeof(double) * num_all);
- T = (double *)malloc(sizeof(double) * (T_MAX / (10 * delta_t)));
- intBuf[0] = num_all; // общее кол-во узлов
- intBuf[1] = NumberOfNodes / total; // кол-во узлов, расчитывающихся на 1 процессе
- }
- // в лекциях; широковещательная посылка данных посылает сообщение из корневого процесса всем процессам группы, включая себя
- MPI_Bcast((void *)intBuf, 2, MPI_INT, 0, MPI_COMM_WORLD);
- n = intBuf[0];
- m = intBuf[1];
- prev_u = (double *)malloc(sizeof(double) * (m));
- u = (double *)malloc(sizeof(double) * (m));
- prev = final1 = 0;
- for (i = 0; i < m; i++)
- {
- prev_u[i] = 0;
- }
- // MPI_PROC_NULL - нуль процесс
- int NextProcNum = (myrank == total - 1) ? MPI_PROC_NULL : myrank + 1;
- int PrevProcNum = (myrank == 0) ? MPI_PROC_NULL : myrank - 1;
- if (!myrank)
- gettimeofday(&tv1, &tz);
- int j = 0;
- for (delta_T = delta_t; delta_T <= T_MAX; delta_T += delta_t, j++)
- {
- i = 0;
- U_const = 1;
- u[i] = prev_u[i] - ((2 * prev_u[i]) / r) * (delta_T / C);
- if (!myrank)
- u[i] = 100;
- else
- u[i] += ((prev + prev_u[i + 1]) / r) * (delta_T / C);
- for (i = 1; i < m - 1; i++)
- {
- if (myrank != 0 && i == 1)
- {
- u[i] = -50;
- }
- else
- {
- u[i] = ((prev_u[i - 1] - prev_u[i]) / r - (prev_u[i] - prev_u[i + 1]) / r) * (delta_T / C) + prev_u[i];
- }
- }
- u[i] = prev_u[i] - ((2 * prev_u[i]) / r) * (delta_T / C);
- if (myrank == total - 1)
- {
- u[i] = 0;
- }
- else
- {
- u[i] += ((prev_u[i - 1] + final1) / r) * (delta_T / C);
- }
- fflush(stdout);
- // MPI_Sendrecv - прием и передача сообщений
- if (myrank != total - 1)
- MPI_Sendrecv(&u[m - 1], 1, MPI_DOUBLE, NextProcNum, 2, &final1, 1, MPI_DOUBLE, NextProcNum, 2,
- MPI_COMM_WORLD, &status);
- fflush(stdout);
- if (myrank != 0)
- MPI_Sendrecv(&u[0], 1, MPI_DOUBLE, PrevProcNum, 2, &prev, 1, MPI_DOUBLE, PrevProcNum, 2,
- MPI_COMM_WORLD, &status);
- // MPI_Gather - для сбора однородных данных со всех процессов группы; из u -> U; m - кол-во узлов
- MPI_Gather((void *)u, m, MPI_DOUBLE, (void *)U, m, MPI_DOUBLE, 0, MPI_COMM_WORLD);
- #ifdef MAKE_GNUPLOT
- if (!myrank && (j % 10 == 0))
- {
- for (int i = 0; i < n; i++)
- fprintf(file, "%d %.10f\n", i, U[i]);
- fprintf(file, "\n\n");
- }
- // dop
- if (!myrank && (j % 200 == 0))
- {
- for (int i = 0; i < n; i++)
- {
- fprintf(file2, "%.10f %d %.10f\n", delta_T, i, U[i]);
- }
- fprintf(file2, "\n");
- }
- #endif
- for (i = 0; i < m; i++)
- prev_u[i] = u[i];
- }
- if (!myrank)
- {
- gettimeofday(&tv2, &tz);
- dtv.tv_sec = tv2.tv_sec - tv1.tv_sec;
- dtv.tv_usec = tv2.tv_usec - tv1.tv_usec;
- if (dtv.tv_usec < 0)
- {
- dtv.tv_usec += 1000000;
- --dtv.tv_sec;
- }
- printf("%ld s %ld ms\n", dtv.tv_sec, dtv.tv_usec);
- }
- #ifdef MAKE_GNUPLOT
- if (!myrank)
- {
- FILE *fid = fopen("comm_test.gnu", "w+");
- fprintf(fid, "set terminal gif animate loop 0\n");
- fprintf(fid, "set output 'lab4.gif'\n");
- fprintf(fid, "set xrange[0:%d]\n", n - 1);
- fprintf(fid, "set yrange[-200:200]\n");
- fprintf(fid, "set grid ytics mytics\n");
- fprintf(fid, "set grid xtics mytics\n");
- fprintf(fid, "set mytics 1\n");
- fprintf(fid, "set grid \n");
- fprintf(fid, "do for [i=0:%d]{\n", (int)(T_MAX / (10 * delta_t)));
- fprintf(fid, "plot 'data_test.txt' index i using 1:2 smooth bezier\npause 0.1}\npause -1\n");
- fclose(fid);
- }
- // dop
- if (!myrank)
- {
- FILE *comm_static = fopen("comm_static.gnu", "w+");
- fprintf(comm_static, "set cbrange [-50:100]\n");
- fprintf(comm_static, "plot 'test_static.txt' using 2:1:3 with image\n");
- fprintf(comm_static, "pause(100)\n");
- FILE *comm_balls = fopen("comm_balls", "w+");
- fprintf(comm_balls, "set style fill transparent solid 1 noborder\n");
- fprintf(comm_balls, "set style circle radius 0.3\n");
- fprintf(comm_balls, "set cbrange [-50:100]\n");
- fprintf(comm_balls, "plot 'test_static.txt' using 2:1:3 with circles palette\n");
- fprintf(comm_balls, "pause(100)\n");
- }
- #endif
- if (!myrank)
- fclose(file);
- MPI_Finalize(); // MPI_Finalize - окончание работы
- exit(0);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement