PETSC_EXTERN void PETSC_STDCALL pcmgsetcycletype_(PC pc,PCMGCycleType *n, int *__ierr ){ *__ierr = PCMGSetCycleType( (PC)PetscToPointer((pc) ),*n); }
PetscErrorCode PCSetFromOptions_MG(PetscOptionItems *PetscOptionsObject,PC pc) { PetscErrorCode ierr; PetscInt m,levels = 1,cycles; PetscBool flg,set; PC_MG *mg = (PC_MG*)pc->data; PC_MG_Levels **mglevels; PCMGType mgtype; PCMGCycleType mgctype; PetscFunctionBegin; ierr = PetscOptionsHead(PetscOptionsObject,"Multigrid options");CHKERRQ(ierr); if (!mg->levels) { ierr = PetscOptionsInt("-pc_mg_levels","Number of Levels","PCMGSetLevels",levels,&levels,&flg);CHKERRQ(ierr); if (!flg && pc->dm) { ierr = DMGetRefineLevel(pc->dm,&levels);CHKERRQ(ierr); levels++; mg->usedmfornumberoflevels = PETSC_TRUE; } ierr = PCMGSetLevels(pc,levels,NULL);CHKERRQ(ierr); } mglevels = mg->levels; mgctype = (PCMGCycleType) mglevels[0]->cycles; ierr = PetscOptionsEnum("-pc_mg_cycle_type","V cycle or for W-cycle","PCMGSetCycleType",PCMGCycleTypes,(PetscEnum)mgctype,(PetscEnum*)&mgctype,&flg);CHKERRQ(ierr); if (flg) { ierr = PCMGSetCycleType(pc,mgctype);CHKERRQ(ierr); } flg = PETSC_FALSE; ierr = PetscOptionsBool("-pc_mg_galerkin","Use Galerkin process to compute coarser operators","PCMGSetGalerkin",flg,&flg,&set);CHKERRQ(ierr); if (set) { ierr = PCMGSetGalerkin(pc,flg);CHKERRQ(ierr); } ierr = PetscOptionsInt("-pc_mg_smoothup","Number of post-smoothing steps","PCMGSetNumberSmoothUp",mg->default_smoothu,&m,&flg);CHKERRQ(ierr); if (flg) { ierr = PCMGSetNumberSmoothUp(pc,m);CHKERRQ(ierr); } ierr = PetscOptionsInt("-pc_mg_smoothdown","Number of pre-smoothing steps","PCMGSetNumberSmoothDown",mg->default_smoothd,&m,&flg);CHKERRQ(ierr); if (flg) { ierr = PCMGSetNumberSmoothDown(pc,m);CHKERRQ(ierr); } mgtype = mg->am; ierr = PetscOptionsEnum("-pc_mg_type","Multigrid type","PCMGSetType",PCMGTypes,(PetscEnum)mgtype,(PetscEnum*)&mgtype,&flg);CHKERRQ(ierr); if (flg) { ierr = PCMGSetType(pc,mgtype);CHKERRQ(ierr); } if (mg->am == PC_MG_MULTIPLICATIVE) { ierr = PetscOptionsInt("-pc_mg_multiplicative_cycles","Number of cycles for each preconditioner step","PCMGMultiplicativeSetCycles",mg->cyclesperpcapply,&cycles,&flg);CHKERRQ(ierr); if (flg) { ierr = PCMGMultiplicativeSetCycles(pc,cycles);CHKERRQ(ierr); } } flg = PETSC_FALSE; ierr = PetscOptionsBool("-pc_mg_log","Log times for each multigrid level","None",flg,&flg,NULL);CHKERRQ(ierr); if (flg) { PetscInt i; char eventname[128]; if (!mglevels) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must set MG levels before calling"); levels = mglevels[0]->levels; for (i=0; i<levels; i++) { sprintf(eventname,"MGSetup Level %d",(int)i); ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventsmoothsetup);CHKERRQ(ierr); sprintf(eventname,"MGSmooth Level %d",(int)i); ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventsmoothsolve);CHKERRQ(ierr); if (i) { sprintf(eventname,"MGResid Level %d",(int)i); ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventresidual);CHKERRQ(ierr); sprintf(eventname,"MGInterp Level %d",(int)i); ierr = PetscLogEventRegister(eventname,((PetscObject)pc)->classid,&mglevels[i]->eventinterprestrict);CHKERRQ(ierr); } } #if defined(PETSC_USE_LOG) { const char *sname = "MG Apply"; PetscStageLog stageLog; PetscInt st; PetscFunctionBegin; ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); for (st = 0; st < stageLog->numStages; ++st) { PetscBool same; ierr = PetscStrcmp(stageLog->stageInfo[st].name, sname, &same);CHKERRQ(ierr); if (same) mg->stageApply = st; } if (!mg->stageApply) { ierr = PetscLogStageRegister(sname, &mg->stageApply);CHKERRQ(ierr); } } #endif } ierr = PetscOptionsTail();CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc, char** argv) { int levels = 4; int mg_levels = 3; PetscInitialize(&argc, &argv, PETSC_NULL, PETSC_NULL); construct_operator(&problem, levels); KSP ksp; PC pc; KSPCreate(PETSC_COMM_WORLD, &ksp); KSPSetOperators(ksp, problem.A, problem.A, SAME_PRECONDITIONER); KSPSetType(ksp, KSPRICHARDSON); if (1) { KSPGetPC(ksp, &pc); PCSetType(pc, PCMG); PCMGSetLevels(pc, mg_levels, NULL); PCMGSetGalerkin(pc); PCMGSetType(pc, PC_MG_MULTIPLICATIVE); PCMGSetCycleType(pc, PC_MG_CYCLE_V); int ii; for (ii=0; ii<mg_levels; ii++) { if (ii == 0) { KSP smooth_ksp; PCMGGetSmoother(pc, ii, &smooth_ksp); KSPSetType(smooth_ksp, KSPPREONLY); PC smooth_pc; KSPGetPC(smooth_ksp, &smooth_pc); PCSetType(smooth_pc, PCLU); } else { // set up the smoother. KSP smooth_ksp; PC smooth_pc; PCMGGetSmoother(pc, ii, &smooth_ksp); KSPSetType(smooth_ksp, KSPRICHARDSON); KSPRichardsonSetScale(smooth_ksp, 2./3.); KSPGetPC(smooth_ksp, &smooth_pc); PCSetType(smooth_pc, PCJACOBI); KSPSetTolerances(smooth_ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, 2); //set up the interpolation operator Mat prolongation; construct_prolongation_operator(ii+1+levels-mg_levels, &prolongation); PCMGSetInterpolation(pc, ii, prolongation); MatScale(prolongation, 1./2.); Mat restriction; MatTranspose(prolongation, &restriction); PCMGSetRestriction(pc, ii, prolongation); MatDestroy(prolongation); MatDestroy(restriction); } } } else { KSPGetPC(ksp, &pc); PCSetType(pc, PCJACOBI); } //*/ /* if (0) { KSPSetType(ksp, KSPRICHARDSON); KSPRichardsonSetScale(ksp, 2./3.); KSPGetPC(ksp, &pc); PCSetType(pc, PCJACOBI); } else { PetscOptionsInsertString("-ksp_type richardson"); PetscOptionsInsertString("-ksp_richardson_scale 0.666666666666666666"); PetscOptionsInsertString("-pc_type jacobi"); } //*/ KSPSetInitialGuessNonzero(ksp, PETSC_TRUE); KSPSetFromOptions(ksp); KSPSetUp(ksp); //VecView(problem.x, PETSC_VIEWER_STDOUT_WORLD); { //CHKERR(PCApply(pc, problem.b, problem.x)); CHKERR(KSPSolve(ksp, problem.b, problem.x)); KSPConvergedReason reason; CHKERR(KSPGetConvergedReason(ksp, &reason)); printf("KSPConvergedReason: %d\n", reason); PetscInt its; CHKERR(KSPGetIterationNumber(ksp, &its)); printf("Num iterations: %d\n", its); } //compute_residual_norm(&problem); VecView(problem.x, PETSC_VIEWER_STDOUT_WORLD); PetscFinalize(); return 0; }