Actual source code: pipecr.c

  1: #include <petsc/private/kspimpl.h>

  3: /*
  4:      KSPSetUp_PIPECR - Sets up the workspace needed by the PIPECR method.

  6:       This is called once, usually automatically by KSPSolve() or KSPSetUp()
  7:      but can be called directly by KSPSetUp()
  8: */
  9: static PetscErrorCode KSPSetUp_PIPECR(KSP ksp)
 10: {
 11:   PetscFunctionBegin;
 12:   /* get work vectors needed by PIPECR */
 13:   PetscCall(KSPSetWorkVecs(ksp, 7));
 14:   PetscFunctionReturn(PETSC_SUCCESS);
 15: }

 17: /*
 18:  KSPSolve_PIPECR - This routine actually applies the pipelined conjugate residual method
 19: */
 20: static PetscErrorCode KSPSolve_PIPECR(KSP ksp)
 21: {
 22:   PetscInt    i;
 23:   PetscScalar alpha = 0.0, beta = 0.0, gamma, gammaold = 0.0, delta;
 24:   PetscReal   dp = 0.0;
 25:   Vec         X, B, Z, P, W, Q, U, M, N;
 26:   Mat         Amat, Pmat;

 28:   PetscFunctionBegin;
 29:   X = ksp->vec_sol;
 30:   B = ksp->vec_rhs;
 31:   M = ksp->work[0];
 32:   Z = ksp->work[1];
 33:   P = ksp->work[2];
 34:   N = ksp->work[3];
 35:   W = ksp->work[4];
 36:   Q = ksp->work[5];
 37:   U = ksp->work[6];

 39:   PetscCall(PCGetOperators(ksp->pc, &Amat, &Pmat));

 41:   ksp->its = 0;
 42:   /* we don't have an R vector, so put the (unpreconditioned) residual in w for now */
 43:   if (!ksp->guess_zero) {
 44:     PetscCall(KSP_MatMult(ksp, Amat, X, W)); /*     w <- b - Ax     */
 45:     PetscCall(VecAYPX(W, -1.0, B));
 46:   } else {
 47:     PetscCall(VecCopy(B, W)); /*     w <- b (x is 0) */
 48:   }
 49:   PetscCall(KSP_PCApply(ksp, W, U)); /*     u <- Bw   */

 51:   switch (ksp->normtype) {
 52:   case KSP_NORM_PRECONDITIONED:
 53:     PetscCall(VecNormBegin(U, NORM_2, &dp)); /*     dp <- u'*u = e'*A'*B'*B*A'*e'     */
 54:     PetscCall(PetscCommSplitReductionBegin(PetscObjectComm((PetscObject)U)));
 55:     PetscCall(KSP_MatMult(ksp, Amat, U, W)); /*     w <- Au   */
 56:     PetscCall(VecNormEnd(U, NORM_2, &dp));
 57:     break;
 58:   case KSP_NORM_NONE:
 59:     PetscCall(KSP_MatMult(ksp, Amat, U, W));
 60:     dp = 0.0;
 61:     break;
 62:   default:
 63:     SETERRQ(PetscObjectComm((PetscObject)ksp), PETSC_ERR_SUP, "%s", KSPNormTypes[ksp->normtype]);
 64:   }
 65:   PetscCall(KSPLogResidualHistory(ksp, dp));
 66:   PetscCall(KSPMonitor(ksp, 0, dp));
 67:   ksp->rnorm = dp;
 68:   PetscCall((*ksp->converged)(ksp, 0, dp, &ksp->reason, ksp->cnvP)); /* test for convergence */
 69:   if (ksp->reason) PetscFunctionReturn(PETSC_SUCCESS);

 71:   i = 0;
 72:   do {
 73:     PetscCall(KSP_PCApply(ksp, W, M)); /*   m <- Bw       */

 75:     if (i > 0 && ksp->normtype == KSP_NORM_PRECONDITIONED) PetscCall(VecNormBegin(U, NORM_2, &dp));
 76:     PetscCall(VecDotBegin(W, U, &gamma));
 77:     PetscCall(VecDotBegin(M, W, &delta));
 78:     PetscCall(PetscCommSplitReductionBegin(PetscObjectComm((PetscObject)U)));

 80:     PetscCall(KSP_MatMult(ksp, Amat, M, N)); /*   n <- Am       */

 82:     if (i > 0 && ksp->normtype == KSP_NORM_PRECONDITIONED) PetscCall(VecNormEnd(U, NORM_2, &dp));
 83:     PetscCall(VecDotEnd(W, U, &gamma));
 84:     PetscCall(VecDotEnd(M, W, &delta));

 86:     if (i > 0) {
 87:       if (ksp->normtype == KSP_NORM_NONE) dp = 0.0;
 88:       ksp->rnorm = dp;
 89:       PetscCall(KSPLogResidualHistory(ksp, dp));
 90:       PetscCall(KSPMonitor(ksp, i, dp));
 91:       PetscCall((*ksp->converged)(ksp, i, dp, &ksp->reason, ksp->cnvP));
 92:       if (ksp->reason) PetscFunctionReturn(PETSC_SUCCESS);
 93:     }

 95:     if (i == 0) {
 96:       alpha = gamma / delta;
 97:       PetscCall(VecCopy(N, Z)); /*     z <- n          */
 98:       PetscCall(VecCopy(M, Q)); /*     q <- m          */
 99:       PetscCall(VecCopy(U, P)); /*     p <- u          */
100:     } else {
101:       beta  = gamma / gammaold;
102:       alpha = gamma / (delta - beta / alpha * gamma);
103:       PetscCall(VecAYPX(Z, beta, N)); /*     z <- n + beta * z   */
104:       PetscCall(VecAYPX(Q, beta, M)); /*     q <- m + beta * q   */
105:       PetscCall(VecAYPX(P, beta, U)); /*     p <- u + beta * p   */
106:     }
107:     PetscCall(VecAXPY(X, alpha, P));  /*     x <- x + alpha * p   */
108:     PetscCall(VecAXPY(U, -alpha, Q)); /*     u <- u - alpha * q   */
109:     PetscCall(VecAXPY(W, -alpha, Z)); /*     w <- w - alpha * z   */
110:     gammaold = gamma;
111:     i++;
112:     ksp->its = i;

114:     /* if (i%50 == 0) { */
115:     /*   PetscCall(KSP_MatMult(ksp,Amat,X,W));            /\*     w <- b - Ax     *\/ */
116:     /*   PetscCall(VecAYPX(W,-1.0,B)); */
117:     /*   PetscCall(KSP_PCApply(ksp,W,U)); */
118:     /*   PetscCall(KSP_MatMult(ksp,Amat,U,W)); */
119:     /* } */

121:   } while (i <= ksp->max_it);
122:   if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS;
123:   PetscFunctionReturn(PETSC_SUCCESS);
124: }

