Example #1
0
static PetscErrorCode KSPSetUp_LSQR(KSP ksp)
{
  PetscErrorCode ierr;
  KSP_LSQR       *lsqr = (KSP_LSQR*)ksp->data;
  PetscBool      nopreconditioner;

  PetscFunctionBegin;
  ierr = PetscObjectTypeCompare((PetscObject)ksp->pc,PCNONE,&nopreconditioner);CHKERRQ(ierr);
  /*  nopreconditioner =PETSC_FALSE; */

  lsqr->nwork_m = 2;
  if (lsqr->vwork_m) {
    ierr = VecDestroyVecs(lsqr->nwork_m,&lsqr->vwork_m);CHKERRQ(ierr);
  }
  if (nopreconditioner) lsqr->nwork_n = 4;
  else lsqr->nwork_n = 5;

  if (lsqr->vwork_n) {
    ierr = VecDestroyVecs(lsqr->nwork_n,&lsqr->vwork_n);CHKERRQ(ierr);
  }
  ierr = KSPGetVecs(ksp,lsqr->nwork_n,&lsqr->vwork_n,lsqr->nwork_m,&lsqr->vwork_m);CHKERRQ(ierr);
  if (lsqr->se_flg && !lsqr->se) {
    /* lsqr->se is not set by user, get it from pmat */
    Vec *se;
    ierr     = KSPGetVecs(ksp,1,&se,0,NULL);CHKERRQ(ierr);
    lsqr->se = *se;
    ierr     = PetscFree(se);CHKERRQ(ierr);
  }
  PetscFunctionReturn(0);
}
Example #2
0
PetscErrorCode    KSPSetUp_LGMRES(KSP ksp)
{
  PetscErrorCode ierr;
  PetscInt       max_k,k, aug_dim;
  KSP_LGMRES     *lgmres = (KSP_LGMRES*)ksp->data;

  PetscFunctionBegin;
  max_k   = lgmres->max_k;
  aug_dim = lgmres->aug_dim;
  ierr    = KSPSetUp_GMRES(ksp);CHKERRQ(ierr);

  /* need array of pointers to augvecs*/
  ierr = PetscMalloc1((2 * aug_dim + AUG_OFFSET),&lgmres->augvecs);CHKERRQ(ierr);

  lgmres->aug_vecs_allocated = 2 *aug_dim + AUG_OFFSET;

  ierr = PetscMalloc1((2* aug_dim + AUG_OFFSET),&lgmres->augvecs_user_work);CHKERRQ(ierr);
  ierr = PetscMalloc1(aug_dim,&lgmres->aug_order);CHKERRQ(ierr);
  ierr = PetscLogObjectMemory((PetscObject)ksp,(aug_dim)*(4*sizeof(void*) + sizeof(PetscInt)) + AUG_OFFSET*2*sizeof(void*));CHKERRQ(ierr);

  /*  for now we will preallocate the augvecs - because aug_dim << restart
     ... also keep in mind that we need to keep augvecs from cycle to cycle*/
  lgmres->aug_vv_allocated = 2* aug_dim + AUG_OFFSET;
  lgmres->augwork_alloc    =  2* aug_dim + AUG_OFFSET;

  ierr = KSPGetVecs(ksp,lgmres->aug_vv_allocated,&lgmres->augvecs_user_work[0],0,NULL);CHKERRQ(ierr);
  ierr = PetscMalloc1((max_k+1),&lgmres->hwork);CHKERRQ(ierr);
  ierr = PetscLogObjectParents(ksp,lgmres->aug_vv_allocated,lgmres->augvecs_user_work[0]);CHKERRQ(ierr);
  for (k=0; k<lgmres->aug_vv_allocated; k++) {
    lgmres->augvecs[k] = lgmres->augvecs_user_work[0][k];
  }
  PetscFunctionReturn(0);
}
Example #3
0
PetscErrorCode KSPGMRESGetNewVectors(KSP ksp,PetscInt it)
{
  KSP_GMRES      *gmres = (KSP_GMRES*)ksp->data;
  PetscErrorCode ierr;
  PetscInt       nwork = gmres->nwork_alloc,k,nalloc;

  PetscFunctionBegin;
  nalloc = PetscMin(ksp->max_it,gmres->delta_allocate);
  /* Adjust the number to allocate to make sure that we don't exceed the
    number of available slots */
  if (it + VEC_OFFSET + nalloc >= gmres->vecs_allocated) {
    nalloc = gmres->vecs_allocated - it - VEC_OFFSET;
  }
  if (!nalloc) PetscFunctionReturn(0);

  gmres->vv_allocated += nalloc;

  ierr = KSPGetVecs(ksp,nalloc,&gmres->user_work[nwork],0,NULL);CHKERRQ(ierr);
  ierr = PetscLogObjectParents(ksp,nalloc,gmres->user_work[nwork]);CHKERRQ(ierr);

  gmres->mwork_alloc[nwork] = nalloc;
  for (k=0; k<nalloc; k++) {
    gmres->vecs[it+VEC_OFFSET+k] = gmres->user_work[nwork][k];
  }
  gmres->nwork_alloc++;
  PetscFunctionReturn(0);
}
Example #4
0
PetscErrorCode  KSPFischerGuessCreate_Method1(KSP ksp,int  maxl,KSPFischerGuess_Method1 **ITG)
{
  KSPFischerGuess_Method1 *itg;
  PetscErrorCode          ierr;

  PetscFunctionBegin;
  PetscValidHeaderSpecific(ksp,KSP_CLASSID,1);
  ierr = PetscMalloc(sizeof(KSPFischerGuess_Method1),&itg);CHKERRQ(ierr);
  ierr = PetscMalloc(maxl * sizeof(PetscScalar),&itg->alpha);CHKERRQ(ierr);
  ierr = PetscLogObjectMemory(ksp,sizeof(KSPFischerGuess_Method1) + maxl*sizeof(PetscScalar));CHKERRQ(ierr);
  ierr = KSPGetVecs(ksp,maxl,&itg->xtilde,0,PETSC_NULL);CHKERRQ(ierr);
  ierr = PetscLogObjectParents(ksp,maxl,itg->xtilde);CHKERRQ(ierr);
  ierr = KSPGetVecs(ksp,maxl,&itg->btilde,0,PETSC_NULL);CHKERRQ(ierr);
  ierr = PetscLogObjectParents(ksp,maxl,itg->btilde);CHKERRQ(ierr);
  ierr = VecDuplicate(itg->xtilde[0],&itg->guess);CHKERRQ(ierr);
  ierr = PetscLogObjectParent(ksp,itg->guess);CHKERRQ(ierr);
  *ITG = itg;
  PetscFunctionReturn(0);
}
Example #5
0
/*
  KSPSetWorkVecs - Sets a number of work vectors into a KSP object

  Input Parameters:
. ksp  - iterative context
. nw   - number of work vectors to allocate

   Developers Note: This is PETSC_EXTERN because it may be used by user written plugin KSP implementations

 */
