c.c
上传用户:jsljixie
上传日期:2013-08-15
资源大小:827k
文件大小:15k
源码类别:

并行计算

开发平台:

Visual C++

  1. #include <stdio.h>
  2. #include <mpi.h>
  3. #include <math.h>
  4. int my_rank,group_size,sub_group;
  5. int n_all;
  6. double pointx[30],pointy[30];
  7. double tempx[2],tempy[2],xtemp[4],ytemp[4];
  8. MPI_Status status;
  9. int location[30];
  10. /*获得y坐标最小的点,坐标值保存到保存到tempx,tempy数组中*/
  11. void getymin( )
  12. {
  13.     int i,index=0;
  14.     double tempvalue=pointy[0];
  15.     for(i=1;i<n_all;i++)
  16.     {
  17.         if(pointy[i]<tempvalue)
  18.         {
  19.             tempvalue=pointy[i];
  20.             index=i;
  21.         }
  22.         else
  23.         {
  24. /*若y坐标相同,则取x坐标小者。这是为了保证(tempx[0],tempy[0])->(tempx[1],tempy[1])为逆时针方向*/
  25.             if(pointy[i]==tempvalue)
  26.                 if(pointx[index]>pointx[i])
  27.                     index = i;
  28.         }
  29.     }
  30.     tempx[0]=pointx[index];
  31.     tempy[0]=pointy[index];
  32. /*如果y坐标最小的极点只有1点,就复制该点*/
  33.     tempx[1]=tempx[0];
  34.     tempy[1]=tempy[0];
  35. /*考察极点是否多于1点*/
  36.     for(i=0;i<n_all;i++)
  37.         if((pointy[i]==tempy[1])&&(pointx[i]>tempx[1]))
  38.     {
  39. /*极点多于1点,取x坐标大者,保存最后一个极点的坐标*/
  40.         tempx[1]=pointx[i];
  41.         tempy[1]=pointy[i];
  42.     }
  43.     return;
  44. }
  45. /*获得y坐标最大的点,保存到tempx,tempy数组中*/
  46. void getymax()
  47. {
  48.     int i,index=0;
  49.     double temp=pointy[0];
  50.     for(i=1;i<n_all;i++)
  51.     {
  52.         if(pointy[i]>temp)
  53.         {
  54.             temp=pointy[i];
  55.             index=i;
  56.         }
  57.         else
  58.         {
  59. /*若y坐标相同,则取x坐标大者。这是为了保证(tempx[0],tempy[0])->(tempx[1],tempy[1])为逆时针方向*/
  60.             if(temp==pointy[i])
  61.                 if(pointx[i]>pointx[index])
  62.                     index=i;
  63.         }
  64.     }
  65. /*保存YMAX极点坐标*/
  66.     tempx[0]=pointx[index];
  67.     tempy[0]=pointy[index];
  68. /*如果y坐标最大的极点只有1点,就复制该点*/
  69.     tempx[1]=tempx[0];
  70.     tempy[1]=tempy[0];
  71. /*考察极点是否多于1点*/
  72.     for(i=0;i<n_all;i++)
  73.     {
  74.         if((pointy[i]==tempy[1])&&(pointx[i]<tempx[1]))
  75.         {
  76. /*极点多于1点,取x坐标小者,保存最后一个极点的坐标*/
  77.             tempx[1]=pointx[i];
  78.             tempy[1]=pointy[i];
  79.         }
  80.     }
  81.     return;
  82. }
  83. /*获得x坐标最小的点,坐标保存到tempx,tempy数组中*/
  84. void getxmin()
  85. {
  86.     int i,index=0;
  87.     double temp=pointx[0];
  88.     for(i=1;i<n_all;i++)
  89.     {
  90.         if(pointx[i]<temp)
  91.         {
  92.             temp=pointx[i];
  93.             index=i;
  94.         }
  95.         else
  96.         {
  97. /*若x坐标相同,则取y坐标大者。这是为了保证(tempx[0],tempy[0])->(tempx[1],tempy[1])为逆时针方向*/
  98.             if(pointx[i]==temp)
  99.                 if(pointy[index]<pointy[i])
  100.                     index=i;
  101.         }
  102.     }
  103. /*保存XMIN极点坐标*/
  104.     tempx[0]=pointx[index];
  105.     tempy[0]=pointy[index];
  106. /*如果x坐标最小的极点只有1点,就复制该点*/
  107.     tempx[1]=tempx[0];
  108.     tempy[1]=tempy[0];
  109. /*考察极点是否多于1点*/
  110.     for(i=0;i<n_all;i++)
  111.     {
  112.         if((pointx[i]==tempx[1])&&(pointy[i]<tempy[1]))
  113.         {
  114. /*极点多于1点,取y坐标小者,保存最后一个极点的坐标*/
  115.             tempx[1]=pointx[i];
  116.             tempy[1]=pointy[i];
  117.         }
  118.     }
  119.     return;
  120. }
  121. /*获得x坐标最大的点,其坐标值保存保存到tempx,tempy数组中*/
  122. void getxmax()
  123. {
  124.     int i,index=0;
  125.     double temp=pointx[0];
  126.     for(i=1;i<n_all;i++)
  127.     {
  128.         if(pointx[i]>temp)
  129.         {
  130.             temp=pointx[i];
  131.             index=i;
  132.         }
  133.         else
  134.         {
  135. /*若x坐标相同,则取y坐标小者。这是为了保证(tempx[0],tempy[0])->(tempx[1],tempy[1])为逆时针方向*/
  136.             if(temp==pointx[i])
  137.                 if(pointy[index]>pointy[i])
  138.                     index=i;
  139.         }
  140.     }
  141. /*保存XMAX极点坐标*/
  142.     tempx[0]=pointx[index];
  143.     tempy[0]=pointy[index];
  144. /*如果x坐标最大的极点只有1点,就复制该点*/
  145.     tempx[1]=tempx[0];
  146.     tempy[1]=tempy[0];
  147. /*考察极点是否多于1点*/
  148.     for(i=0;i<n_all;i++)
  149.     {
  150.         if((pointx[i]==tempx[1])&&(pointy[i]>tempy[1]))
  151.         {
  152. /*极点多于1点,取y坐标大者,保存第2个极点的坐标*/
  153.             tempx[1]=pointx[i];
  154.             tempy[1]=pointy[i];
  155.         }
  156.     }
  157.     return;
  158. }
  159. /*temp[x],temp[y]设置两个值的作用是为了有多个最值时,保存首尾两个,后面划分
  160. 区域时分别以这两个为端点,中间就没有其他的点了*/
  161. /*确定是属于哪一部分*/
  162. void getincludedvertex(int tag)
  163. {
  164.     double linea,lineb,dist;
  165.     int i,count=0;
  166. /*若该边已退化成一个点, 则除此点外无其它点在处理区域内*/
  167.     if((tempx[1]==tempx[0])&&(tempy[1]==tempy[0]))
  168.     {
  169.         n_all=1;
  170.         pointx[0]=tempx[1];
  171.         pointy[0]=tempy[1];
  172.     }
  173.     else
  174.     {
  175. /*根据两端点坐标确定直线的斜率和参数*/
  176.         linea=(tempy[1]-tempy[0])/(tempx[1]-tempx[0]);
  177.         lineb=tempy[1]-linea*tempx[1];
  178. /*根据点在直线的哪一侧来确定该顶点是否在处理区域内*/
  179.         for(i=0;i<n_all;i++)
  180.         {
  181.             dist=linea*pointx[i]+lineb-pointy[i];
  182.             if(tag*dist<0)
  183.             {
  184.                 pointx[count]=pointx[i];
  185.                 pointy[count++]=pointy[i];
  186.             }
  187.         }
  188. /*调整各点的位置以加入两个端点*/
  189.         for(i=0;i<count;i++)
  190.         {
  191.             pointx[count-i]=pointx[count-1-i];
  192.             pointy[count-i]=pointy[count-1-i];
  193.         }
  194. /*将两个端点放在两端*/
  195.         pointx[0]=tempx[0];
  196.         pointy[0]=tempy[0];
  197.         pointx[count+1]=tempx[1];
  198.         pointy[count+1]=tempy[1];
  199.         count+=2;
  200. /*更新n_all为要处理的新的表列中的点的数量*/
  201.         n_all=count;
  202.     }
  203. }
  204. /*确定此点的后一点的序号,并放入location[]中*/
  205. void nextindex(int i,int x,int y)
  206. {
  207.     double x1,y1,temp,valuemax=0;
  208.     int j;
  209.     x1=pointx[i];
  210.     y1=pointy[i];
  211. /*遍历各顶, 将有最小极角点的序号作为自己的Nextindex值*/
  212.     for(j=0;j<n_all;j++)
  213.     {
  214.         if(((pointx[j]-x1)*x+(pointy[j]-y1)*y)>0)
  215.         {
  216. /*由极角的余弦或其余角的正弦来判断极角大小*/
  217.             temp=((pointx[j]-x1)*x+(pointy[j]-y1)*y)/(sqrt((pointx[j]-x1)*(pointx[j]-x1)+(pointy[j]-y1)*(pointy[j]-y1)));
  218.             if(temp>valuemax)
  219.             {
  220.                 location[i]=j;
  221.                 valuemax=temp;
  222.             }
  223.         }
  224.     }
  225.     if(valuemax==0)
  226.         location[i]=-1;
  227. }
  228. /*输出点的序列*/
  229. void output(int rank)
  230. {
  231.     int j=0,index,temp;
  232.     double xtem,ytem;
  233.     int flag=0;
  234.     printf("输出的是第%d部分的点n",rank/sub_group);
  235.     if(rank==0)
  236.         flag=1;
  237.     if(flag==0)
  238.         if(!((pointx[n_all-1]==tempx[0])&&
  239.         (pointy[n_all-1]==tempy[0])))
  240.             flag=1;
  241. /*将nextindex反向,使输出的点按逆时针方向,以保证各行主处理器输出顺序相邻*/
  242.     index=location[j];
  243.     while(location[index]!=-1)
  244.     {
  245.         temp=location[index];
  246.         location[index]=j;
  247.         j=index;
  248.         index=temp;
  249.     }
  250.     location[index]=j;
  251.     location[0]=-1;
  252. /*按照索引顺序输出各点*/
  253.     j=n_all-1;
  254.     while(location[j]!=-1)
  255.     {
  256.         if(!((j==n_all-1)&&(flag==0)))
  257.         {
  258.             printf("%.2lf,%.2lfn",pointx[j],pointy[j]);
  259.             xtem=pointx[j];
  260.             ytem=pointy[j];
  261.         }
  262.         j=location[j];
  263.     }
  264. /*判断是不是重合*/
  265.     if(!((j==n_all-1)&&(flag==0)))
  266.     {
  267.         printf("%.2lf,%.2lfn",pointx[j],pointy[j]);
  268.         xtem=pointx[j];
  269.         ytem=pointy[j];
  270.     }
  271.     if((rank==3*sub_group)&&!((xtem==tempx[1])&&(ytem==tempy[1])))
  272.         printf("%.2lf,%.2lfn",tempx[1],tempy[1]);
  273.     return;
  274. }
  275. main(int argc,char *argv[])
  276. {
  277.     int i;
  278.     MPI_Init(&argc,&argv);
  279.     MPI_Comm_size(MPI_COMM_WORLD,&group_size);
  280.     MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
  281. /*本程序至少要4个处理器才能正常执行*/
  282.     if (group_size < 4)
  283.     {
  284.         if (my_rank==0)
  285.         {
  286.             printf("Need 4 or more processors to run!n");
  287.         }
  288.         MPI_Finalize();
  289.         exit(0);
  290.     }
  291.     if(my_rank==0)
  292.     {
  293.         printf("please input all the vertexes!nfirst is number!n");
  294.         printf("please input the Number:");
  295.         scanf("%d",&n_all);
  296.         printf("please input the vertex:n");
  297.         for(i=0;i<n_all;i++)
  298.         {
  299.             scanf("%lf",&pointx[i]);
  300.             scanf("%lf",&pointy[i]);
  301.         }
  302.     }
  303. /*处理器0接收输入的顶点坐标*/
  304.     sub_group = group_size / 4;
  305.     MPI_Bcast(&n_all,1,MPI_INT,0,MPI_COMM_WORLD);
  306. /*广播顶点总数*/
  307. /*第1行的行主处理器,向第2,3,4行的行主处理器发送顶点坐标,对应于算法17.6步骤(1.1)*/
  308.     if(my_rank==0)
  309.     {
  310.         for(i=1;i<4;i++)
  311.         {
  312.             MPI_Send(pointx,n_all,MPI_DOUBLE,i*sub_group,i,MPI_COMM_WORLD);
  313.             MPI_Send(pointy,n_all,MPI_DOUBLE,i*sub_group,i,MPI_COMM_WORLD);
  314.         }
  315.     }
  316.     if((my_rank>0)&&(my_rank<4*sub_group)&&(my_rank%sub_group==0))
  317.     {
  318.         MPI_Recv(pointx,n_all,MPI_DOUBLE,0,my_rank/sub_group,MPI_COMM_WORLD,&status);
  319.         MPI_Recv(pointy,n_all,MPI_DOUBLE,0,my_rank/sub_group,MPI_COMM_WORLD,&status);
  320.     }
  321.     MPI_Barrier(MPI_COMM_WORLD);
  322. /*计算极点,并把他们的坐标分别存储在4个行主处理器中*/
  323. /*第1行的行主处理器计算YMIN*/
  324.     if(my_rank==0)
  325.         getymin();
  326. /*第2行的行主处理器计算XMAX*/
  327.     if(my_rank==sub_group)
  328.         getxmax();
  329. /*第3行的行主处理器计算YMAX*/
  330.     if(my_rank==2*sub_group)
  331.         getymax();
  332. /*第4行的行主处理器计算XMIN*/
  333.     if(my_rank==3*sub_group)
  334.         getxmin();
  335.     MPI_Barrier(MPI_COMM_WORLD);
  336. /*将四条由极点组成的边存储到每一行的行主处理器上*/
  337.     if((my_rank>0)&&(my_rank<4*sub_group)&&(my_rank%sub_group==0))
  338.     {
  339. /*各行主处理器发送消息给进程0, 告知极点坐标*/
  340.         MPI_Send(&tempx[1],1,MPI_DOUBLE,0,my_rank,MPI_COMM_WORLD);
  341.         MPI_Send(&tempy[1],1,MPI_DOUBLE,0,my_rank,MPI_COMM_WORLD);
  342.     }
  343.     if(my_rank==0)
  344.     {
  345.         for(i=1;i<4;i++)
  346.         {
  347.             MPI_Recv(&xtemp[i],1,MPI_DOUBLE,i*sub_group,i*sub_group,MPI_COMM_WORLD,&status);
  348.             MPI_Recv(&ytemp[i],1,MPI_DOUBLE,i*sub_group,i*sub_group,MPI_COMM_WORLD,&status);
  349.         }
  350.         xtemp[0]=tempx[1];
  351.         ytemp[0]=tempy[1];
  352.         tempx[1]=xtemp[3];
  353.         tempy[1]=ytemp[3];
  354.         for(i=1;i<4;i++)
  355.         {
  356. /*进程0将相关的极点坐标发送给各行主处理器*/
  357.             MPI_Send(&xtemp[i-1],1,MPI_DOUBLE,i*sub_group,i*sub_group,MPI_COMM_WORLD);
  358.             MPI_Send(&ytemp[i-1],1,MPI_DOUBLE,i*sub_group,i*sub_group,MPI_COMM_WORLD);
  359.         }
  360.     }
  361.     else
  362.     {
  363.         if((my_rank<4*sub_group)&&(my_rank%sub_group==0))
  364.         {
  365. /*各行主处理器接收进程0的消息,得到并存储由极点构成的边*/
  366.             MPI_Recv(&tempx[1],1,MPI_DOUBLE,0,my_rank,MPI_COMM_WORLD,&status);
  367.             MPI_Recv(&tempy[1],1,MPI_DOUBLE,0,my_rank,MPI_COMM_WORLD,&status);
  368.         }
  369.     }
  370.     MPI_Barrier(MPI_COMM_WORLD);
  371. /*确定四边形中的顶点,并将其余顶点归入四个三角区中*/
  372. /*四个行主处理器同时判断顶点是否处于自身所在的区域 */
  373. /*保留属于该区域内的点,每个行主处理器得到要处理的新的表列*/
  374. /*下面得到属于此范围的点*/
  375.     if(my_rank==0)
  376.         getincludedvertex(-1);
  377.     if(my_rank==sub_group)
  378.         getincludedvertex(-1);
  379.     if(my_rank==2*sub_group)
  380.         getincludedvertex(1);
  381.     if(my_rank==3*sub_group)
  382.         getincludedvertex(1);
  383.     MPI_Barrier(MPI_COMM_WORLD);
  384.     if((my_rank<4*sub_group)&&(my_rank%sub_group==0))
  385.     {
  386.         for(i=1;i<sub_group;i++)
  387.         {
  388. /*各行主处理器向该行的其他处理器发送新的表列中的顶点数量*/
  389.             MPI_Send(&n_all,1,MPI_INT,my_rank+i,i,MPI_COMM_WORLD);
  390.         }
  391.     }
  392.     else if (my_rank<4*sub_group)
  393.     {
  394. /*各处理器从该行的主处理器接收新的表列中的顶点数量*/
  395.         MPI_Recv(&n_all,1,MPI_INT,my_rank/sub_group*sub_group,my_rank%sub_group,MPI_COMM_WORLD,&status);
  396.     }
  397.     MPI_Barrier(MPI_COMM_WORLD);
  398.     if((my_rank<4*sub_group)&&(my_rank%sub_group==0))
  399.     {
  400.         for(i=1;i<sub_group;i++)
  401.         {
  402. /*各行主处理器向该行的其他处理器发送新的表列中的顶点坐标*/
  403.             MPI_Send(pointx,n_all,MPI_DOUBLE,my_rank+i,i,MPI_COMM_WORLD);
  404.             MPI_Send(pointy,n_all,MPI_DOUBLE,my_rank+i,i,MPI_COMM_WORLD);
  405.         }
  406.     }
  407.     else if (my_rank<4*sub_group)
  408.     {
  409.         MPI_Recv(pointx,n_all,MPI_DOUBLE,my_rank/sub_group*sub_group,my_rank%sub_group,MPI_COMM_WORLD,&status);
  410.         MPI_Recv(pointy,n_all,MPI_DOUBLE,my_rank/sub_group*sub_group,my_rank%sub_group,MPI_COMM_WORLD,&status);
  411.     }
  412.     MPI_Barrier(MPI_COMM_WORLD);
  413. /*每一行上的处理器对属于同一区域的点计算极角;将有最小极角点的序号作为自己的Nexindex值建立各进程中点的nextindex索引*/
  414.     if((n_all>1)&&(my_rank<4*sub_group))
  415.     {
  416.         for(i=my_rank%sub_group;i<n_all-1;i+=sub_group)
  417.         {
  418.             if(my_rank/sub_group==0)
  419.                 nextindex(i,-1,0);
  420.             if(my_rank/sub_group==1)
  421.                 nextindex(i,0,-1);
  422.             if(my_rank/sub_group==2)
  423.                 nextindex(i,1,0);
  424.             if(my_rank/sub_group==3)
  425.                 nextindex(i,0,1);
  426.         }
  427.     }
  428.     MPI_Barrier(MPI_COMM_WORLD);
  429. /*将个进程中点的nextindex索引发送到中心结点*/
  430.     if((my_rank<4*sub_group)&&(my_rank%sub_group!=0))
  431.     {
  432.         for(i=my_rank%sub_group;i<n_all-1;i+=sub_group)
  433.             MPI_Send(&location[i],1,MPI_INT,my_rank/sub_group*sub_group,my_rank,MPI_COMM_WORLD);
  434.     }
  435.     else if (my_rank<4*sub_group)
  436.     {
  437.         for(i=1;i<n_all-1;i++)
  438.         {
  439.             if(i%sub_group!=0)
  440.             {
  441.                 MPI_Recv(&location[i],1,MPI_INT,my_rank+i%sub_group,my_rank+i%sub_group,MPI_COMM_WORLD,&status);
  442.             }
  443.         }
  444.     }
  445.     MPI_Barrier(MPI_COMM_WORLD);
  446.     location[n_all-1]=-1;
  447.     MPI_Barrier(MPI_COMM_WORLD);
  448. /*每个行主处理器按照点的Nextindex索引输出自己处理器上的点)*/
  449.     if(my_rank==0)
  450.     {
  451. /*第1行输出各顶点的坐标*/
  452.         output(my_rank);
  453. /*将最后的一个点传送给第2行主处理器判断是不是相同*/
  454.         MPI_Send(&pointx[0],1,MPI_DOUBLE,sub_group,sub_group,MPI_COMM_WORLD);
  455.         MPI_Send(&pointy[0],1,MPI_DOUBLE,sub_group,sub_group,MPI_COMM_WORLD);
  456. /*将起始点传送给第4行主处理器判断是不是相同*/
  457.         MPI_Send(&pointx[n_all-1],1,MPI_DOUBLE,3*sub_group,3*sub_group,MPI_COMM_WORLD);
  458.         MPI_Send(&pointy[n_all-1],1,MPI_DOUBLE,3*sub_group,3*sub_group,MPI_COMM_WORLD);
  459.     }
  460.     if(my_rank==sub_group)
  461.     {
  462. /*接收第1行主处理器发送过来的最后一个点,也即本行起始点,以判断是不是相同*/
  463.         MPI_Recv(&tempx[0],1,MPI_DOUBLE,0,sub_group,MPI_COMM_WORLD,&status);
  464.         MPI_Recv(&tempy[0],1,MPI_DOUBLE,0,sub_group,MPI_COMM_WORLD,&status);
  465. /*将最后的一个点传送给第3行主处理器判断是不是相同*/
  466.         MPI_Send(&pointx[0],1,MPI_DOUBLE,2*sub_group,2*sub_group,MPI_COMM_WORLD);
  467.         MPI_Send(&pointy[0],1,MPI_DOUBLE,2*sub_group,2*sub_group,MPI_COMM_WORLD);
  468.     }
  469.     if(my_rank==2*sub_group)
  470.     {
  471.         MPI_Recv(&tempx[0],1,MPI_DOUBLE,sub_group,2*sub_group,MPI_COMM_WORLD,&status);
  472.         MPI_Recv(&tempy[0],1,MPI_DOUBLE,sub_group,2*sub_group,MPI_COMM_WORLD,&status);
  473.         MPI_Send(&pointx[0],1,MPI_DOUBLE,3*sub_group,3*sub_group,MPI_COMM_WORLD);
  474.         MPI_Send(&pointy[0],1,MPI_DOUBLE,3*sub_group,3*sub_group,MPI_COMM_WORLD);
  475.     }
  476.     if(my_rank==3*sub_group)
  477.     {
  478.         MPI_Recv(&tempx[0],1,MPI_DOUBLE,2*sub_group,3*sub_group,MPI_COMM_WORLD,&status);
  479.         MPI_Recv(&tempy[0],1,MPI_DOUBLE,2*sub_group,3*sub_group,MPI_COMM_WORLD,&status);
  480.         MPI_Recv(&tempx[1],1,MPI_DOUBLE,0,3*sub_group,MPI_COMM_WORLD,&status);
  481.         MPI_Recv(&tempy[1],1,MPI_DOUBLE,0,3*sub_group,MPI_COMM_WORLD,&status);
  482.     }
  483.     MPI_Barrier(MPI_COMM_WORLD);
  484. /*第2行输出各顶点的坐标*/
  485.     if(my_rank==sub_group)
  486.         output(my_rank);
  487.     MPI_Barrier(MPI_COMM_WORLD);
  488. /*第3行输出各顶点的坐标*/
  489.     if(my_rank==2*sub_group)
  490.         output(my_rank);
  491.     MPI_Barrier(MPI_COMM_WORLD);
  492. /*第4行输出各顶点的坐标*/
  493.     if(my_rank==3*sub_group)
  494.         output(my_rank);
  495.     MPI_Barrier(MPI_COMM_WORLD);
  496.     MPI_Finalize();
  497. }