Лабораторная работа № 2. Решение уравнения Пуассона в трехмерной области методом Зейделя, страница 3

/* Грань Z=0 */

MPI_Irecv(z0,sendcounts[rank]*Iy,MPI_FLOAT,size-1,tag+3,MPI_COMM_WORLD,&req);

MPI_Wait(&req,&st);

for(i=i1;i<sendcounts[rank]+i1;i++)

for(j=0;j<Iy;j++)

F[i][j*Iz]=z0[(i-i1)*Iy+j];

/* Грань Z=Zm */

MPI_Irecv(z1,sendcounts[rank]*Iy,MPI_FLOAT,size-1,tag+4,MPI_COMM_WORLD,&req);

MPI_Wait(&req,&st);

for(i=i1;i<sendcounts[rank]+i1;i++)

for(j=0;j<Iy;j++)

F[i][(j+1)*Iz-1]=z1[(i-i1)*Iy+j];

}

free(y0);

free(y1);

free(z0);

free(z1);

/* Выделяем память для ро и заполняем нулями */

xdims(sendcounts,displs);

/* Для rank=0 считываем со 2-го слоя, т.к. 1-й не используется*/

sendcounts[0]--;

r=(float **)malloc(sendcounts[rank]*sizeof(float *));

for(i=0;i<sendcounts[rank];i++)

{  r[i]=(float *)malloc(Iy*Iz*sizeof(float ));

for(j=0;j<Iy*Iz;j++) r[i][j]=0;

}

/* Читаем данные для ро */

if(rank==size-1)

{if((fd=fopen("dat_r.txt","rt"))==NULL)

{printf("Запусти генератор1\n");

MPI_Finalize();

return(1);

}

for(k=0;k<size-1;k++)// по процессорам

{

for(i=0;i<sendcounts[k];i++)// по слоям

{

for(j=0;j<Iy*Iz;j++)

fscanf(fd,"%f",&x0[j]);

MPI_Send(&x0[0],Iy*Iz,MPI_FLOAT,k,tag+5,MPI_COMM_WORLD);   

}

}

/* Для rank=size-1 */

for(i=0;i<sendcounts[rank];i++)

for(j=0;j<Iy*Iz;j++)

fscanf(fd,"%f",&r[i][j]);

fclose(fd);

}

else

{

for(i=0;i<sendcounts[rank];i++)

MPI_Recv(&r[i][0],Iy*Iz,MPI_FLOAT,size-1,tag+5,MPI_COMM_WORLD,&st);

}

fclose(fd1);

xdims(sendcounts,displs);

flg=(int*)malloc(size*sizeof(int)); // массив флагов

for(i=0;i<size;i++) flg[i]=1;

/* Замеряем время */

if(!rank) gettimeofday(&tv1,(struct timezone*)0);

/*-------------------------- ВЫЧИСЛЕНИЯ -----------------------------*/

while(!flag)

{flag=1;

iter++;

/* Ожидаем «старый» слой от следующего процесса */

if(rank<size-1)

MPI_Irecv(&F[M-1][0],Iy*Iz,MPI_FLOAT,rank+1,tag+1,MPI_COMM_WORLD,&req);

/* отправляем первый «старый» слой предыдущему процессу и получаем «новый» слой от предыдущего процесса */

if(rank>0)

{ MPI_Isend(&F[1][0],Iy*Iz,MPI_FLOAT,rank-1,tag+1,MPI_COMM_WORLD,&req);

MPI_Recv(&F[0][0],Iy*Iz,MPI_FLOAT,rank-1,tag,MPI_COMM_WORLD,&st);

}

/* Вычисляем слои, кроме последнего */

for(i=1;i<M-2;i++)

flag*= vichisl(i);

/* для последнего слоя нужен слой от следующего процесса */

if(rank<size-1)

MPI_Wait(&req,&st);

/* Получаем последний слой */

flag*=vichisl(M-2);

/* отправляем последний слой следующему процессу */

if (rank<size-1)

MPI_Send(&F[M-2][0],Iy*Iz,MPI_FLOAT,rank+1,tag,MPI_COMM_WORLD); 

/* Получаем флаги */

MPI_Allgather(&flag,1,MPI_INT,flg,1,MPI_INT,MPI_COMM_WORLD);

flag=1;

for(i=0;i<size;i++) flag*=flg[i];

}

/*-------------------Вычисления окончены----------------------------- */

/* Замеряем время завершения вычислений */

if(!rank) gettimeofday(&tv2,(struct timezone*)0);

{ s=(tv2.tv_sec-tv1.tv_sec)+(tv2.tv_usec-tv1.tv_usec)*0.000001;

printf("Время исполнения %f с\nЧисло итераций %d\n",s,iter);

}

/*Запись в файл */

if(!rank)

{xdims(sendcounts,displs);

fd=fopen("rez.dat","wt");

fprintf(fd,"Количество процессоров: %d\n",size);

fprintf(fd,"Размерность данных: Ix=%d Iy=%d Iz=%d\n",Ix-1,Iy-1,Iz-1);

fprintf(fd,"Точность решения: %f\n",eps);

fprintf(fd,"Число итераций: %d\n",iter);

fprintf(fd,"Время исполнения: %f c\n\n",s);

fprintf(fd,"rank=0 sendc=%d \n",sendcounts[0]);

for(i=0;i<M-1;i++)

{ for(j=0;j<Iy;j++)

{for(k=0;k<Iz;k++)

fprintf(fd,"%f ",F[i][j*Iz+k]);

fprintf(fd,"\n");

}

fprintf(fd,"\n");

}

for(k=1;k<size;k++)// принимаем данные от других процессоров

{fprintf(fd,"rank=%d sendc=%d\n",k,sendcounts[k]);

for(i=0;i<sendcounts[k];i++)

{  MPI_Recv(x0,Iy*Iz,MPI_FLOAT,k,tag,MPI_COMM_WORLD,&st);

for(j=0;j<Iy;j++)

{ for(l=0;l<Iz;l++)

fprintf(fd,"%f ",x0[j*Iz+l]);

fprintf(fd,"\n");

}

fprintf(fd,"\n");

}

fprintf(fd,"\n");

}

fclose(fd);

}

else

{

for(i=0;i<sendcounts[rank];i++)

MPI_Send(&F[i+i1][0],Iy*Iz,MPI_FLOAT,0,tag,MPI_COMM_WORLD);

}

MPI_Finalize();

return(0);

}