static PetscErrorCode KSPSolve_SpecEst(KSP ksp) { PetscErrorCode ierr; KSP_SpecEst *spec = (KSP_SpecEst*)ksp->data; PetscFunctionBegin; if (spec->current) { ierr = KSPSolve(spec->kspcheap,ksp->vec_rhs,ksp->vec_sol);CHKERRQ(ierr); ierr = KSPSpecEstPropagateUp(ksp,spec->kspcheap);CHKERRQ(ierr); } else { PetscInt i,its,neig; PetscReal *real,*imag,rad = 0; ierr = KSPSolve(spec->kspest,ksp->vec_rhs,ksp->vec_sol);CHKERRQ(ierr); ierr = KSPSpecEstPropagateUp(ksp,spec->kspest);CHKERRQ(ierr); ierr = KSPComputeExtremeSingularValues(spec->kspest,&spec->max,&spec->min);CHKERRQ(ierr); ierr = KSPGetIterationNumber(spec->kspest,&its);CHKERRQ(ierr); ierr = PetscMalloc2(its,PetscReal,&real,its,PetscReal,&imag);CHKERRQ(ierr); ierr = KSPComputeEigenvalues(spec->kspest,its,real,imag,&neig);CHKERRQ(ierr); for (i=0; i<neig; i++) { /* We would really like to compute w (nominally 1/radius) to minimize |1-wB|. Empirically it is better to compute rad = |1-B| than rad = |B|. There must be a cheap way to do better. */ rad = PetscMax(rad,PetscRealPart(PetscSqrtScalar((PetscScalar)(PetscSqr(real[i]-1.) + PetscSqr(imag[i]))))); } ierr = PetscFree2(real,imag);CHKERRQ(ierr); spec->radius = rad; ierr = KSPChebyshevSetEigenvalues(spec->kspcheap,spec->max*spec->maxfactor,spec->min*spec->minfactor);CHKERRQ(ierr); ierr = KSPRichardsonSetScale(spec->kspcheap,spec->richfactor/spec->radius); ierr = PetscInfo3(ksp,"Estimated singular value min=%G max=%G, spectral radius=%G",spec->min,spec->max,spec->radius);CHKERRQ(ierr); spec->current = PETSC_TRUE; } PetscFunctionReturn(0); }
PetscErrorCode KSPSetFromOptions_Richardson(KSP ksp) { KSP_Richardson *rich = (KSP_Richardson*)ksp->data; PetscErrorCode ierr; PetscReal tmp; PetscBool flg,flg2; PetscFunctionBegin; ierr = PetscOptionsHead("KSP Richardson Options");CHKERRQ(ierr); ierr = PetscOptionsReal("-ksp_richardson_scale","damping factor","KSPRichardsonSetScale",rich->scale,&tmp,&flg);CHKERRQ(ierr); if (flg) { ierr = KSPRichardsonSetScale(ksp,tmp);CHKERRQ(ierr); } ierr = PetscOptionsBool("-ksp_richardson_self_scale","dynamically determine optimal damping factor","KSPRichardsonSetSelfScale",rich->selfscale,&flg2,&flg);CHKERRQ(ierr); if (flg) { ierr = KSPRichardsonSetSelfScale(ksp,flg2);CHKERRQ(ierr); } 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; }