/****************************************************************************** * Applies the PARALLEL matrix vector mulitplication of a block of vectors. * Because a block function is not available, we call blockSize times * the Parasails function MatrixMatvec() * ******************************************************************************/ void par_MatrixMatvec(void *x, void *y, int *blockSize, primme_params *primme) { int i; double *xvec, *yvec; xvec = (double *)x; yvec = (double *)y; for (i=0;i<*blockSize;i++) { MatrixMatvec(primme->matrix, &xvec[primme->nLocal*i], &yvec[primme->nLocal*i]); } }
void PCG_ParaSails(Matrix *mat, ParaSails *ps, double *b, double *x, double tol, HYPRE_Int max_iter) { double *p, *s, *r; double alpha, beta; double gamma, gamma_old; double bi_prod, i_prod, eps; HYPRE_Int i = 0; HYPRE_Int mype; /* local problem size */ HYPRE_Int n = mat->end_row - mat->beg_row + 1; MPI_Comm comm = mat->comm; hypre_MPI_Comm_rank(comm, &mype); /* compute square of absolute stopping threshold */ /* bi_prod = <b,b> */ bi_prod = InnerProd(n, b, b, comm); eps = (tol*tol)*bi_prod; /* Check to see if the rhs vector b is zero */ if (bi_prod == 0.0) { /* Set x equal to zero and return */ CopyVector(n, b, x); return; } p = (double *) malloc(n * sizeof(double)); s = (double *) malloc(n * sizeof(double)); r = (double *) malloc(n * sizeof(double)); /* r = b - Ax */ MatrixMatvec(mat, x, r); /* r = Ax */ ScaleVector(n, -1.0, r); /* r = -r */ Axpy(n, 1.0, b, r); /* r = r + b */ /* p = C*r */ if (ps != NULL) ParaSailsApply(ps, r, p); else CopyVector(n, r, p); /* gamma = <r,p> */ gamma = InnerProd(n, r, p, comm); while ((i+1) <= max_iter) { i++; /* s = A*p */ MatrixMatvec(mat, p, s); /* alpha = gamma / <s,p> */ alpha = gamma / InnerProd(n, s, p, comm); gamma_old = gamma; /* x = x + alpha*p */ Axpy(n, alpha, p, x); /* r = r - alpha*s */ Axpy(n, -alpha, s, r); /* s = C*r */ if (ps != NULL) ParaSailsApply(ps, r, s); else CopyVector(n, r, s); /* gamma = <r,s> */ gamma = InnerProd(n, r, s, comm); /* set i_prod for convergence test */ i_prod = InnerProd(n, r, r, comm); #ifdef PARASAILS_CG_PRINT if (mype == 0 && i % 100 == 0) hypre_printf("Iter (%d): rel. resid. norm: %e\n", i, sqrt(i_prod/bi_prod)); #endif /* check for convergence */ if (i_prod < eps) break; /* non-convergence test */ if (i >= 1000 && i_prod/bi_prod > 0.01) { if (mype == 0) hypre_printf("Aborting solve due to slow or no convergence.\n"); break; } /* beta = gamma / gamma_old */ beta = gamma / gamma_old; /* p = s + beta p */ ScaleVector(n, beta, p); Axpy(n, 1.0, s, p); } free(p); free(s); /* compute exact relative residual norm */ MatrixMatvec(mat, x, r); /* r = Ax */ ScaleVector(n, -1.0, r); /* r = -r */ Axpy(n, 1.0, b, r); /* r = r + b */ i_prod = InnerProd(n, r, r, comm); free(r); if (mype == 0) hypre_printf("Iter (%4d): computed rrn : %e\n", i, sqrt(i_prod/bi_prod)); }
static void matvec_timing(MPI_Comm comm, Matrix *mat) { HYPRE_Real time0, time1; HYPRE_Real trial1, trial2, trial3, trial4, trial5, trial6; HYPRE_Real *temp1, *temp2; HYPRE_Int i, mype; HYPRE_Int n = mat->end_row - mat->beg_row + 1; temp1 = (HYPRE_Real *) calloc(n, sizeof(HYPRE_Real)); temp2 = (HYPRE_Real *) calloc(n, sizeof(HYPRE_Real)); /* warm-up */ hypre_MPI_Barrier(comm); for (i=0; i<100; i++) MatrixMatvec(mat, temp1, temp2); hypre_MPI_Barrier(comm); time0 = hypre_MPI_Wtime(); for (i=0; i<100; i++) MatrixMatvec(mat, temp1, temp2); hypre_MPI_Barrier(comm); time1 = hypre_MPI_Wtime(); trial1 = time1-time0; hypre_MPI_Barrier(comm); time0 = hypre_MPI_Wtime(); for (i=0; i<100; i++) MatrixMatvec(mat, temp1, temp2); hypre_MPI_Barrier(comm); time1 = hypre_MPI_Wtime(); trial2 = time1-time0; hypre_MPI_Barrier(comm); time0 = hypre_MPI_Wtime(); for (i=0; i<100; i++) MatrixMatvec(mat, temp1, temp2); hypre_MPI_Barrier(comm); time1 = hypre_MPI_Wtime(); trial3 = time1-time0; hypre_MPI_Barrier(comm); time0 = hypre_MPI_Wtime(); for (i=0; i<100; i++) MatrixMatvecSerial(mat, temp1, temp2); hypre_MPI_Barrier(comm); time1 = hypre_MPI_Wtime(); trial4 = time1-time0; hypre_MPI_Barrier(comm); time0 = hypre_MPI_Wtime(); for (i=0; i<100; i++) MatrixMatvecSerial(mat, temp1, temp2); hypre_MPI_Barrier(comm); time1 = hypre_MPI_Wtime(); trial5 = time1-time0; hypre_MPI_Barrier(comm); time0 = hypre_MPI_Wtime(); for (i=0; i<100; i++) MatrixMatvecSerial(mat, temp1, temp2); hypre_MPI_Barrier(comm); time1 = hypre_MPI_Wtime(); trial6 = time1-time0; hypre_MPI_Comm_rank(comm, &mype); if (mype == 0) hypre_printf("Timings: %f %f %f Serial: %f %f %f\n", trial1, trial2, trial3, trial4, trial5, trial6); fflush(stdout); /* this is all we wanted, so don't waste any more cycles */ exit(0); }