PetscErrorCode KSPSetWorkVecs(KSP ksp,PetscInt nw)
{
  PetscErrorCode ierr;

  PetscFunctionBegin;
  ierr       = VecDestroyVecs(ksp->nwork,&ksp->work);CHKERRQ(ierr);
  ksp->nwork = nw;
  ierr       = KSPGetVecs(ksp,nw,&ksp->work,0,NULL);CHKERRQ(ierr);
  ierr       = PetscLogObjectParents(ksp,nw,ksp->work);CHKERRQ(ierr);
  PetscFunctionReturn(0);
}
Example #6
0
static PetscErrorCode KSPFGMRESGetNewVectors(KSP ksp,PetscInt it)
{
  KSP_FGMRES     *fgmres = (KSP_FGMRES*)ksp->data;
  PetscInt       nwork   = fgmres->nwork_alloc; /* number of work vector chunks allocated */
  PetscInt       nalloc;                      /* number to allocate */
  PetscErrorCode ierr;
  PetscInt       k;

  PetscFunctionBegin;
  nalloc = fgmres->delta_allocate; /* number of vectors to allocate
                                      in a single chunk */

  /* Adjust the number to allocate to make sure that we don't exceed the
     number of available slots (fgmres->vecs_allocated)*/
  if (it + VEC_OFFSET + nalloc >= fgmres->vecs_allocated) {
    nalloc = fgmres->vecs_allocated - it - VEC_OFFSET;
  }
  if (!nalloc) PetscFunctionReturn(0);

  fgmres->vv_allocated += nalloc; /* vv_allocated is the number of vectors allocated */

  /* work vectors */
  ierr = KSPGetVecs(ksp,nalloc,&fgmres->user_work[nwork],0,NULL);CHKERRQ(ierr);
  ierr = PetscLogObjectParents(ksp,nalloc,fgmres->user_work[nwork]);CHKERRQ(ierr);
  for (k=0; k < nalloc; k++) {
    fgmres->vecs[it+VEC_OFFSET+k] = fgmres->user_work[nwork][k];
  }
  /* specify size of chunk allocated */
  fgmres->mwork_alloc[nwork] = nalloc;

  /* preconditioned vectors */
  ierr = KSPGetVecs(ksp,nalloc,&fgmres->prevecs_user_work[nwork],0,NULL);CHKERRQ(ierr);
  ierr = PetscLogObjectParents(ksp,nalloc,fgmres->prevecs_user_work[nwork]);CHKERRQ(ierr);
  for (k=0; k < nalloc; k++) {
    fgmres->prevecs[it+VEC_OFFSET+k] = fgmres->prevecs_user_work[nwork][k];
  }

  /* increment the number of work vector chunks */
  fgmres->nwork_alloc++;
  PetscFunctionReturn(0);
}
Example #7
0
static PetscErrorCode KSPSetUp_LSQR(KSP ksp)
{
  PetscErrorCode ierr;
  KSP_LSQR       *lsqr = (KSP_LSQR*)ksp->data;
  PetscTruth     nopreconditioner;

  PetscFunctionBegin;
  ierr = PetscTypeCompare((PetscObject)ksp->pc,PCNONE,&nopreconditioner);CHKERRQ(ierr);
  if (ksp->pc_side == PC_SYMMETRIC){
    SETERRQ(PETSC_ERR_SUP,"no symmetric preconditioning for KSPLSQR");
  } else if (ksp->pc_side == PC_RIGHT){
    SETERRQ(PETSC_ERR_SUP,"no right preconditioning for KSPLSQR");
  }
  /*  nopreconditioner =PETSC_FALSE; */

  lsqr->nwork_m = 2;
  if (lsqr->vwork_m) {
    ierr = VecDestroyVecs(lsqr->vwork_m,lsqr->nwork_m);CHKERRQ(ierr);
  }
  if (nopreconditioner) {
     lsqr->nwork_n = 4;
  } else {
     lsqr->nwork_n = 5;
  }
  if (lsqr->vwork_n) {
    ierr = VecDestroyVecs(lsqr->vwork_n,lsqr->nwork_n);CHKERRQ(ierr);
  }
  ierr = KSPGetVecs(ksp,lsqr->nwork_n,&lsqr->vwork_n,lsqr->nwork_m,&lsqr->vwork_m);CHKERRQ(ierr);
  if (lsqr->se_flg && !lsqr->se){
    /* lsqr->se is not set by user, get it from pmat */
    Vec *se;
    ierr = KSPGetVecs(ksp,1,&se,0,PETSC_NULL);CHKERRQ(ierr);
    lsqr->se = *se;
    ierr = PetscFree(se);CHKERRQ(ierr);
  }
  PetscFunctionReturn(0);
}
Example #8
0
PetscErrorCode    KSPSetUp_FGMRES(KSP ksp)
{
  PetscErrorCode ierr;
  PetscInt       max_k,k;
  KSP_FGMRES     *fgmres = (KSP_FGMRES*)ksp->data;

  PetscFunctionBegin;
  max_k = fgmres->max_k;

  ierr = KSPSetUp_GMRES(ksp);CHKERRQ(ierr);

  ierr = PetscMalloc1((VEC_OFFSET+2+max_k),&fgmres->prevecs);CHKERRQ(ierr);
  ierr = PetscMalloc1((VEC_OFFSET+2+max_k),&fgmres->prevecs_user_work);CHKERRQ(ierr);
  ierr = PetscLogObjectMemory((PetscObject)ksp,(VEC_OFFSET+2+max_k)*(2*sizeof(void*)));CHKERRQ(ierr);

  ierr = KSPGetVecs(ksp,fgmres->vv_allocated,&fgmres->prevecs_user_work[0],0,NULL);CHKERRQ(ierr);
  ierr = PetscLogObjectParents(ksp,fgmres->vv_allocated,fgmres->prevecs_user_work[0]);CHKERRQ(ierr);
  for (k=0; k < fgmres->vv_allocated; k++) {
    fgmres->prevecs[k] = fgmres->prevecs_user_work[0][k];
  }
  PetscFunctionReturn(0);
}
Example #9
0
PetscErrorCode    KSPSetUp_GMRES(KSP ksp)
{
  PetscInt       hh,hes,rs,cc;
  PetscErrorCode ierr;
  PetscInt       max_k,k;
  KSP_GMRES      *gmres = (KSP_GMRES*)ksp->data;

  PetscFunctionBegin;
  max_k = gmres->max_k;          /* restart size */
  hh    = (max_k + 2) * (max_k + 1);
  hes   = (max_k + 1) * (max_k + 1);
  rs    = (max_k + 2);
  cc    = (max_k + 1);

  ierr = PetscMalloc5(hh,PetscScalar,&gmres->hh_origin,hes,PetscScalar,&gmres->hes_origin,rs,PetscScalar,&gmres->rs_origin,cc,PetscScalar,&gmres->cc_origin,cc,PetscScalar,&gmres->ss_origin);CHKERRQ(ierr);
  ierr = PetscMemzero(gmres->hh_origin,hh*sizeof(PetscScalar));CHKERRQ(ierr);
  ierr = PetscMemzero(gmres->hes_origin,hes*sizeof(PetscScalar));CHKERRQ(ierr);
  ierr = PetscMemzero(gmres->rs_origin,rs*sizeof(PetscScalar));CHKERRQ(ierr);
  ierr = PetscMemzero(gmres->cc_origin,cc*sizeof(PetscScalar));CHKERRQ(ierr);
  ierr = PetscMemzero(gmres->ss_origin,cc*sizeof(PetscScalar));CHKERRQ(ierr);
  ierr = PetscLogObjectMemory(ksp,(hh + hes + rs + 2*cc)*sizeof(PetscScalar));CHKERRQ(ierr);

  if (ksp->calc_sings) {
    /* Allocate workspace to hold Hessenberg matrix needed by lapack */
    ierr = PetscMalloc((max_k + 3)*(max_k + 9)*sizeof(PetscScalar),&gmres->Rsvd);CHKERRQ(ierr);
    ierr = PetscLogObjectMemory(ksp,(max_k + 3)*(max_k + 9)*sizeof(PetscScalar));CHKERRQ(ierr);
    ierr = PetscMalloc(6*(max_k+2)*sizeof(PetscReal),&gmres->Dsvd);CHKERRQ(ierr);
    ierr = PetscLogObjectMemory(ksp,6*(max_k+2)*sizeof(PetscReal));CHKERRQ(ierr);
  }

  /* Allocate array to hold pointers to user vectors.  Note that we need
   4 + max_k + 1 (since we need it+1 vectors, and it <= max_k) */
  gmres->vecs_allocated = VEC_OFFSET + 2 + max_k + gmres->nextra_vecs;

  ierr = PetscMalloc((gmres->vecs_allocated)*sizeof(Vec),&gmres->vecs);CHKERRQ(ierr);
  ierr = PetscMalloc((VEC_OFFSET+2+max_k)*sizeof(Vec*),&gmres->user_work);CHKERRQ(ierr);
  ierr = PetscMalloc((VEC_OFFSET+2+max_k)*sizeof(PetscInt),&gmres->mwork_alloc);CHKERRQ(ierr);
  ierr = PetscLogObjectMemory(ksp,(VEC_OFFSET+2+max_k)*(sizeof(Vec*)+sizeof(PetscInt)) + gmres->vecs_allocated*sizeof(Vec));CHKERRQ(ierr);

  if (gmres->q_preallocate) {
    gmres->vv_allocated = VEC_OFFSET + 2 + max_k;

    ierr = KSPGetVecs(ksp,gmres->vv_allocated,&gmres->user_work[0],0,NULL);CHKERRQ(ierr);
    ierr = PetscLogObjectParents(ksp,gmres->vv_allocated,gmres->user_work[0]);CHKERRQ(ierr);

    gmres->mwork_alloc[0] = gmres->vv_allocated;
    gmres->nwork_alloc    = 1;
    for (k=0; k<gmres->vv_allocated; k++) {
      gmres->vecs[k] = gmres->user_work[0][k];
    }
  } else {
    gmres->vv_allocated = 5;

    ierr = KSPGetVecs(ksp,5,&gmres->user_work[0],0,NULL);CHKERRQ(ierr);
    ierr = PetscLogObjectParents(ksp,5,gmres->user_work[0]);CHKERRQ(ierr);

    gmres->mwork_alloc[0] = 5;
    gmres->nwork_alloc    = 1;
    for (k=0; k<gmres->vv_allocated; k++) {
      gmres->vecs[k] = gmres->user_work[0][k];
    }
  }
  PetscFunctionReturn(0);
}
Example #10
0
PetscErrorCode PCSetUp_MG(PC pc)
{
    PC_MG          *mg        = (PC_MG*)pc->data;
    PC_MG_Levels   **mglevels = mg->levels;
    PetscErrorCode ierr;
    PetscInt       i,n = mglevels[0]->levels;
    PC             cpc;
    PetscBool      preonly,lu,redundant,cholesky,svd,dump = PETSC_FALSE,opsset,use_amat;
    Mat            dA,dB;
    MatStructure   uflag;
    Vec            tvec;
    DM             *dms;
    PetscViewer    viewer = 0;

    PetscFunctionBegin;
    /* FIX: Move this to PCSetFromOptions_MG? */
    if (mg->usedmfornumberoflevels) {
        PetscInt levels;
        ierr = DMGetRefineLevel(pc->dm,&levels);
        CHKERRQ(ierr);
        levels++;
        if (levels > n) { /* the problem is now being solved on a finer grid */
            ierr     = PCMGSetLevels(pc,levels,NULL);
            CHKERRQ(ierr);
            n        = levels;
            ierr     = PCSetFromOptions(pc);
            CHKERRQ(ierr); /* it is bad to call this here, but otherwise will never be called for the new hierarchy */
            mglevels =  mg->levels;
        }
    }
    ierr = KSPGetPC(mglevels[0]->smoothd,&cpc);
    CHKERRQ(ierr);


    /* If user did not provide fine grid operators OR operator was not updated since last global KSPSetOperators() */
    /* so use those from global PC */
    /* Is this what we always want? What if user wants to keep old one? */
    ierr = KSPGetOperatorsSet(mglevels[n-1]->smoothd,NULL,&opsset);
    CHKERRQ(ierr);
    if (opsset) {
        Mat mmat;
        ierr = KSPGetOperators(mglevels[n-1]->smoothd,NULL,&mmat,NULL);
        CHKERRQ(ierr);
        if (mmat == pc->pmat) opsset = PETSC_FALSE;
    }

    if (!opsset) {
        ierr = PCGetUseAmat(pc,&use_amat);
        CHKERRQ(ierr);
        if(use_amat) {
            ierr = PetscInfo(pc,"Using outer operators to define finest grid operator \n  because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n");
            CHKERRQ(ierr);
            ierr = KSPSetOperators(mglevels[n-1]->smoothd,pc->mat,pc->pmat,pc->flag);
            CHKERRQ(ierr);
        }
        else {
            ierr = PetscInfo(pc,"Using matrix (pmat) operators to define finest grid operator \n  because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n");
            CHKERRQ(ierr);
            ierr = KSPSetOperators(mglevels[n-1]->smoothd,pc->pmat,pc->pmat,pc->flag);
            CHKERRQ(ierr);
        }
    }

    /* Skipping this for galerkin==2 (externally managed hierarchy such as ML and GAMG). Cleaner logic here would be great. Wrap ML/GAMG as DMs? */
    if (pc->dm && mg->galerkin != 2 && !pc->setupcalled) {
        /* construct the interpolation from the DMs */
        Mat p;
        Vec rscale;
        ierr     = PetscMalloc(n*sizeof(DM),&dms);
        CHKERRQ(ierr);
        dms[n-1] = pc->dm;
        for (i=n-2; i>-1; i--) {
            DMKSP kdm;
            ierr = DMCoarsen(dms[i+1],MPI_COMM_NULL,&dms[i]);
            CHKERRQ(ierr);
            ierr = KSPSetDM(mglevels[i]->smoothd,dms[i]);
            CHKERRQ(ierr);
            if (mg->galerkin) {
                ierr = KSPSetDMActive(mglevels[i]->smoothd,PETSC_FALSE);
                CHKERRQ(ierr);
            }
            ierr = DMGetDMKSPWrite(dms[i],&kdm);
            CHKERRQ(ierr);
            /* Ugly hack so that the next KSPSetUp() will use the RHS that we set. A better fix is to change dmActive to take
             * a bitwise OR of computing the matrix, RHS, and initial iterate. */
            kdm->ops->computerhs = NULL;
            kdm->rhsctx          = NULL;
            if (!mglevels[i+1]->interpolate) {
                ierr = DMCreateInterpolation(dms[i],dms[i+1],&p,&rscale);
                CHKERRQ(ierr);
                ierr = PCMGSetInterpolation(pc,i+1,p);
                CHKERRQ(ierr);
                if (rscale) {
                    ierr = PCMGSetRScale(pc,i+1,rscale);
                    CHKERRQ(ierr);
                }
                ierr = VecDestroy(&rscale);
                CHKERRQ(ierr);
                ierr = MatDestroy(&p);
                CHKERRQ(ierr);
            }
        }

        for (i=n-2; i>-1; i--) {
            ierr = DMDestroy(&dms[i]);
            CHKERRQ(ierr);
        }
        ierr = PetscFree(dms);
        CHKERRQ(ierr);
    }

    if (pc->dm && !pc->setupcalled) {
        /* finest smoother also gets DM but it is not active, independent of whether galerkin==2 */
        ierr = KSPSetDM(mglevels[n-1]->smoothd,pc->dm);
        CHKERRQ(ierr);
        ierr = KSPSetDMActive(mglevels[n-1]->smoothd,PETSC_FALSE);
        CHKERRQ(ierr);
    }

    if (mg->galerkin == 1) {
        Mat B;
        /* currently only handle case where mat and pmat are the same on coarser levels */
        ierr = KSPGetOperators(mglevels[n-1]->smoothd,&dA,&dB,&uflag);
        CHKERRQ(ierr);
        if (!pc->setupcalled) {
            for (i=n-2; i>-1; i--) {
                ierr = MatPtAP(dB,mglevels[i+1]->interpolate,MAT_INITIAL_MATRIX,1.0,&B);
                CHKERRQ(ierr);
                ierr = KSPSetOperators(mglevels[i]->smoothd,B,B,uflag);
                CHKERRQ(ierr);
                if (i != n-2) {
                    ierr = PetscObjectDereference((PetscObject)dB);
                    CHKERRQ(ierr);
                }
                dB = B;
            }
            if (n > 1) {
                ierr = PetscObjectDereference((PetscObject)dB);
                CHKERRQ(ierr);
            }
        } else {
            for (i=n-2; i>-1; i--) {
                ierr = KSPGetOperators(mglevels[i]->smoothd,NULL,&B,NULL);
                CHKERRQ(ierr);
                ierr = MatPtAP(dB,mglevels[i+1]->interpolate,MAT_REUSE_MATRIX,1.0,&B);
                CHKERRQ(ierr);
                ierr = KSPSetOperators(mglevels[i]->smoothd,B,B,uflag);
                CHKERRQ(ierr);
                dB   = B;
            }
        }
    } else if (!mg->galerkin && pc->dm && pc->dm->x) {
        /* need to restrict Jacobian location to coarser meshes for evaluation */
        for (i=n-2; i>-1; i--) {
            Mat R;
            Vec rscale;
            if (!mglevels[i]->smoothd->dm->x) {
                Vec *vecs;
                ierr = KSPGetVecs(mglevels[i]->smoothd,1,&vecs,0,NULL);
                CHKERRQ(ierr);

                mglevels[i]->smoothd->dm->x = vecs[0];

                ierr = PetscFree(vecs);
                CHKERRQ(ierr);
            }
            ierr = PCMGGetRestriction(pc,i+1,&R);
            CHKERRQ(ierr);
            ierr = PCMGGetRScale(pc,i+1,&rscale);
            CHKERRQ(ierr);
            ierr = MatRestrict(R,mglevels[i+1]->smoothd->dm->x,mglevels[i]->smoothd->dm->x);
            CHKERRQ(ierr);
            ierr = VecPointwiseMult(mglevels[i]->smoothd->dm->x,mglevels[i]->smoothd->dm->x,rscale);
            CHKERRQ(ierr);
        }
    }
    if (!mg->galerkin && pc->dm) {
        for (i=n-2; i>=0; i--) {
            DM  dmfine,dmcoarse;
            Mat Restrict,Inject;
            Vec rscale;
            ierr   = KSPGetDM(mglevels[i+1]->smoothd,&dmfine);
            CHKERRQ(ierr);
            ierr   = KSPGetDM(mglevels[i]->smoothd,&dmcoarse);
            CHKERRQ(ierr);
            ierr   = PCMGGetRestriction(pc,i+1,&Restrict);
            CHKERRQ(ierr);
            ierr   = PCMGGetRScale(pc,i+1,&rscale);
            CHKERRQ(ierr);
            Inject = NULL;      /* Callback should create it if it needs Injection */
            ierr   = DMRestrict(dmfine,Restrict,rscale,Inject,dmcoarse);
            CHKERRQ(ierr);
        }
    }

    if (!pc->setupcalled) {
        for (i=0; i<n; i++) {
            ierr = KSPSetFromOptions(mglevels[i]->smoothd);
            CHKERRQ(ierr);
        }
        for (i=1; i<n; i++) {
            if (mglevels[i]->smoothu && (mglevels[i]->smoothu != mglevels[i]->smoothd)) {
                ierr = KSPSetFromOptions(mglevels[i]->smoothu);
                CHKERRQ(ierr);
            }
        }
        for (i=1; i<n; i++) {
            ierr = PCMGGetInterpolation(pc,i,&mglevels[i]->interpolate);
            CHKERRQ(ierr);
            ierr = PCMGGetRestriction(pc,i,&mglevels[i]->restrct);
            CHKERRQ(ierr);
        }
        for (i=0; i<n-1; i++) {
            if (!mglevels[i]->b) {
                Vec *vec;
                ierr = KSPGetVecs(mglevels[i]->smoothd,1,&vec,0,NULL);
                CHKERRQ(ierr);
                ierr = PCMGSetRhs(pc,i,*vec);
                CHKERRQ(ierr);
                ierr = VecDestroy(vec);
                CHKERRQ(ierr);
                ierr = PetscFree(vec);
                CHKERRQ(ierr);
            }
            if (!mglevels[i]->r && i) {
                ierr = VecDuplicate(mglevels[i]->b,&tvec);
                CHKERRQ(ierr);
                ierr = PCMGSetR(pc,i,tvec);
                CHKERRQ(ierr);
                ierr = VecDestroy(&tvec);
                CHKERRQ(ierr);
            }
            if (!mglevels[i]->x) {
                ierr = VecDuplicate(mglevels[i]->b,&tvec);
                CHKERRQ(ierr);
                ierr = PCMGSetX(pc,i,tvec);
                CHKERRQ(ierr);
                ierr = VecDestroy(&tvec);
                CHKERRQ(ierr);
            }
        }
        if (n != 1 && !mglevels[n-1]->r) {
            /* PCMGSetR() on the finest level if user did not supply it */
            Vec *vec;
            ierr = KSPGetVecs(mglevels[n-1]->smoothd,1,&vec,0,NULL);
            CHKERRQ(ierr);
            ierr = PCMGSetR(pc,n-1,*vec);
            CHKERRQ(ierr);
            ierr = VecDestroy(vec);
            CHKERRQ(ierr);
            ierr = PetscFree(vec);
            CHKERRQ(ierr);
        }
    }

    if (pc->dm) {
        /* need to tell all the coarser levels to rebuild the matrix using the DM for that level */
        for (i=0; i<n-1; i++) {
            if (mglevels[i]->smoothd->setupstage != KSP_SETUP_NEW) mglevels[i]->smoothd->setupstage = KSP_SETUP_NEWMATRIX;
        }
    }

    for (i=1; i<n; i++) {
        if (mglevels[i]->smoothu == mglevels[i]->smoothd) {
            /* if doing only down then initial guess is zero */
            ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothd,PETSC_TRUE);
            CHKERRQ(ierr);
        }
        if (mglevels[i]->eventsmoothsetup) {
            ierr = PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0);
            CHKERRQ(ierr);
        }
        ierr = KSPSetUp(mglevels[i]->smoothd);
        CHKERRQ(ierr);
        if (mglevels[i]->eventsmoothsetup) {
            ierr = PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0);
            CHKERRQ(ierr);
        }
        if (!mglevels[i]->residual) {
            Mat mat;
            ierr = KSPGetOperators(mglevels[i]->smoothd,NULL,&mat,NULL);
            CHKERRQ(ierr);
            ierr = PCMGSetResidual(pc,i,PCMGResidual_Default,mat);
            CHKERRQ(ierr);
        }
    }
    for (i=1; i<n; i++) {
        if (mglevels[i]->smoothu && mglevels[i]->smoothu != mglevels[i]->smoothd) {
            Mat          downmat,downpmat;
            MatStructure matflag;

            /* check if operators have been set for up, if not use down operators to set them */
            ierr = KSPGetOperatorsSet(mglevels[i]->smoothu,&opsset,NULL);
            CHKERRQ(ierr);
            if (!opsset) {
                ierr = KSPGetOperators(mglevels[i]->smoothd,&downmat,&downpmat,&matflag);
                CHKERRQ(ierr);
                ierr = KSPSetOperators(mglevels[i]->smoothu,downmat,downpmat,matflag);
                CHKERRQ(ierr);
            }

            ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothu,PETSC_TRUE);
            CHKERRQ(ierr);
            if (mglevels[i]->eventsmoothsetup) {
                ierr = PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0);
                CHKERRQ(ierr);
            }
            ierr = KSPSetUp(mglevels[i]->smoothu);
            CHKERRQ(ierr);
            if (mglevels[i]->eventsmoothsetup) {
                ierr = PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0);
                CHKERRQ(ierr);
            }
        }
    }

    /*
        If coarse solver is not direct method then DO NOT USE preonly
    */
    ierr = PetscObjectTypeCompare((PetscObject)mglevels[0]->smoothd,KSPPREONLY,&preonly);
    CHKERRQ(ierr);
    if (preonly) {
        ierr = PetscObjectTypeCompare((PetscObject)cpc,PCLU,&lu);
        CHKERRQ(ierr);
        ierr = PetscObjectTypeCompare((PetscObject)cpc,PCREDUNDANT,&redundant);
        CHKERRQ(ierr);
        ierr = PetscObjectTypeCompare((PetscObject)cpc,PCCHOLESKY,&cholesky);
        CHKERRQ(ierr);
        ierr = PetscObjectTypeCompare((PetscObject)cpc,PCSVD,&svd);
        CHKERRQ(ierr);
        if (!lu && !redundant && !cholesky && !svd) {
            ierr = KSPSetType(mglevels[0]->smoothd,KSPGMRES);
            CHKERRQ(ierr);
        }
    }

    if (!pc->setupcalled) {
        ierr = KSPSetFromOptions(mglevels[0]->smoothd);
        CHKERRQ(ierr);
    }

    if (mglevels[0]->eventsmoothsetup) {
        ierr = PetscLogEventBegin(mglevels[0]->eventsmoothsetup,0,0,0,0);
        CHKERRQ(ierr);
    }
    ierr = KSPSetUp(mglevels[0]->smoothd);
    CHKERRQ(ierr);
    if (mglevels[0]->eventsmoothsetup) {
        ierr = PetscLogEventEnd(mglevels[0]->eventsmoothsetup,0,0,0,0);
        CHKERRQ(ierr);
    }

    /*
       Dump the interpolation/restriction matrices plus the
     Jacobian/stiffness on each level. This allows MATLAB users to
     easily check if the Galerkin condition A_c = R A_f R^T is satisfied.

     Only support one or the other at the same time.
    */
#if defined(PETSC_USE_SOCKET_VIEWER)
    ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_mg_dump_matlab",&dump,NULL);
    CHKERRQ(ierr);
    if (dump) viewer = PETSC_VIEWER_SOCKET_(PetscObjectComm((PetscObject)pc));
    dump = PETSC_FALSE;
#endif
    ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_mg_dump_binary",&dump,NULL);
    CHKERRQ(ierr);
    if (dump) viewer = PETSC_VIEWER_BINARY_(PetscObjectComm((PetscObject)pc));

    if (viewer) {
        for (i=1; i<n; i++) {
            ierr = MatView(mglevels[i]->restrct,viewer);
            CHKERRQ(ierr);
        }
        for (i=0; i<n; i++) {
            ierr = KSPGetPC(mglevels[i]->smoothd,&pc);
            CHKERRQ(ierr);
            ierr = MatView(pc->mat,viewer);
            CHKERRQ(ierr);
        }
    }
    PetscFunctionReturn(0);
}