126: /*MC
127:    KSPPIPECR - Pipelined conjugate residual method {cite}`ghyselsvanroose2014`. [](sec_pipelineksp)

129:    Level: intermediate

131:    Notes:
132:    This method has only a single non-blocking reduction per iteration, compared to 2 for standard `KSPCR`.  The
133:    non-blocking reduction is overlapped by the matrix-vector product, but not the preconditioner application.

135:    See also `KSPPIPECG`, where the reduction is overlapped with the matrix-vector product.

137:    MPI configuration may be necessary for reductions to make asynchronous progress, which is important for performance of pipelined methods.
138:    See [](doc_faq_pipelined)

140:    Contributed by:
141:    Pieter Ghysels, Universiteit Antwerpen, Intel Exascience lab Flanders

143: .seealso: [](ch_ksp), [](sec_pipelineksp), [](doc_faq_pipelined), `KSPCreate()`, `KSPSetType()`, `KSPPIPECG`, `KSPGROPPCG`, `KSPPGMRES`, `KSPCG`, `KSPCGUseSingleReduction()`
144: M*/

146: PETSC_EXTERN PetscErrorCode KSPCreate_PIPECR(KSP ksp)
147: {
148:   PetscFunctionBegin;
149:   PetscCall(KSPSetSupportedNorm(ksp, KSP_NORM_PRECONDITIONED, PC_LEFT, 2));
150:   PetscCall(KSPSetSupportedNorm(ksp, KSP_NORM_NONE, PC_LEFT, 1));

152:   ksp->ops->setup          = KSPSetUp_PIPECR;
153:   ksp->ops->solve          = KSPSolve_PIPECR;
154:   ksp->ops->destroy        = KSPDestroyDefault;
155:   ksp->ops->view           = NULL;
156:   ksp->ops->setfromoptions = NULL;
157:   ksp->ops->buildsolution  = KSPBuildSolutionDefault;
158:   ksp->ops->buildresidual  = KSPBuildResidualDefault;
159:   PetscFunctionReturn(PETSC_SUCCESS);
160: }