Date: 2013-07-02T14:48:08+00:00

Actual source code: groppcg.c
petsc-3.4.2 2013-07-02

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

      3: /*
      4:  KSPSetUp_GROPPCG - Sets up the workspace needed by the GROPPCG method.

      6:  This is called once, usually automatically by KSPSolve() or KSPSetUp()
      7:  but can be called directly by KSPSetUp()
      8: */
     11: PetscErrorCode KSPSetUp_GROPPCG(KSP ksp)
     12: {

     16:   KSPSetWorkVecs(ksp,6);
     17:   return(0);
     18: }

     20: /*
     21:  KSPSolve_GROPPCG

     23:  Input Parameter:
     24:  .     ksp - the Krylov space object that was set to use conjugate gradient, by, for
     25:              example, KSPCreate(MPI_Comm,KSP *ksp); KSPSetType(ksp,KSPCG);
     26: */
     29: PetscErrorCode  KSPSolve_GROPPCG(KSP ksp)
     30: {
     32:   PetscInt       i;
     33:   PetscScalar    alpha,beta = 0.0,gamma,gammaNew,t;
     34:   PetscReal      dp = 0.0;
     35:   Vec            x,b,r,p,s,S,z,Z;
     36:   Mat            Amat,Pmat;
     37:   MatStructure   pflag;
     38:   PetscBool      diagonalscale;

     41:   PCGetDiagonalScale(ksp->pc,&diagonalscale);
     42:   if (diagonalscale) SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"Krylov method %s does not support diagonal scaling",((PetscObject)ksp)->type_name);

     44:   x = ksp->vec_sol;
     45:   b = ksp->vec_rhs;
     46:   r = ksp->work[0];
     47:   p = ksp->work[1];
     48:   s = ksp->work[2];
     49:   S = ksp->work[3];
     50:   z = ksp->work[4];
     51:   Z = ksp->work[5];

     53:   PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);

     55:   ksp->its = 0;
     56:   if (!ksp->guess_zero) {
     57:     KSP_MatMult(ksp,Amat,x,r);            /*     r <- b - Ax     */
     58:     VecAYPX(r,-1.0,b);
     59:   } else {
     60:     VecCopy(b,r);                         /*     r <- b (x is 0) */
     61:   }

     63:   KSP_PCApply(ksp,r,z);                   /*     z <- Br   */
     64:   VecCopy(z,p);                           /*     p <- z    */
     65:   VecDotBegin(r,z,&gamma);                  /*     gamma <- z'*r       */
     66:   PetscCommSplitReductionBegin(PetscObjectComm((PetscObject)r));
     67:   KSP_MatMult(ksp,Amat,p,s);              /*     s <- Ap   */
     68:   VecDotEnd(r,z,&gamma);                  /*     gamma <- z'*r       */

     70:   switch (ksp->normtype) {
     71:   case KSP_NORM_PRECONDITIONED:
     72:     /* This could be merged with the computation of gamma above */
     73:     VecNorm(z,NORM_2,&dp);                /*     dp <- z'*z = e'*A'*B'*B*A'*e'     */
     74:     break;
     75:   case KSP_NORM_UNPRECONDITIONED:
     76:     /* This could be merged with the computation of gamma above */
     77:     VecNorm(r,NORM_2,&dp);                /*     dp <- r'*r = e'*A'*A*e            */
     78:     break;
     79:   case KSP_NORM_NATURAL:
     80:     if (PetscIsInfOrNanScalar(gamma)) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_FP,"Infinite or not-a-number generated in dot product");
     81:     dp = PetscSqrtReal(PetscAbsScalar(gamma));                  /*     dp <- r'*z = r'*B*r = e'*A'*B*A*e */
     82:     break;
     83:   case KSP_NORM_NONE:
     84:     dp = 0.0;
     85:     break;
     86:   default: SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP,"%s",KSPNormTypes[ksp->normtype]);
     87:   }
     88:   KSPLogResidualHistory(ksp,dp);
     89:   KSPMonitor(ksp,0,dp);
     90:   ksp->rnorm = dp;
     91:   (*ksp->converged)(ksp,0,dp,&ksp->reason,ksp->cnvP); /* test for convergence */
     92:   if (ksp->reason) return(0);

     94:   i = 0;
     95:   do {
     96:     ksp->its = i+1;
     97:     i++;

     99:     VecDotBegin(p,s,&t);
    100:     PetscCommSplitReductionBegin(PetscObjectComm((PetscObject)p));

    102:     KSP_PCApply(ksp,s,S);         /*   S <- Bs       */

    104:     VecDotEnd(p,s,&t);

    106:     alpha = gamma / t;
    107:     VecAXPY(x, alpha,p);   /*     x <- x + alpha * p   */
    108:     VecAXPY(r,-alpha,s);   /*     r <- r - alpha * s   */
    109:     VecAXPY(z,-alpha,S);   /*     z <- z - alpha * S   */

    111:     if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
    112:       VecNormBegin(r,NORM_2,&dp);
    113:     } else if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
    114:       VecNormBegin(z,NORM_2,&dp);
    115:     }
    116:     VecDotBegin(r,z,&gammaNew);
    117:     PetscCommSplitReductionBegin(PetscObjectComm((PetscObject)r));

    119:     KSP_MatMult(ksp,Amat,z,Z);      /*   Z <- Az       */

    121:     if (ksp->normtype == KSP_NORM_UNPRECONDITIONED) {
    122:       VecNormEnd(r,NORM_2,&dp);
    123:     } else if (ksp->normtype == KSP_NORM_PRECONDITIONED) {
    124:       VecNormEnd(z,NORM_2,&dp);
    125:     }
    126:     VecDotEnd(r,z,&gammaNew);

    128:     if (ksp->normtype == KSP_NORM_NATURAL) {
    129:       if (PetscIsInfOrNanScalar(gammaNew)) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_FP,"Infinite or not-a-number generated in dot product");
    130:       dp = PetscSqrtReal(PetscAbsScalar(gammaNew));                  /*     dp <- r'*z = r'*B*r = e'*A'*B*A*e */
    131:     } else if (ksp->normtype == KSP_NORM_NONE) {
    132:       dp = 0.0;
    133:     }
    134:     ksp->rnorm = dp;
    135:     KSPLogResidualHistory(ksp,dp);
    136:     KSPMonitor(ksp,i,dp);
    137:     (*ksp->converged)(ksp,i,dp,&ksp->reason,ksp->cnvP);
    138:     if (ksp->reason) break;

    140:     beta  = gammaNew / gamma;
    141:     gamma = gammaNew;
    142:     VecAYPX(p,beta,z);   /*     p <- z + beta * p   */
    143:     VecAYPX(s,beta,Z);   /*     s <- Z + beta * s   */

    145:   } while (i<ksp->max_it);

    147:   if (i >= ksp->max_it) ksp->reason = KSP_DIVERGED_ITS;
    148:   return(0);
    149: }

    151: /*MC
    152:    KSPGROPPCG - A pipelined conjugate gradient method from Bill Gropp

    154:    There method has two reductions, one of which is overlapped with the matrix-vector product and one of which is
    155:    overlapped with the preconditioner.

    157:    See also KSPPIPECG, which has only a single reduction that overlaps both the matrix-vector product and the preconditioner.

    159:    Level:
    160:    beginner

    162:    Notes:
    163:    MPI configuration may be necessary for reductions to make asynchronous progress, which is important for performance of pipelined methods.
    164:    See the FAQ on the PETSc website for details.

    166:    Contributed by:
    167:    Pieter Ghysels, Universiteit Antwerpen, Intel Exascience lab Flanders

    169:    Reference:
    170:    http://www.cs.uiuc.edu/~wgropp/bib/talks/tdata/2012/icerm.pdf

    172: .seealso: KSPCreate(), KSPSetType(), KSPPIPECG, KSPPIPECR, KSPPGMRES, KSPCG, KSPCGUseSingleReduction()
    173: M*/

    177: PETSC_EXTERN PetscErrorCode KSPCreate_GROPPCG(KSP ksp)
    178: {

    182:   KSPSetSupportedNorm(ksp,KSP_NORM_UNPRECONDITIONED,PC_LEFT,1);
    183:   KSPSetSupportedNorm(ksp,KSP_NORM_PRECONDITIONED,PC_LEFT,1);
    184:   KSPSetSupportedNorm(ksp,KSP_NORM_NATURAL,PC_LEFT,1);
    185:   KSPSetSupportedNorm(ksp,KSP_NORM_NONE,PC_LEFT,1);

    187:   ksp->ops->setup          = KSPSetUp_GROPPCG;
    188:   ksp->ops->solve          = KSPSolve_GROPPCG;
    189:   ksp->ops->destroy        = KSPDestroyDefault;
    190:   ksp->ops->view           = 0;
    191:   ksp->ops->setfromoptions = 0;
    192:   ksp->ops->buildsolution  = KSPBuildSolutionDefault;
    193:   ksp->ops->buildresidual  = KSPBuildResidualDefault;
    194:   return(0);
    195: }