#include #include #include #include "mpi.h" #include //#define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) //#define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) struct Config { int Kx; //разбиение на процессы по осям int Ky; int Nx; //разбиение на отрезки по осям, дб. кратно Кх и Ку int Ny; int Nt; //число интервалов по времени }; //глобальные массивы для хранения значений во всей области на 0-вом процессе double** global_ro; double** global_u; double** global_v; double** global_eps; double** global_P; double** global_E; //локальные массивы, с которыми работает на каждом процессе double** local_ro; double** local_u; double** local_v; double** local_eps; double** local_P; double** local_E; //массивы с фиктивными ячейками для просчета local double** complex_local_ro; double** complex_local_u; double** complex_local_v; double** complex_local_eps; double** complex_local_P; double** complex_local_E; int myid; //идентификатор текущего процесса в системе const double gamma; //показатель адиабаты const double Lx = 1; //длины промежутков по осям const double Ly = 2; const double Lt = 3; //промежуток по времени const double granica1 = 1.8; //граница разделения области 1 и 2 const double fi = 1; //граница разделения области 2 и 3 int numprocs; //число процессов int namelen; //-----------------------------------------что такое? char processor_name[MPI_MAX_PROCESSOR_NAME]; //имя процесса double startwtime; //время начала просчета double endwtime; //время конца просчета void* mpi_buf; //------------------------------что такое? double* P, E, eps, u, v, ro; //массивы содержащие начальные значения в каждой области int mpi_buf_size; //размер буфера int nx, ny; // размеры в ячейках локальногом массива MPI_Status* mpi_status; //статус double dv(double g,int i,int j,int k,int l) { //вычисление впомогательной константы для аппроксимации производной return max(sqrt(g*(g-1)*complex_local_eps[i][j])+sqrt(complex_local_u[i][j]*complex_local_u[i][j]+complex_local_v[i][j]*complex_local_v[i][j]),sqrt(g*(g-1)*complex_local_eps[i+k][j+l])+sqrt(complex_local_u[i+k][j+l]*complex_local_u[i+k][j+l]+complex_local_v[i+k][j+l]*complex_local_v[i+k][j+l]); } int ident_oblast(int i, int j) { //смотрим, какой области принадлежит текущая ячейка с левым нижним углом i,j if(((j*hy)fi)) return 23; if(((j*hy)granica1)) return 12; if(((j*hy)=fi)&&(((j+1)*hy)<=granica1)) return 2; if(((j*hy)>=granica1)&&(((j+1)*hy)<=Ly)) return 1; return 0; } void create_first_step() { nx = config->Nx/config->Kx; //размер в интервалах локального массива для пересчета ny = config->Ny/config->Ky; smeshX = nx*(myid%config->Kx); //смещение в большом массиве для (0,0)-го элемента нашего массива smeshY = ny*(myid/config->Ky); double S = hx*hy; //площадь ячейки for(int j=0; jnx*getKx(config); i++) { for(j = 0; j < config->ny*getKy(config); j++) { fprintf(log, "\t%d", global[i][j]); } fprintf(log, "\n"); } fclose (log); } free(filename); } void calc(struct Config* config) { create_parameters(); //заполнили нужные массивы начальных данных для 3-х областей create_first_step(); //заполняем локальные массивы значениями for(int k=1; k<=Nt; k++) //для каждого момента времени { //забиваем в комплекс значения из локал for(int i=0; i<=nx; i++) { for(int j=0; j<=ny; j++) { complex_local_ro[i+1,j+1]=local_ro[i,j]; complex_local_eps[i+1,j+1]=local_eps[i,j]; complex_local_u[i+1,j+1]=local_u[i,j]; complex_local_v[i+1,j+1]=local_v[i,j]; complex_local_E[i+1,j+1]=local_E[i,j]; complex_local_P[i+1,j+1]=local_P[i,j]; } } //рассылаем границы и запрашиваем в комплекс фиктивные ячейки от соседей first_send(config); //просчитываем новый локал по старому комплексу real_calc(config); //посылка в 0вой процесс просчитанных значений из локал get_data(config); if(myid == 0) { write_to_log(config); } } } double** init_array(int size_x, int size_y, double value) { int i,j; double** ptr = (double**)malloc(sizeof(double*)*size_x); for(i = 0; inx+2, config->ny+2, 0); complex_local_u = init_array(config->nx+2, config->ny+2, 0); complex_local_v = init_array(config->nx+2, config->ny+2, 0); complex_local_eps = init_array(config->nx+2, config->ny+2, 0); complex_local_P = init_array(config->nx+2, config->ny+2, 0); complex_local_E = init_array(config->nx+2, config->ny+2, 0); //!!!!!!!!!!!!!!!!!!!!!!ЗДЕСЬ НАДО СОЗДАТЬ ЛОКАЛ-МАССИВЫ!!!!!!!!!!!!!!!!!!!!!!!!!!!! //НАФИГА ЭТО НАДО? ВСЕ ЭТИ БУФ САЙЗЫ mpi_buf_size = sizeof(double)*(config->nx*getKx(config) + config->ny*getKy(config) + MPI_BSEND_OVERHEAD); mpi_buf = malloc(mpi_buf_size); MPI_Buffer_attach(mpi_buf, mpi_buf_size); free(buf); return 0; } else { debug_info(config, "Error in MPI_Comm_rank"); } } else { debug_info(config, "Error in MPI_Comm_size"); } free(buf); return 1; } int fin( struct Config* config) { //ЭТО ЕЩЕ НАДО ПЕРЕПИСАТЬ С УЧЕТОМ НАШИХ БОЛЬШИХ МАССИВОВ!!!!!!!!!!!!!!! char* buf = malloc(sizeof(char)*512); free_array(complex_local, config->nx); //еще тут бы неплохо освободить local, но вот как я пока придумать не могу. MPI_Buffer_detach(&mpi_buf, &mpi_buf_size); if (myid == 0) {//нулевой процесс записывает время выполнения проги free_array(global, config->nx*getKx(config)); endwtime = MPI_Wtime(); snprintf(buf, 512, "wall clock time = %f\n", endwtime-startwtime); debug_info(config, buf); } free(buf); } struct Config* parsing(int argc, char** argv) { // инициализируем переменные struct Config* config = malloc(sizeof(struct Config)); int c; // устанавливаем значения конфигурации по умолчанию config->Kx = 1; config->Ky = 1; config->Nx = 8; config->Ny = 8; config->Nt = 10; // НИФИГА НЕ ПОНЯТНО!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // разбираем все аргументы используя getopt. optarg это глобальная // пермененная типа char* в которую записываются аргументы опции, // если они есть while ((c = getopt (argc, argv, "x:y:X:Y:T")) != -1) { switch (c) { case 'x': config->Kx = atoi(optarg); break; case 'y': config->Ky = atoi(optarg); break; case 'X': config->Nx = atoi(optarg); break; case 'Y': config->Ny = atoi(optarg); break; case 't': config->Nt = atoi(optarg); break; case '?': if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); return NULL; default: abort (); } } // если не установили kx и ky выставляем автоматический расчет kx_ky //if(config->kx == 0 && config->ky == 0){ // config->auto_kx_ky = 1; // } } void create_parameters() { P = malloc(sizeof(double)*3); ro = malloc(sizeof(double)*3); u = malloc(sizeof(double)*3); v = malloc(sizeof(double)*3); eps = malloc(sizeof(double)*3); E = malloc(sizeof(double)*3); u[0] = 10.0; //от балды u[1] = 0; u[2] = 0; eps[0]=5.0; //от балды eps[1]=6.0; //от балды eps[2]=7.0; //от балды for(int i = 0; i < 3; i++) { v[i]=0; E[i]=eps[i]+(u[i]*u[i]+v[i]*v[i])/2; } ro[0]=3.0; //от балды ro[1]=2.0; //от балды ro[2]=1.0; P[0]=(gamma-1)*ro[0]*eps[0]; P[1] = (gamma-1)*ro[1]*eps[1]; P[2]=1.0; } int main(int argc, char** argv) { int n; //зачем нужна эта переменная???? if(!MPI_Init(&argc, &argv)){ struct Config* config = parsing(argc, argv); //разбираем аргументы входной строки init(config); //выделяем память для всех нужных объектов calc(config); //производим вычисления fin(config); //освобождаем память if(MPI_Finalize()){ fprintf(stderr,"Not finialize mpi :(\n"); } } else { fprintf(stderr,"Not init mpi :(\n"); } return 0; }