Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- ************************************************************************
- Example 25 (congrad.c)
- Objective : Conjugate Gradient Method to solve AX = b
- matrix system of linear equations.
- Input : Real Symmetric Positive definite Matrix
- and the real vector - Input_A and Vector_B
- Read files (mdatcg.inp) for Matrix A
- and (vdatcg.inp) for Vector b
- Description : Input matrix is stored in n by n format.
- Diagonal preconditioning matrix is used.
- Rowwise block striped partitioning matrix
- is used.Maximum iterations is given by
- MAX_ITERATIONS.Tolerance value is given
- by EPSILON
- Header file used : cg_constants.h
- Output : The solution of Ax=b on process with
- Rank 0 and the number of iterations
- for convergence of the method.
- Necessary conditions : Number of Processes should be less than
- or equal to 8 Input Matrix Should be
- Square Matrix. Matrix size for Matrix A
- and vector size for vector b should be
- equally striped, that is Matrix size and
- Vector Size should be dividible by the
- number of processes used.
- ***************************************************************
- */
- #include<math.h>
- #include<stdio.h>
- #include<stdlib.h>
- #include<mpi.h>
- #define EPSILON 1.0E-20
- #define MAX_ITERATIONS 10000
- /******************************************************************************/
- void
- GetPreconditionMatrix(double **Bloc_Precond_Matrix, int NoofRows_Bloc,
- int NoofCols)
- {
- /*... Preconditional Martix is identity matrix .......*/
- int Bloc_MatrixSize;
- int irow, icol, index;
- double *Precond_Matrix;
- Bloc_MatrixSize = NoofRows_Bloc*NoofCols;
- Precond_Matrix = (double *) malloc(Bloc_MatrixSize * sizeof(double));
- index = 0;
- for(irow=0; irow<NoofRows_Bloc; irow++){
- for(icol=0; icol<NoofCols; icol++){
- Precond_Matrix[index++] = 1.0;
- }
- }
- *Bloc_Precond_Matrix = Precond_Matrix;
- }
- /******************************************************************************/
- double
- ComputeVectorDotProduct(double *Vector1, double *Vector2, int VectorSize)
- {
- int index;
- double Product;
- Product = 0.0;
- for(index=0; index<VectorSize; index++)
- Product += Vector1[index]*Vector2[index];
- return(Product);
- }
- /******************************************************************************/
- void
- CalculateResidueVector(double *Bloc_Residue_Vector, double *Bloc_Matrix_A,
- double *Input_B, double *Vector_X, int NoofRows_Bloc,
- int VectorSize, int MyRank)
- {
- /*... Computes residue = AX - b .......*/
- int irow, index, GlobalVectorIndex;
- double value;
- GlobalVectorIndex = MyRank * NoofRows_Bloc;
- for(irow=0; irow<NoofRows_Bloc; irow++){
- index = irow * VectorSize;
- value = ComputeVectorDotProduct(&Bloc_Matrix_A[index], Vector_X,
- VectorSize);
- Bloc_Residue_Vector[irow] = value - Input_B[GlobalVectorIndex++];
- }
- }
- /******************************************************************************/
- void
- SolvePrecondMatrix(double *Bloc_Precond_Matrix, double *HVector,
- double *Bloc_Residue_Vector, int Bloc_VectorSize)
- {
- /*...HVector = Bloc_Precond_Matrix inverse * Bloc_Residue_Vector.......*/
- int index;
- for(index=0; index<Bloc_VectorSize; index++){
- HVector[index] = Bloc_Residue_Vector[index]/1.0;
- }
- }
- /******************************************************************************/
- main(int argc, char *argv[])
- {
- int NumProcs, MyRank, Root=0;
- int NoofRows, NoofCols, VectorSize;
- int n_size, NoofRows_Bloc, Bloc_MatrixSize, Bloc_VectorSize;
- int Iteration = 0, irow, icol, index, CorrectResult;
- double **Matrix_A, *Input_A, *Input_B, *Vector_X, *Bloc_Vector_X;
- double *Bloc_Matrix_A, *Bloc_Precond_Matrix, *Buffer;
- double *Bloc_Residue_Vector ,*Bloc_HVector, *Bloc_Gradient_Vector;
- double *Direction_Vector, *Bloc_Direction_Vector;
- double Delta0, Delta1, Bloc_Delta0, Bloc_Delta1;
- double Tau, val, temp, Beta;
- double *AMatDirect_local, *XVector_local;
- double *ResidueVector_local, *DirectionVector_local;
- double StartTime, EndTime;
- MPI_Status status;
- FILE *fp;
- /*...Initialising MPI .......*/
- MPI_Init(&argc,&argv);
- MPI_Comm_size(MPI_COMM_WORLD,&NumProcs);
- MPI_Comm_rank(MPI_COMM_WORLD,&MyRank);
- /* .......Read the Input file ......*/
- if(MyRank == Root) {
- if ((fp = fopen ("./data/mdatcg.inp", "r")) == NULL) {
- printf("Can't open input matrix file");
- exit(-1);
- }
- fscanf(fp, "%d %d", &NoofRows,&NoofCols);
- n_size=NoofRows;
- /* ...Allocate memory and read data .....*/
- Matrix_A = (double **) malloc(n_size*sizeof(double *));
- for(irow = 0; irow < n_size; irow++){
- Matrix_A[irow] = (double *) malloc(n_size * sizeof(double));
- for(icol = 0; icol < n_size; icol++)
- fscanf(fp, "%lf", &Matrix_A[irow][icol]);
- }
- fclose(fp);
- if ((fp = fopen ("./data/vdatcg.inp", "r")) == NULL){
- printf("Can't open input vector file");
- exit(-1);
- }
- fscanf(fp, "%d", &VectorSize);
- n_size=VectorSize;
- Input_B = (double *)malloc(n_size*sizeof(double));
- for (irow = 0; irow<n_size; irow++)
- fscanf(fp, "%lf",&Input_B[irow]);
- fclose(fp);
- /* ...Convert Matrix_A into 1-D array Input_A ......*/
- Input_A = (double *)malloc(n_size*n_size*sizeof(double));
- index = 0;
- for(irow=0; irow<n_size; irow++)
- for(icol=0; icol<n_size; icol++)
- Input_A[index++] = Matrix_A[irow][icol];
- }
- MPI_Barrier(MPI_COMM_WORLD);
- StartTime = MPI_Wtime();
- /*...Broadcast Matrix and Vector size and perform input validation tests...*/
- MPI_Bcast(&NoofRows, 1, MPI_INT, Root, MPI_COMM_WORLD);
- MPI_Bcast(&NoofCols, 1, MPI_INT, Root, MPI_COMM_WORLD);
- MPI_Bcast(&VectorSize, 1, MPI_INT, Root, MPI_COMM_WORLD);
- if(NoofRows != NoofCols){
- MPI_Finalize();
- if(MyRank == Root)
- printf("Error : Coefficient Matrix Should be square matrix");
- exit(-1);
- }
- if(NoofRows != VectorSize){
- MPI_Finalize();
- if(MyRank == Root)
- printf("Error : Matrix Size should be equal to VectorSize");
- exit(-1);
- }
- if(NoofRows % NumProcs != 0){
- MPI_Finalize();
- if(MyRank == Root)
- printf("Error : Matrix cannot be evenly striped among processes");
- exit(-1);
- }
- /*...Allocate memory for Input_B and BroadCast Input_B.......*/
- if(MyRank != Root)
- Input_B = (double *) malloc(VectorSize*sizeof(double));
- MPI_Bcast(Input_B, VectorSize, MPI_DOUBLE, Root, MPI_COMM_WORLD);
- /*...Allocate memory for Block Matrix A and Scatter Input_A .......*/
- NoofRows_Bloc = NoofRows / NumProcs;
- Bloc_VectorSize = NoofRows_Bloc;
- Bloc_MatrixSize = NoofRows_Bloc * NoofCols;
- Bloc_Matrix_A = (double *) malloc (Bloc_MatrixSize*sizeof(double));
- MPI_Scatter(Input_A, Bloc_MatrixSize, MPI_DOUBLE,
- Bloc_Matrix_A, Bloc_MatrixSize, MPI_DOUBLE, Root, MPI_COMM_WORLD);
- /*... Allocates memory for solution vector and intialise it to zero.......*/
- Vector_X = (double *) malloc(VectorSize*sizeof(double));
- for(index=0; index<VectorSize; index++)
- Vector_X[index] = 0.0;
- /*...Calculate RESIDUE = AX - b .......*/
- Bloc_Residue_Vector = (double *) malloc(NoofRows_Bloc*sizeof(double));
- CalculateResidueVector(Bloc_Residue_Vector,Bloc_Matrix_A, Input_B, Vector_X,
- NoofRows_Bloc, VectorSize, MyRank);
- /*... Precondtion Matrix is identity matrix ......*/
- GetPreconditionMatrix( &Bloc_Precond_Matrix, NoofRows_Bloc, NoofCols);
- /*...Bloc_HVector = Bloc_Precond_Matrix inverse * Bloc_Residue_Vector......*/
- Bloc_HVector = (double *) malloc(Bloc_VectorSize*sizeof(double));
- SolvePrecondMatrix(Bloc_Precond_Matrix, Bloc_HVector, Bloc_Residue_Vector,
- Bloc_VectorSize);
- /*...Initailise Bloc Direction Vector = -(Bloc_HVector).......*/
- Bloc_Direction_Vector = (double *) malloc(Bloc_VectorSize*sizeof(double));
- for(index=0; index<Bloc_VectorSize; index++)
- Bloc_Direction_Vector[index] = 0 - Bloc_HVector[index];
- /*...Calculate Delta0 and check for convergence .......*/
- Bloc_Delta0 = ComputeVectorDotProduct(Bloc_Residue_Vector,
- Bloc_HVector, Bloc_VectorSize);
- MPI_Allreduce(&Bloc_Delta0, &Delta0, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- if(Delta0 < EPSILON){
- MPI_Finalize();
- exit(0);
- }
- /*...Allocate memory for Direction Vector.......*/
- Direction_Vector = (double *) malloc(VectorSize*sizeof(double));
- /*...Allocate temporary buffer to store Bloc_Matrix_A*Direction_Vector...*/
- Buffer = (double *) malloc(Bloc_VectorSize*sizeof(double));
- /*...Allocate memory for Bloc_Vector_X .......*/
- Bloc_Vector_X = (double *)malloc(Bloc_VectorSize*sizeof(double));
- Iteration = 0;
- do{
- Iteration++;
- /*
- if(MyRank == Root)
- printf("Iteration : %d\n",Iteration);
- */
- /*...Gather Direction Vector on all processes.......*/
- MPI_Allgather(Bloc_Direction_Vector, Bloc_VectorSize, MPI_DOUBLE,
- Direction_Vector, Bloc_VectorSize, MPI_DOUBLE, MPI_COMM_WORLD);
- /*...Compute Tau = Delta0 / (DirVector Transpose*Matrix_A*DirVector)...*/
- for(index=0; index<NoofRows_Bloc; index++){
- Buffer[index] = ComputeVectorDotProduct(&Bloc_Matrix_A[index*NoofCols],
- Direction_Vector, VectorSize);
- }
- temp = ComputeVectorDotProduct(Bloc_Direction_Vector, Buffer,
- Bloc_VectorSize);
- MPI_Allreduce(&temp, &val, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
- Tau = Delta0 / val;
- /*Compute new vector Xnew = Xold + Tau*Direction........................*/
- /*Compute BlocResidueVec = BlocResidueVect + Tau*Bloc_MatA*DirVector...*/
- for(index = 0; index<Bloc_VectorSize; index++){
- Bloc_Vector_X[index] = Vector_X[MyRank*Bloc_VectorSize + index] +
- Tau*Bloc_Direction_Vector[index];
- Bloc_Residue_Vector[index] = Bloc_Residue_Vector[index] +
- Tau*Buffer[index];
- }
- /*...Gather New Vector X at all processes......*/
- MPI_Allgather(Bloc_Vector_X, Bloc_VectorSize, MPI_DOUBLE, Vector_X,
- Bloc_VectorSize, MPI_DOUBLE, MPI_COMM_WORLD);
- SolvePrecondMatrix(Bloc_Precond_Matrix, Bloc_HVector, Bloc_Residue_Vector,
- Bloc_VectorSize);
- Bloc_Delta1 = ComputeVectorDotProduct(Bloc_Residue_Vector, Bloc_HVector,
- Bloc_VectorSize);
- MPI_Allreduce(&Bloc_Delta1, &Delta1, 1, MPI_DOUBLE, MPI_SUM,
- MPI_COMM_WORLD);
- if(Delta1 < EPSILON)
- break;
- Beta = Delta1 / Delta0;
- Delta0 = Delta1;
- for(index=0; index<Bloc_VectorSize; index++){
- Bloc_Direction_Vector[index] = -Bloc_HVector[index] +
- Beta*Bloc_Direction_Vector[index];
- }
- }while(Delta0 > EPSILON && Iteration < MAX_ITERATIONS);
- MPI_Barrier(MPI_COMM_WORLD);
- EndTime = MPI_Wtime();
- if (MyRank == 0) {
- printf ("\n");
- printf(" ------------------------------------------- \n");
- printf("Results of Jacobi Method on processor %d: \n", MyRank);
- printf ("\n");
- printf("Matrix Input_A \n");
- printf ("\n");
- for (irow = 0; irow < n_size; irow++) {
- for (icol = 0; icol < n_size; icol++)
- printf("%.3lf ", Matrix_A[irow][icol]);
- printf("\n");
- }
- printf ("\n");
- printf("Matrix Input_B \n");
- printf("\n");
- for (irow = 0; irow < n_size; irow++) {
- printf("%.3lf\n", Input_B[irow]);
- }
- printf ("\n");
- printf("Solution vector \n");
- printf("Number of iterations = %d\n",Iteration);
- printf ("\n");
- for(irow = 0; irow < n_size; irow++)
- printf("%.12lf\n",Vector_X[irow]);
- printf(" --------------------------------------------------- \n");
- }
- MPI_Finalize();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement