HYPRE_Int hypre_ParaSailsApply(hypre_ParaSails obj, HYPRE_Real *u, HYPRE_Real *v) { hypre_ParaSails_struct *internal = (hypre_ParaSails_struct *) obj; ParaSailsApply(internal->ps, u, v); return hypre_error_flag; }
/****************************************************************************** * Apply the PARALLEL Parasails preconditioner to a block of vectors. * Because Parasails is not block, we apply the preconditioner for each * block vector. * ******************************************************************************/ void par_ApplyParasailsPrec(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++) { ParaSailsApply(primme->preconditioner, &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)); }