/* 热分布问题*/
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <gl/glut.h>
#include <gl/gl.h>
#include <gl/glu.h>
#define LIMIT 1000
#define bottom_value 1.0
#define top_value 1.0
#define left_value 1.0
#define right_value 1.0
#define ROW 200
#define COL 200
float h[ROW][COL],g[ROW][COL];
void SetupRC (void) ; //初始化OpenGL场景
void RenderScene(void) ; //场景的绘制函数
void ChangeSize(GLsizei width, GLsizei height) ;
void Calculate(int highrow, int lowrow, int myid, int numprocs)
{
int j , k , iteration ;
for(iteration=0;iteration<LIMIT;iteration++)
{
for(k=lowrow;k<=highrow;k++)
{
for(j=0;j<COL;j++)
{
if(k==0)
g[k][j]=bottom_value;
else if(k==ROW-1)
g[k][j]=top_value;
else if(j==0||j==COL-1)
g[k][j]=h[k][j];
else
g[k][j]=0.25*(h[k-1][j]+h[k+1][j]+h[k][j-1]+h[k][j+1]);
}
}
for(k=lowrow;k<=highrow;k++)
for(j=0;j<COL;j++)
h[k][j]=g[k][j];
if(numprocs>1)
{
if(myid%2==0)//若是偶数号进程则先发送后接收
{
if(myid>0)
MPI_Send(&g[lowrow][0],COL,MPI_FLOAT,myid-1,0,MPI_COMM_WORLD);
if(myid<numprocs-1)
MPI_Send(&g[highrow][0],COL,MPI_FLOAT,myid+1,0,MPI_COMM_WORLD);
if(myid<numprocs-1)
MPI_Recv(&h[highrow+1][0],COL,MPI_FLOAT,myid+1,0,MPI_COMM_WORLD,0);
if(myid>0)
MPI_Recv(&h[lowrow-1][0],COL,MPI_FLOAT,myid-1,0,MPI_COMM_WORLD,0);
}
else//若是奇数号进程则先接收后发送
{
if(myid<numprocs-1)
MPI_Recv(&h[highrow+1][0],COL,MPI_FLOAT,myid+1,0,MPI_COMM_WORLD,0);
if(myid>0)
MPI_Recv(&h[lowrow-1][0],COL,MPI_FLOAT,myid-1,0,MPI_COMM_WORLD,0);
if(myid>0)
MPI_Send(&g[lowrow][0],COL,MPI_FLOAT,myid-1,0,MPI_COMM_WORLD);
if(myid<numprocs-1)
MPI_Send(&g[highrow][0],COL,MPI_FLOAT,myid+1,0,MPI_COMM_WORLD);
}
}
}
}
int main(int argc,char *argv[])
{
int myid,numprocs;
int step,highrow,lowrow ;
int i,j,k;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
//数据赋初值
step=ROW/numprocs;
lowrow=myid*step;
if(myid==numprocs-1)
highrow=ROW-1;
else
highrow=lowrow+step-1;
if(myid==0)
{
printf("Processes number: %d\n",numprocs);
//初始化数据:
for(i=0;i<ROW;i++)
{
for(j=0;j<COL;j++)
{
if(i==0)
{
h[i][j]=bottom_value;
continue;
}
if(i==ROW-1)
{
h[i][j]=top_value;
continue;
}
if(j==0)
{
h[i][j]=left_value;
continue;
}
if(j==COL-1)
{
h[i][j]=right_value;
continue;
}
h[i][j]=0.0;
}
}
//分配任务,将初始数据送到各个进程
for(i=1;i<numprocs;i++)
{
j=i*step;
if(i!=numprocs-1)
{
MPI_Send(&h[j][0],step*COL,MPI_FLOAT,i,0,MPI_COMM_WORLD);
}
else
{
k=ROW-i*step;
MPI_Send(&h[j][0],k*COL,MPI_FLOAT,i,0,MPI_COMM_WORLD);
}
}
Calculate( highrow, lowrow, myid, numprocs) ;
//接收各个进程送来的数据
for(i=1;i<numprocs;i++)
{
j=i*step;
if(i!=numprocs-1)
MPI_Recv(&h[j][0],COL*step,MPI_FLOAT,i,0,MPI_COMM_WORLD,0);
else
{
k=ROW-i*step;
MPI_Recv(&h[j][0],COL*k,MPI_FLOAT,i,0,MPI_COMM_WORLD,0);
}
printf("Received data from process %d\n",i);
}
MPI_Finalize(); //0号进程MPI_Finalize()的正确位置
//绘制计算结果:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(COL , ROW);
glutCreateWindow("Jacobi");
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
SetupRC();
glutMainLoop();
}
else
{
if(myid!=numprocs-1)
MPI_Recv(&h[lowrow][0],COL*step,MPI_FLOAT,0,0,MPI_COMM_WORLD,0);
else
{
k=ROW-myid*step;
MPI_Recv(&h[lowrow][0],COL*k,MPI_FLOAT,0,0,MPI_COMM_WORLD,0);
}
Calculate( highrow, lowrow, myid, numprocs) ;
//向主进程发送数据
if(myid!=numprocs-1)
MPI_Send(&h[lowrow][0],COL*step,MPI_FLOAT,0,0,MPI_COMM_WORLD);
else
{
k=ROW-myid*step;
MPI_Send(&h[lowrow][0],COL*k,MPI_FLOAT,0,0,MPI_COMM_WORLD);
}
MPI_Finalize(); //其他进程MPI_Finalize()的正确位置
}
//MPI_Finalize();
/* MPI_Finalize()不可以放在这里,因为0号进程已经把控制权移交给glutMainLoop(),
所以0号进程的glutMainLoop()之后的代码不会被执行,
其他进程的MPI_Finalize()因此也不会执行完毕,进程不会自动结束 */
printf("Process %d exited.\n",myid);
return 0;
}
//初始化OpenGL场景
void SetupRC (void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT); //设置明暗处理
}
void RenderScene(void)
{
int i,j;
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除缓存
glBegin(GL_POINTS); //开始画点
for(i=0; i<ROW; i++)
for(j=0; j<COL; j++)
{
glColor3f (h[i][j], 0.0f, 0.0f); //设置颜色为红色
glVertex3f((float)j,float(i),0.0); //设置点在世界坐标系中的坐标
}
glEnd(); //画点结束
glutSwapBuffers();
}
// Called by GLUT library when the window has chanaged size
void ChangeSize(GLsizei width, GLsizei height)
{
// Prevent a divide by zero
if(height == 0)
height = 1;
// Set Viewport to window dimensions
glViewport((width-COL)/2, (height-ROW)/2, COL, ROW);
// Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Establish clipping volume (left, right, bottom, top, near, far)
glOrtho (0, COL, 0, ROW, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
评论0