Advertisement
chuckbass1

gmres

Dec 2nd, 2016
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.04 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <mpi.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include <time.h>
  6.  
  7.  
  8. #define m 10
  9. #define beta 0.9
  10.  
  11. int N,flag=0,rank,nump;
  12.  
  13. void Least_sq(double *g,double **Hm)
  14. {
  15.     int i=0,j=0,k=0,p=0,q=0;
  16.     double W[m+1][m+1],si=0,ci=0;
  17.     double temp1[m+1][m],temp2[m+1];
  18.  
  19.     for (i=0;i<m;i++){
  20.         si=(Hm[i+1][i])/sqrt(pow(Hm[i][i],2)+pow(Hm[i+1][i],2));
  21.         ci=(Hm[i][i])/sqrt(pow(Hm[i][i],2)+pow(Hm[i+1][i],2));
  22.         for (j=0;j<(m+1);j++){
  23.             for (p=0; p<m; p++) {
  24.                 temp1[j][p]=0;
  25.             }
  26.             for (k=0;k<(m+1);k++){
  27.                 if(j==k){
  28.                     W[j][k]=1;
  29.                 }
  30.                 else {
  31.                     W[j][k]=0;
  32.                 }
  33.             }
  34.             temp2[j]=0;
  35.         }
  36.         W[i][i]=ci;
  37.         W[i][i+1]=si;
  38.         W[i+1][i]=-si;
  39.         W[i+1][i+1]=ci;
  40.                     for (j=0;j<(m+1);j++){
  41.             for(k=0;k<m;k++){
  42.                 for(p=0;p<(m+1);p++){
  43.                     temp1[j][k]+=(W[j][p]*(Hm[p][k]));
  44.                 }
  45.             }
  46.         }
  47.         for (j=0; j<(m+1); j++) {
  48.             for (k=0; k<m; k++) {
  49.                 Hm[j][k]=temp1[j][k];
  50.             }
  51.         }
  52.         for (j=0;j<(m+1);j++){
  53.             for(p=0;p<(m+1);p++){
  54.                 temp2[j]+=W[j][p]*g[p];
  55.             }
  56.         }
  57.         for (j=0; j<(m+1); j++) {
  58.             g[j]=temp2[j];
  59.         }
  60.     }
  61. }
  62.  
  63. void Back_sub(double *y,double *g,double **Hm)
  64. {
  65.     int i=0,j=0,k=0;
  66.     double sum=0,help[m+1];
  67.  
  68.     for (i=0;i<(m+1);i++){
  69.         help[i]=g[i];
  70.     }
  71.     for (i=(m-1);i>=0;i--){
  72.         sum=help[i];
  73.         if (i<(m-1)){
  74.             for (j=(i+1);j<m;j++){
  75.                 sum-=(Hm[i][j])*help[j];
  76.             }
  77.         }
  78.         help[i]=sum/(Hm[i][i]);
  79.     }
  80.     for (i=0;i<m;i++){
  81.         y[i]=help[i];
  82.     }
  83. }
  84.  
  85. void Krylov(double **A,double *uj,double **Hm, double **u_base,int rank,
  86.         int nump,int local_N,int init,double *comm_tot)
  87. {
  88.     int  i=0,j=0,k=0;
  89.     double *w,*buffer,buff,help;
  90.     double comm_time1=0,comm_time2=0;
  91.  
  92.     w=(double*)malloc(N*sizeof(double));
  93.     buffer=(double*)malloc(local_N*sizeof(double));
  94.     for (j=0;j<m;j++){
  95.                     for(k=0;k<N;k++){
  96.                 uj[k]=u_base[k][j];
  97.         }
  98.         for (i=0; i<local_N; i++) {
  99.             w[i+init]=0;
  100.             for (k=0; k<N; k++) {
  101.                 w[i+init]+=A[i][k]*uj[k];
  102.             }
  103.         }
  104.  
  105.         for (i=0;i<local_N; i++) {
  106.             buffer[i]=w[i+init];
  107.         }
  108.         comm_time1=MPI_Wtime();
  109.         MPI_Allgather(buffer, local_N, MPI_DOUBLE,w, local_N,
  110.                       MPI_DOUBLE, MPI_COMM_WORLD);
  111.         comm_time2=MPI_Wtime();
  112.         *comm_tot += (comm_time2-comm_time1);
  113.  
  114.         for (i=0;i<=j;i++){
  115.             for(k=0;k<N;k++){
  116.                     uj[k]=u_base[k][i];
  117.             }
  118.             buff=0;
  119.             for (k=0; k<local_N; k++) {
  120.                 buff+=w[init+k]*uj[k+init];
  121.             }
  122.             comm_time1=MPI_Wtime();
  123.             MPI_Allreduce(&buff,&help,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
  124.             comm_time2=MPI_Wtime();
  125.             Hm[i][j]=help;
  126.             *comm_tot+=(comm_time2-comm_time1);
  127.                       for(k=0;k<=N;k++){
  128.                     w[k]-=(Hm[i][j])*(uj[k]);
  129.             }
  130.         }
  131.  
  132.         buff=0;
  133.         for (k=0;k<local_N;k++){
  134.                 buff+=pow(w[k+init],2);
  135.         }
  136.         comm_time1=MPI_Wtime();
  137.         MPI_Allreduce(&buff,&help,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
  138.         comm_time2=MPI_Wtime();
  139.         Hm[j+1][j]=help;
  140.         *comm_tot+=(comm_time2-comm_time1);
  141.         Hm[j+1][j]=sqrt(Hm[j+1][j]);
  142.         if (Hm[j+1][j]==0) {
  143.             break;
  144.         }
  145.         if(j<(m-1)){
  146.             for (k=0;k<N;k++){
  147.                     u_base[k][j+1]=w[k]/(Hm[j+1][j]);
  148.             }
  149.         }
  150.     }
  151. }
  152.  
  153. void GMRES_m(double *b,double **A,double *x,int rank, int nump,int local_N,int init,int fin)
  154. {
  155.     int i=0,j=0,k=0,iter=0;
  156.     double vita=0,eps=0.000000001,sum=0,buff,*buffer;
  157.     double e[m+1],y[m],g[m+1];
  158.     double *x0,*r0,*uj,*temp,norm=1,norm0=1;
  159.     double **Hm,**u_base;
  160.     double tot_time=0,init_time=0,comm_time1=0,comm_time2=0,comm_tot=0;
  161.         init_time=MPI_Wtime();
  162.     x0=(double*)calloc(N,sizeof(double));
  163.     r0=(double*)malloc(N*sizeof(double));
  164.     buffer=(double*)malloc(local_N*sizeof(double));
  165.     uj=(double*)malloc(N*sizeof(double));
  166.     temp=(double*)malloc(N*sizeof(double));
  167.         Hm=(double**)(malloc((m+1)*sizeof(double*)));
  168.     for (i=0; i<(m+1); i++) {
  169.         Hm[i]=(double*)(malloc(m*sizeof(double)));
  170.     }
  171.     u_base=(double**)(malloc(N*sizeof(double*)));
  172.     for (i=0; i<N; i++) {
  173.         x[i]=0;
  174.         u_base[i]=(double*)(malloc(m*sizeof(double)));
  175.     }
  176.     iter=1;
  177.  
  178.     while ((norm/norm0)>=eps) {
  179. flag=iter;
  180.  
  181.         for (i=0; i<N; i++) {
  182.             x0[i]=x[i];
  183.             uj[i]=0;
  184.             r0[i]=0;
  185.             temp[i]=0;
  186.         }
  187.                 for (i=0; i<N; i++) {
  188.             for (j=0; j<m; j++) {
  189.                 u_base[i][j]=0;
  190.             }
  191.         }
  192.         for (i=0; i<(m+1); i++) {
  193.             e[i]=0;
  194.             g[i]=0;
  195.             for (j=0; j<m; j++) {
  196.                 Hm[i][j]=0;
  197.                 y[j]=0;
  198.             }
  199.         }
  200.         e[0]=1;
  201.         for (i=0; i<local_N; i++) {
  202.             sum=0;
  203.             for (j=0; j<N; j++) {
  204.                 sum+=A[i][j]*x0[j];
  205.             }
  206.             r0[i+init]=b[i+init]-sum;
  207.         }
  208.         vita=0;
  209.         buff=0;
  210.         for (i=0; i<local_N; i++) {
  211.                 vita+=pow(r0[init+i],2);
  212.         }
  213.         comm_time1=MPI_Wtime();
  214.         MPI_Allreduce(&vita,&buff,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
  215.         comm_time2=MPI_Wtime();
  216.         comm_tot+=(comm_time2-comm_time1);
  217.         vita=sqrt(buff);
  218.         if (iter==1) {
  219.             norm0=vita;
  220.         }
  221.         norm=vita;
  222.         for (i=0;i<local_N; i++) {
  223.             uj[i+init]=r0[i+init]/vita;
  224.             buffer[i]=uj[i+init];
  225.         }
  226.         comm_time1=MPI_Wtime();
  227.         MPI_Allgather(buffer, local_N, MPI_DOUBLE,uj, local_N,
  228.                     MPI_DOUBLE, MPI_COMM_WORLD);
  229.         comm_time2=MPI_Wtime();
  230.         comm_tot+=(comm_time2-comm_time1);
  231.                 for (i=0; i<N; i++) {
  232.             u_base[i][0]=uj[i];
  233.         }
  234.                     for (i=0; i<(m+1); i++) {
  235.             g[i]=vita*e[i];
  236.         }
  237.               Krylov(A,uj,Hm,u_base,rank,nump,local_N,init,&comm_tot);
  238.         Least_sq(g,Hm);
  239.         Back_sub(y,g,Hm);
  240.         for (i=0; i<local_N; i++) {
  241.             for (k=0; k<m; k++) {
  242.                 temp[i]+=u_base[i+init][k]*y[k];
  243.             }
  244.         }
  245.         for (i=0; i<local_N; i++) {
  246.             x[i+init]=x0[i+init]+temp[i];
  247.         }
  248.         for (i=0;i<local_N; i++) {
  249.             buffer[i]=x[i+init];
  250.         }
  251.  
  252.                 comm_time1=MPI_Wtime();
  253.         MPI_Allgather(buffer, local_N, MPI_DOUBLE,x, local_N,
  254.                       MPI_DOUBLE, MPI_COMM_WORLD);
  255.         comm_time2=MPI_Wtime();
  256.         comm_tot+=(comm_time2-comm_time1);
  257.         comm_time2=comm_tot;
  258.  
  259.         iter++;
  260.     }
  261.  
  262.     free(x0);
  263.     free(r0);
  264.     free(uj);
  265.     free(temp);
  266.     free(Hm);
  267.     free(u_base);
  268.     comm_time1=MPI_Wtime()-init_time;
  269.     MPI_Allreduce(&comm_time1,&tot_time,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
  270.     MPI_Allreduce(&comm_time2,&comm_tot,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
  271.     if (rank==0) {
  272.         printf("%d %d %.10f\n", N, nump, tot_time/nump);
  273.            }
  274.    }
  275. }
  276.  
  277. void matrix_fill(double *x, double **S, double **D, double **invS)
  278. {
  279.     int i=0,j=0;
  280.     double temp;
  281.  
  282.     for (i=0; i<N; i++) {
  283.         x[i]=i+1;
  284.         for (j=0; j<N; j++) {
  285.             S[i][j]=0;
  286.             D[i][j]=0;
  287.             invS[i][j]=0;
  288.             if (i==j) {
  289.                 S[i][j]=1;
  290.                 D[i][j]=i+1;
  291.                 invS[i][j]=1;
  292.             }
  293.             if ((j-i)==1) {
  294.                 S[i][j]=beta;
  295.             }
  296.             if (i<=j) {
  297.                 temp=(double) j-i;
  298.                 invS[i][j]=pow(-beta, temp);
  299.             }
  300.         }
  301.     }
  302.  
  303. }
  304.  
  305. void matvec(double **A, double *x, double *y)
  306. {
  307.     double temp=0;
  308.     int i=0,j=0;
  309.  
  310.     for (i=0; i<N; i++) {
  311.         temp=0;
  312.         for (j=0; j<N; j++) {
  313.             temp+=A[i][j]*x[j];
  314.         }
  315.         y[i]=temp;
  316.     }
  317. }
  318.  
  319. void matmul(double **A, double **B, double **Y)
  320. {
  321.     double temp=0;
  322.     int i=0,j=0,r=0;
  323.  
  324.     for (i=0; i<N; i++) {
  325.         for (j=0; j<N; j++) {
  326.             temp=0;
  327.             for (r=0; r<N; r++) {
  328.                 temp+=A[i][r]*B[r][j];
  329.             }
  330.             Y[i][j]=temp;
  331.         }
  332.     }
  333. }
  334.  
  335. double norm(double *x)
  336. {
  337.     int i=0;
  338.     double temp,res=0;
  339.     temp=0;
  340.     for (i=0; i<N; i++) {
  341.         temp+=pow(x[i], 2);
  342.     }
  343.     res=sqrt(temp);
  344.     return res;
  345. }
  346.  
  347. int main (int argc,char* argv[])
  348. {
  349.     MPI_Init( &argc,&argv);
  350.     MPI_Comm_rank(MPI_COMM_WORLD,&rank);
  351.     MPI_Comm_size(MPI_COMM_WORLD,&nump);
  352.     double *x,*y,**A,**S,**invS,**D,**T,temp=0,help=0,eigen=0,**local_A;
  353.     int i=0,j=0,local_N,temp_div,temp_mod,init,fin,irina;
  354.        clock_t start1, end1 ;
  355.     double time1,time2;
  356.     int mem1=0,mem2=0;
  357.       for (irina=1;irina<=16;irina++){
  358.             N=irina*128;
  359.     x=(double*)(malloc(N*sizeof(double)));
  360.     y=(double*)(malloc(N*sizeof(double)));
  361.         A=(double**)(malloc(N*sizeof(double*)));
  362.     S=(double**)(malloc(N*sizeof(double*)));
  363.     D=(double**)(malloc(N*sizeof(double*)));
  364.     invS=(double**)(malloc(N*sizeof(double*)));
  365.     T=(double**)(malloc(N*sizeof(double*)));
  366.     for (i=0; i<N; i++) {
  367.         S[i]=(double*)(malloc(N*sizeof(double)));
  368.         D[i]=(double*)(malloc(N*sizeof(double)));
  369.         invS[i]=(double*)(malloc(N*sizeof(double)));
  370.         T[i]=(double*)(malloc(N*sizeof(double)));
  371.     }
  372.  
  373.        matrix_fill(x,S,D,invS);
  374.         matmul(S,D,T);
  375.     free(D);
  376.     free(S);
  377.       for (i=0; i<N; i++) {
  378.         A[i]=(double*)(malloc(N*sizeof(double)));
  379.     }
  380.     matmul(T,invS,A);
  381.         matvec(A,x,y);
  382.     free(T);
  383.     free(invS);
  384.  
  385.  
  386.        temp_mod=N%nump;
  387.     temp_div=N/nump;
  388.     if (temp_mod==0){
  389.         init=rank*temp_div;
  390.         fin=(rank+1)*temp_div-1;
  391.     }
  392.     else if (temp_mod!=0){
  393.         if (rank!=(nump-1)){
  394.             init=(rank*temp_div+rank);
  395.             fin=((rank+1)*(temp_div+1)-1);
  396.         }
  397.         else if (rank==(nump-1)){
  398.             init=(rank*temp_div+rank);
  399.             fin=(N-1);
  400.         }
  401.     }
  402.  
  403.     local_N=fin-init+1;
  404.     double *b;
  405.     b=(double*)(malloc(N*sizeof(double)));
  406.     for (i=0; i<N; i++) {
  407.         x[i]=0;
  408.         b[i]=1;
  409.     }
  410.     local_A=(double**)(malloc(local_N*sizeof(double*)));
  411.     for (i=0; i<local_N; i++) {
  412.         local_A[i]=(double*)(malloc(N*sizeof(double)));
  413.     }
  414.         for (i=0; i<local_N; i++) {
  415.         for (j=0; j<N; j++) {
  416.             local_A[i][j]=A[i+init][j];
  417.         }
  418.     }
  419.     free(A);
  420.     GMRES_m(b,local_A,x,rank,nump,local_N,init,fin);
  421.  
  422.    
  423. }
  424.     MPI_Barrier(MPI_COMM_WORLD);
  425.     MPI_Finalize();
  426.     return 0;
  427. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement