int main (int argc, char *argv[]) { void inidat(), prtdat(), update(); int taskid, /* this task's unique id */ numworkers, /* number of worker processes */ numtasks, /* number of tasks */ averow,rows,offset,extra, /* for sending rows of data */ dest, source, /* to - from for message send-receive */ left,right, /* neighbor tasks */ msgtype, /* for message types */ rc,start,end, /* misc */ i,ix,iy,iz,it; /* loop variables */ inidat(NXPROB, NYPROB, u); prtdat(NXPROB, NYPROB, u, "initial.dat"); }
int main (int argc, char *argv[]) { void inidat(), prtdat(), update(); float u[2][NXPROB][NYPROB]; /* array for grid */ int taskid, /* this task's unique id */ numworkers, /* number of worker processes */ numtasks, /* number of tasks */ averow,rows,offset,extra, /* for sending rows of data */ dest, source, /* to - from for message send-receive */ left,right, /* neighbor tasks */ msgtype, /* for message types */ rc,start,end, /* misc */ i,ix,iy,iz,it; /* loop variables */ MPI_Status status; /* First, find out my taskid and how many tasks are running */ MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numtasks); MPI_Comm_rank(MPI_COMM_WORLD,&taskid); numworkers = numtasks-1; if (taskid == MASTER) { /************************* master code *******************************/ /* Check if numworkers is within range - quit if not */ if ((numworkers > MAXWORKER) || (numworkers < MINWORKER)) { printf("ERROR: the number of tasks must be between %d and %d.\n", MINWORKER+1,MAXWORKER+1); printf("Quitting...\n"); MPI_Abort(MPI_COMM_WORLD, rc); exit(1); } printf ("Starting mpi_heat2D with %d worker tasks.\n", numworkers); /* Initialize grid */ printf("Grid size: X= %d Y= %d Time steps= %d\n",NXPROB,NYPROB,STEPS); printf("Initializing grid and writing initial.dat file...\n"); inidat(NXPROB, NYPROB, u); prtdat(NXPROB, NYPROB, u, "initial.dat"); /* Distribute work to workers. Must first figure out how many rows to */ /* send and what to do with extra rows. */ averow = NXPROB/numworkers; extra = NXPROB%numworkers; offset = 0; for (i=1; i<=numworkers; i++) { rows = (i <= extra) ? averow+1 : averow; /* Tell each worker who its neighbors are, since they must exchange */ /* data with each other. */ if (i == 1) left = NONE; else left = i - 1; if (i == numworkers) right = NONE; else right = i + 1; /* Now send startup information to each worker */ dest = i; MPI_Send(&offset, 1, MPI_INT, dest, BEGIN, MPI_COMM_WORLD); MPI_Send(&rows, 1, MPI_INT, dest, BEGIN, MPI_COMM_WORLD); MPI_Send(&left, 1, MPI_INT, dest, BEGIN, MPI_COMM_WORLD); MPI_Send(&right, 1, MPI_INT, dest, BEGIN, MPI_COMM_WORLD); MPI_Send(&u[0][offset][0], rows*NYPROB, MPI_FLOAT, dest, BEGIN, MPI_COMM_WORLD); printf("Sent to task %d: rows= %d offset= %d ",dest,rows,offset); printf("left= %d right= %d\n",left,right); offset = offset + rows; } /* Now wait for results from all worker tasks */ for (i=1; i<=numworkers; i++) { source = i; msgtype = DONE; MPI_Recv(&offset, 1, MPI_INT, source, msgtype, MPI_COMM_WORLD, &status); MPI_Recv(&rows, 1, MPI_INT, source, msgtype, MPI_COMM_WORLD, &status); MPI_Recv(&u[0][offset][0], rows*NYPROB, MPI_FLOAT, source, msgtype, MPI_COMM_WORLD, &status); } /* Write final output, call X graph and finalize MPI */ printf("Writing final.dat file and generating graph...\n"); prtdat(NXPROB, NYPROB, &u[0][0][0], "final.dat"); printf("Click on MORE button to view initial/final states.\n"); printf("Click on EXIT button to quit program.\n"); //draw_heat(NXPROB,NYPROB); MPI_Finalize(); } /* End of master code */ /************************* workers code **********************************/ if (taskid != MASTER) { /* Initialize everything - including the borders - to zero */ for (iz=0; iz<2; iz++) for (ix=0; ix<NXPROB; ix++) for (iy=0; iy<NYPROB; iy++) u[iz][ix][iy] = 0.0; /* Receive my offset, rows, neighbors and grid partition from master */ source = MASTER; msgtype = BEGIN; MPI_Recv(&offset, 1, MPI_INT, source, msgtype, MPI_COMM_WORLD, &status); MPI_Recv(&rows, 1, MPI_INT, source, msgtype, MPI_COMM_WORLD, &status); MPI_Recv(&left, 1, MPI_INT, source, msgtype, MPI_COMM_WORLD, &status); MPI_Recv(&right, 1, MPI_INT, source, msgtype, MPI_COMM_WORLD, &status); MPI_Recv(&u[0][offset][0], rows*NYPROB, MPI_FLOAT, source, msgtype, MPI_COMM_WORLD, &status); /* Determine border elements. Need to consider first and last columns. */ /* Obviously, row 0 can't exchange with row 0-1. Likewise, the last */ /* row can't exchange with last+1. */ start=offset; end=offset+rows-1; if (offset==0) start=1; if ((offset+rows)==NXPROB) end--; printf("task=%d start=%d end=%d\n",taskid,start,end); /* Begin doing STEPS iterations. Must communicate border rows with */ /* neighbors. If I have the first or last grid row, then I only need */ /* to communicate with one neighbor */ printf("Task %d received work. Beginning time steps...\n",taskid); iz = 0; for (it = 1; it <= STEPS; it++) { if (left != NONE) { MPI_Send(&u[iz][offset][0], NYPROB, MPI_FLOAT, left, RTAG, MPI_COMM_WORLD); source = left; msgtype = LTAG; MPI_Recv(&u[iz][offset-1][0], NYPROB, MPI_FLOAT, source, msgtype, MPI_COMM_WORLD, &status); } if (right != NONE) { MPI_Send(&u[iz][offset+rows-1][0], NYPROB, MPI_FLOAT, right, LTAG, MPI_COMM_WORLD); source = right; msgtype = RTAG; MPI_Recv(&u[iz][offset+rows][0], NYPROB, MPI_FLOAT, source, msgtype, MPI_COMM_WORLD, &status); } /* Now call update to update the value of grid points */ update(start,end,NYPROB,&u[iz][0][0],&u[1-iz][0][0]); iz = 1 - iz; } /* Finally, send my portion of final results back to master */ MPI_Send(&offset, 1, MPI_INT, MASTER, DONE, MPI_COMM_WORLD); MPI_Send(&rows, 1, MPI_INT, MASTER, DONE, MPI_COMM_WORLD); MPI_Send(&u[iz][offset][0], rows*NYPROB, MPI_FLOAT, MASTER, DONE, MPI_COMM_WORLD); MPI_Finalize(); } }
/* Main program */ int main(){ /* not Locals */ lapack_complex_double *a, *temp, * u, *vt; lapack_int m = M, n = N, lda = LDA, ldu = LDU, ldvt = LDVT, info; /* Local arrays */ //void prtdat(); double *s; double *superb; int svd_count=0; int i, j ,ix ,iy, index, ii, jj ; double x_min, x_max, y_min, y_max, stepx, /* step size for finding gridpoints coordinates in x and y dimension.*/ stepy; double e=0.1; /* Array used for the ploting of * grid, as an input to the * draw_pseudospectra function. */ double *plot; //double plot[n][n]; COLOUR colour; BITMAP4 col,grey = {128,128,128,0}; /* Memory alocations*/ temp = malloc((lda*m)*sizeof(lapack_complex_double)); a = malloc((lda*m)*sizeof(lapack_complex_double)); u = malloc((ldu*m)*sizeof(lapack_complex_double)); vt = malloc((ldvt*n)*sizeof(lapack_complex_double)); s = malloc(m*sizeof(double)); superb = malloc(min(m,n)*sizeof(double)); plot = malloc((NGRID*NGRID)*sizeof(double)); z = malloc((NGRID*NGRID)*sizeof(double _Complex)); //allocating the 2D array data. if ((data = malloc(SCALE*NGRID*sizeof(double *))) == NULL) { fprintf(stderr,"Failed to malloc space for the data\n"); exit(-1); } for (i=0;i<SCALE*NGRID;i++) { if ((data[i] = malloc(SCALE*NGRID*sizeof(double))) == NULL) { fprintf(stderr,"Failed to malloc space for the data\n"); exit(-1); } } for (i=0;i<SCALE*NGRID;i++){ for (j=0;j<SCALE*NGRID;j++){ data[i][j] = 0; // printf("%f\t",data[i][j]); } } /* printf("-------------------------------------------------\n"); printf(" --------------------------------- \n"); printf ("Starting Computing Pseudopsecta of grcar Matrix\n"); printf("Give the doundaries of the 2-dimenional domain\n"); printf("Insert the minimum value of x-axis\n"); clearerr(stdin); scanf("%lf",&x_min); //getchar(); printf("Insert the maximum value of x-axis\n"); scanf("%lf",&x_max); printf("Insert the minimum value of y-axis\n"); scanf("%lf",&y_min); printf("Insert the maximun value of y-axis\n"); scanf("%lf",&y_max); //printf("Give the grid size you want:\n"); //scanf("%d",&n); */ /*if (x_min==0.0)*/ x_min=XMIN; /*if (x_max==0.0)*/ x_max=XMAX; /*if (y_min==0.0)*/ y_min=YMIN; /*if (y_max==0.0)*/ y_max=YMAX; /* Initialize grid */ printf("The size of the domain is: X=[%f-%f] Y=[%f-%f] \n",x_min,x_max,y_min,y_max); stepx=(double)abs(x_max-x_min)/(NGRID-1); stepy=(double)abs(y_max-y_min)/(NGRID-1); printf("To stepx einai %f\n",stepx); printf("To stepy einai %f\n",stepy); for (i =0; i <NGRID*NGRID; i++){ z[i]=x_min+(i/n * stepx)+(y_min + (i%n * stepy))*I; // z[i]=lapack_make_complex_double( i/n,i%n); just for testing //** printf( " (%6.2f,%6.2f)", lapack_complex_double_real(z[i]), lapack_complex_double_imag(z[i]) ); } memset(temp,0,(lda*m)*sizeof(*temp)); memset(a,0,(lda*m)*sizeof(*a)); memset(u,0,(ldu*m)*sizeof(*u)); memset(vt,0,(ldvt*m)*sizeof(*vt)); j=0; for (i = 0; i < lda*m ; i=i+n ){ if(i==0){ a[i]=lapack_make_complex_double( 1,0); a[i+1]=lapack_make_complex_double( 1,0); a[i+2]=lapack_make_complex_double( 1,0); a[i+3]=lapack_make_complex_double( 1,0); } else if(i == (n-3)*n ){ a[i+j]=lapack_make_complex_double( -1,0); a[i+(j+1)]=lapack_make_complex_double( 1,0); a[i+(j+2)]=lapack_make_complex_double( 1,0); a[i+(j+3)]=lapack_make_complex_double( 1,0); j++; } else if(i == (n-2)*n ){ a[i+j]=lapack_make_complex_double( -1,0); a[i+(j+1)]=lapack_make_complex_double( 1,0); a[i+(j+2)]=lapack_make_complex_double( 1,0); j++; } else if(i == (n-1)*n ){ a[i+j]=lapack_make_complex_double( -1,0); a[i+(j+1)]=lapack_make_complex_double( 1,0); j++; } else{ a[i+j]=lapack_make_complex_double( -1,0); a[i+(j+1)]=lapack_make_complex_double( 1,0); a[i+(j+2)]=lapack_make_complex_double( 1,0); a[i+(j+3)]=lapack_make_complex_double( 1,0); a[i+(j+4)]=lapack_make_complex_double( 1,0); j++; } } //print_matrix("Entry Matrix A", m, n, a, lda ); for (iy = 0; iy < NGRID*NGRID; iy++){ //printf("temp size %d, a size %d",(lda*m)*sizeof(*temp),(lda*m)*sizeof(*a)); memcpy(temp, a ,(lda*m)*sizeof(*temp)); //~ print_matrix( "Entry Matrix Temp just after memcopy", m, n, temp, lda ); //~ print_matrix( "Entry Matrix A just after memcopy", m, n, a, lda ); // printf( "To z[%d](%6.4f,%6.4f)\n",iy,lapack_complex_double_real(z[iy]),lapack_complex_double_imag(z[iy]) ); for (i = 0; i < lda*m ; i=i+(n+1)){ //~ printf("%d",i); //~ printf( "To a[%d](%6.2f,%6.2f)\t",i, lapack_complex_double_real(a[i]), lapack_complex_double_imag(a[i]) ); //~ printf( "To z[%d](%6.2f,%6.2f)\n",iy,lapack_complex_double_real(z[iy]),lapack_complex_double_imag(z[iy]) ); temp[i]=a[i]-z[iy]; //~ temp[index] = lapack_make_complex_double(lapack_complex_double_real(a[index])-lapack_complex_double_real(z[iy]), lapack_complex_double_imag(a[index])-lapack_complex_double_imag(z[iy]) ); //~ printf( " temp[%d](%6.2f,%6.2f)", i,lapack_complex_double_real(temp[i]), lapack_complex_double_imag(temp[i]) ); //~ printf( "\n"); } //printf("GRCAR MATRIX AFTER SUBSTRACTION (%d,%d)\n",iy/n,iy%n); //~ print_matrix( "Entry Matrix Temp just before", m, n, temp, lda ); /* Executable statements */ //~ print_matrix( "AT THE BEGINING OF THE FOR LOOP", m, n, a, lda ); printf( "LAPACKE_zgesvd (row-major, high-level) Example Program Results(%d,%d)\n",iy/NGRID,iy%NGRID); /* Compute SVD */ info = LAPACKE_zgesvd( LAPACK_ROW_MAJOR, 'N', 'N', m, n, temp, lda, s, NULL, ldu, NULL, ldvt, superb ); svd_count++; //~ //~ print_matrix( "IN THE MIDDLE OF THE FOR LOOP", m, n, a, lda ); //~ print_matrix( "IN THE MIDDLE OF THE FOR LOOP-TEMP", m, n, temp, lda ); /* Check for convergence */ if( info > 0 ) { printf( "The algorithm computing SVD failed to converge.\n" ); exit( 1 ); } /* Print singular values */ if( info == 0){ // printf("Solution\n"); for ( i= 0; i< m; i++ ) { // printf(" s[ %d ] = %f\n", i, s[ i ] ); } } if(s[m-1] <= e){ printf("THIS ELEMENT BELONGS TO PSEUDOSPECTRA (%d,%d):%6.10f\n",(iy/NGRID+1),(iy%NGRID+1),s[m-1]); /*to index tis parapanw ektupwshs anaferetai sto index tou antistoixou mhtrwou apo thn synarthsh ths matlab grcar_example.m*/ //~ plot[iy/n][iy%n]=s[m-1]; plot[iy]=s[m-1]; } //~ else plot[iy/n][iy%n]=0; else plot[iy]=0; //~ print_rmatrix( "Singular values", 1, m, s, 1 ); /* Print left singular vectors */ // print_matrix( "Left singular vectors (stored columnwise)", m, m, u, ldu ); /* Print right singular vectors */ // print_matrix( "Right singular vectors (stored rowwise)", m, n, vt, ldvt ); } prtdat(NGRID, NGRID, plot, "svd.data"); printf("Total number of svd evaluations in the %d,%d grid is:\t %d\n",NGRID,NGRID,svd_count); //giving values to data from plot for (i = 0; i<NGRID*NGRID; i++) data[SCALE*(i/NGRID)][SCALE*(i%NGRID)] = plot[i]; ///////////////// BITMAP4 black = {0,0,0,0}; Draw_Line(image,NGRID,NGRID,x_min,y_min,x_max,y_min,black); ////////////////// //~ contours[0] = 0.1; //~ contours[1] = 0.01; //~ contours[2] = 0.001; //~ contours[3] = 0.0001; //~ contours[4] = 0.00001; if ((image = Create_Bitmap(SCALE*NGRID,SCALE*NGRID)) == NULL) { fprintf(stderr,"Malloc of bitmap failed\n"); exit(-1); } Erase_Bitmap(image,SCALE*NGRID,SCALE*NGRID,grey); /* Not strictly necessary */ for (j=0;j<SCALE*NGRID;j++) { for (i=0;i<SCALE*NGRID;i++) { colour = GetColour(data[i][j],0,0.1,1); ///////////////////////////////////////////// col.r = colour.r * 255; // col.b = colour.b * 255; // Draw_Pixel(image,SCALE*NGRID,SCALE*NGRID,(double)i,(double)j,col); // colour = GetColour(data[i][j],0,0.0001,1); ///////////////////////////////////////////// // col.g = colour.g * 255; Draw_Pixel(image,SCALE*NGRID,SCALE*NGRID,(double)i,(double)j,col); } } /* Finally do the contouring */ CONREC(data,0,SCALE*NGRID-1,0,SCALE*NGRID-1, z,NCONTOUR,contours,drawline); fprintf(stderr,"Drew %d vectors\n",vectorsdrawn); /* Write the image as a TGA file See bitmaplib.c for more details, or write "image" in your own prefered format. */ if ((fp = fopen("image.tga","w")) == NULL) { fprintf(stderr,"Failed to open output image\n"); exit(-1); } Write_Bitmap(fp,image,SCALE*NGRID,SCALE*NGRID,12); fclose(fp); exit(0); } /* End of LAPACKE_zgesvd Example */