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); }
static PetscErrorCode KSPSetFromOptions_Chebyshev(PetscOptions *PetscOptionsObject,KSP ksp) { KSP_Chebyshev *cheb = (KSP_Chebyshev*)ksp->data; PetscErrorCode ierr; PetscInt neigarg = 2, nestarg = 4; PetscReal eminmax[2] = {0., 0.}; PetscReal tform[4] = {PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE}; PetscBool flgeig, flgest; PetscFunctionBegin; ierr = PetscOptionsHead(PetscOptionsObject,"KSP Chebyshev Options");CHKERRQ(ierr); ierr = PetscOptionsInt("-ksp_chebyshev_esteig_steps","Number of est steps in Chebyshev","",cheb->eststeps,&cheb->eststeps,NULL);CHKERRQ(ierr); ierr = PetscOptionsRealArray("-ksp_chebyshev_eigenvalues","extreme eigenvalues","KSPChebyshevSetEigenvalues",eminmax,&neigarg,&flgeig);CHKERRQ(ierr); if (flgeig) { if (neigarg != 2) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_INCOMP,"-ksp_chebyshev_eigenvalues: must specify 2 parameters, min and max eigenvalues"); ierr = KSPChebyshevSetEigenvalues(ksp, eminmax[1], eminmax[0]);CHKERRQ(ierr); } ierr = PetscOptionsRealArray("-ksp_chebyshev_esteig","estimate eigenvalues using a Krylov method, then use this transform for Chebyshev eigenvalue bounds","KSPChebyshevEstEigSet",tform,&nestarg,&flgest);CHKERRQ(ierr); if (flgest) { switch (nestarg) { case 0: ierr = KSPChebyshevEstEigSet(ksp,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); break; case 2: /* Base everything on the max eigenvalues */ ierr = KSPChebyshevEstEigSet(ksp,PETSC_DECIDE,tform[0],PETSC_DECIDE,tform[1]);CHKERRQ(ierr); break; case 4: /* Use the full 2x2 linear transformation */ ierr = KSPChebyshevEstEigSet(ksp,tform[0],tform[1],tform[2],tform[3]);CHKERRQ(ierr); break; default: SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_ARG_INCOMP,"Must specify either 0, 2, or 4 parameters for eigenvalue estimation"); } } /* We need to estimate eigenvalues; need to set this here so that KSPSetFromOptions() is called on the estimator */ if ((cheb->emin == 0. || cheb->emax == 0.) && !cheb->kspest) { ierr = KSPChebyshevEstEigSet(ksp,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); } if (cheb->kspest) { ierr = PetscOptionsBool("-ksp_chebyshev_esteig_random","Use random right hand side for estimate","KSPChebyshevEstEigSetUseRandom",cheb->userandom,&cheb->userandom,NULL);CHKERRQ(ierr); if (cheb->userandom) { const char *ksppre; if (!cheb->random) { ierr = PetscRandomCreate(PetscObjectComm((PetscObject)ksp),&cheb->random);CHKERRQ(ierr); } ierr = KSPGetOptionsPrefix(cheb->kspest, &ksppre);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject)cheb->random,ksppre);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(cheb->random);CHKERRQ(ierr); } ierr = KSPSetFromOptions(cheb->kspest);CHKERRQ(ierr); } ierr = PetscOptionsTail();CHKERRQ(ierr); PetscFunctionReturn(0); }
void PETSC_STDCALL kspchebyshevseteigenvalues_(KSP ksp,PetscReal *emax,PetscReal *emin, int *__ierr ){ *__ierr = KSPChebyshevSetEigenvalues( (KSP)PetscToPointer((ksp) ),*emax,*emin); }