PetscErrorCode EPSSolve_Arnoldi(EPS eps) { PetscErrorCode ierr; PetscInt k,nv,ld; Mat U; PetscScalar *H,*X; PetscReal beta,gamma=1.0; PetscBool breakdown,harmonic,refined; BVOrthogRefineType orthog_ref; EPS_ARNOLDI *arnoldi = (EPS_ARNOLDI*)eps->data; PetscFunctionBegin; ierr = DSGetLeadingDimension(eps->ds,&ld);CHKERRQ(ierr); ierr = DSGetRefined(eps->ds,&refined);CHKERRQ(ierr); harmonic = (eps->extraction==EPS_HARMONIC || eps->extraction==EPS_REFINED_HARMONIC)?PETSC_TRUE:PETSC_FALSE; ierr = BVGetOrthogonalization(eps->V,NULL,&orthog_ref,NULL);CHKERRQ(ierr); /* Get the starting Arnoldi vector */ ierr = EPSGetStartVector(eps,0,NULL);CHKERRQ(ierr); /* Restart loop */ while (eps->reason == EPS_CONVERGED_ITERATING) { eps->its++; /* Compute an nv-step Arnoldi factorization */ nv = PetscMin(eps->nconv+eps->mpd,eps->ncv); ierr = DSSetDimensions(eps->ds,nv,0,eps->nconv,0);CHKERRQ(ierr); ierr = DSGetArray(eps->ds,DS_MAT_A,&H);CHKERRQ(ierr); if (!arnoldi->delayed) { ierr = EPSBasicArnoldi(eps,PETSC_FALSE,H,ld,eps->nconv,&nv,&beta,&breakdown);CHKERRQ(ierr); } else SETERRQ(PetscObjectComm((PetscObject)eps),1,"Not implemented"); /*if (orthog_ref == BV_ORTHOG_REFINE_NEVER) { ierr = EPSDelayedArnoldi1(eps,H,ld,eps->V,eps->nconv,&nv,f,&beta,&breakdown);CHKERRQ(ierr); } else { ierr = EPSDelayedArnoldi(eps,H,ld,eps->V,eps->nconv,&nv,f,&beta,&breakdown);CHKERRQ(ierr); }*/ ierr = DSRestoreArray(eps->ds,DS_MAT_A,&H);CHKERRQ(ierr); ierr = DSSetState(eps->ds,DS_STATE_INTERMEDIATE);CHKERRQ(ierr); ierr = BVSetActiveColumns(eps->V,eps->nconv,nv);CHKERRQ(ierr); /* Compute translation of Krylov decomposition if harmonic extraction used */ if (harmonic) { ierr = DSTranslateHarmonic(eps->ds,eps->target,beta,PETSC_FALSE,NULL,&gamma);CHKERRQ(ierr); } /* Solve projected problem */ ierr = DSSolve(eps->ds,eps->eigr,eps->eigi);CHKERRQ(ierr); ierr = DSSort(eps->ds,eps->eigr,eps->eigi,NULL,NULL,NULL);CHKERRQ(ierr); ierr = DSUpdateExtraRow(eps->ds);CHKERRQ(ierr); /* Check convergence */ ierr = EPSKrylovConvergence(eps,PETSC_FALSE,eps->nconv,nv-eps->nconv,beta,gamma,&k);CHKERRQ(ierr); if (refined) { ierr = DSGetArray(eps->ds,DS_MAT_X,&X);CHKERRQ(ierr); ierr = BVMultColumn(eps->V,1.0,0.0,k,X+k*ld);CHKERRQ(ierr); ierr = DSRestoreArray(eps->ds,DS_MAT_X,&X);CHKERRQ(ierr); ierr = DSGetMat(eps->ds,DS_MAT_Q,&U);CHKERRQ(ierr); ierr = BVMultInPlace(eps->V,U,eps->nconv,nv);CHKERRQ(ierr); ierr = MatDestroy(&U);CHKERRQ(ierr); ierr = BVOrthogonalizeColumn(eps->V,k,NULL,NULL,NULL);CHKERRQ(ierr); } else { ierr = DSGetMat(eps->ds,DS_MAT_Q,&U);CHKERRQ(ierr); ierr = BVMultInPlace(eps->V,U,eps->nconv,nv);CHKERRQ(ierr); ierr = MatDestroy(&U);CHKERRQ(ierr); } eps->nconv = k; ierr = EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,nv);CHKERRQ(ierr); if (breakdown && k<eps->nev) { ierr = PetscInfo2(eps,"Breakdown in Arnoldi method (it=%D norm=%g)\n",eps->its,(double)beta);CHKERRQ(ierr); ierr = EPSGetStartVector(eps,k,&breakdown);CHKERRQ(ierr); if (breakdown) { eps->reason = EPS_DIVERGED_BREAKDOWN; ierr = PetscInfo(eps,"Unable to generate more start vectors\n");CHKERRQ(ierr); } } if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS; if (eps->nconv >= eps->nev) eps->reason = EPS_CONVERGED_TOL; } /* truncate Schur decomposition and change the state to raw so that PSVectors() computes eigenvectors from scratch */ ierr = DSSetDimensions(eps->ds,eps->nconv,0,0,0);CHKERRQ(ierr); ierr = DSSetState(eps->ds,DS_STATE_RAW);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode EPSSolve_KrylovSchur_Default(EPS eps) { PetscErrorCode ierr; EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data; PetscInt i,j,*pj,k,l,nv,ld; Mat U; PetscScalar *S,*Q,*g; PetscReal beta,gamma=1.0; PetscBool breakdown,harmonic; PetscFunctionBegin; ierr = DSGetLeadingDimension(eps->ds,&ld);CHKERRQ(ierr); harmonic = (eps->extraction==EPS_HARMONIC || eps->extraction==EPS_REFINED_HARMONIC)?PETSC_TRUE:PETSC_FALSE; if (harmonic) { ierr = PetscMalloc1(ld,&g);CHKERRQ(ierr); } if (eps->arbitrary) pj = &j; else pj = NULL; /* Get the starting Arnoldi vector */ ierr = EPSGetStartVector(eps,0,NULL);CHKERRQ(ierr); l = 0; /* Restart loop */ while (eps->reason == EPS_CONVERGED_ITERATING) { eps->its++; /* Compute an nv-step Arnoldi factorization */ nv = PetscMin(eps->nconv+eps->mpd,eps->ncv); ierr = DSGetArray(eps->ds,DS_MAT_A,&S);CHKERRQ(ierr); ierr = EPSBasicArnoldi(eps,PETSC_FALSE,S,ld,eps->nconv+l,&nv,&beta,&breakdown);CHKERRQ(ierr); ierr = DSRestoreArray(eps->ds,DS_MAT_A,&S);CHKERRQ(ierr); ierr = DSSetDimensions(eps->ds,nv,0,eps->nconv,eps->nconv+l);CHKERRQ(ierr); if (l==0) { ierr = DSSetState(eps->ds,DS_STATE_INTERMEDIATE);CHKERRQ(ierr); } else { ierr = DSSetState(eps->ds,DS_STATE_RAW);CHKERRQ(ierr); } ierr = BVSetActiveColumns(eps->V,eps->nconv,nv);CHKERRQ(ierr); /* Compute translation of Krylov decomposition if harmonic extraction used */ if (harmonic) { ierr = DSTranslateHarmonic(eps->ds,eps->target,beta,PETSC_FALSE,g,&gamma);CHKERRQ(ierr); } /* Solve projected problem */ ierr = DSSolve(eps->ds,eps->eigr,eps->eigi);CHKERRQ(ierr); if (eps->arbitrary) { ierr = EPSGetArbitraryValues(eps,eps->rr,eps->ri);CHKERRQ(ierr); j=1; } ierr = DSSort(eps->ds,eps->eigr,eps->eigi,eps->rr,eps->ri,pj);CHKERRQ(ierr); /* Check convergence */ ierr = EPSKrylovConvergence(eps,PETSC_FALSE,eps->nconv,nv-eps->nconv,beta,gamma,&k);CHKERRQ(ierr); if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS; if (k >= eps->nev) eps->reason = EPS_CONVERGED_TOL; /* Update l */ if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0; else { l = PetscMax(1,(PetscInt)((nv-k)*ctx->keep)); #if !defined(PETSC_USE_COMPLEX) ierr = DSGetArray(eps->ds,DS_MAT_A,&S);CHKERRQ(ierr); if (S[k+l+(k+l-1)*ld] != 0.0) { if (k+l<nv-1) l = l+1; else l = l-1; } ierr = DSRestoreArray(eps->ds,DS_MAT_A,&S);CHKERRQ(ierr); #endif } if (eps->reason == EPS_CONVERGED_ITERATING) { if (breakdown) { /* Start a new Arnoldi factorization */ ierr = PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%D norm=%g)\n",eps->its,(double)beta);CHKERRQ(ierr); if (k<eps->nev) { ierr = EPSGetStartVector(eps,k,&breakdown);CHKERRQ(ierr); if (breakdown) { eps->reason = EPS_DIVERGED_BREAKDOWN; ierr = PetscInfo(eps,"Unable to generate more start vectors\n");CHKERRQ(ierr); } } } else { /* Undo translation of Krylov decomposition */ if (harmonic) { ierr = DSSetDimensions(eps->ds,nv,0,k,l);CHKERRQ(ierr); ierr = DSTranslateHarmonic(eps->ds,0.0,beta,PETSC_TRUE,g,&gamma);CHKERRQ(ierr); /* gamma u^ = u - U*g~ */ ierr = BVMultColumn(eps->V,-1.0,1.0,nv,g);CHKERRQ(ierr); ierr = BVScaleColumn(eps->V,nv,1.0/gamma);CHKERRQ(ierr); } /* Prepare the Rayleigh quotient for restart */ ierr = DSGetArray(eps->ds,DS_MAT_A,&S);CHKERRQ(ierr); ierr = DSGetArray(eps->ds,DS_MAT_Q,&Q);CHKERRQ(ierr); for (i=k;i<k+l;i++) { S[k+l+i*ld] = Q[nv-1+i*ld]*beta*gamma; } ierr = DSRestoreArray(eps->ds,DS_MAT_A,&S);CHKERRQ(ierr); ierr = DSRestoreArray(eps->ds,DS_MAT_Q,&Q);CHKERRQ(ierr); } } /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */ ierr = DSGetMat(eps->ds,DS_MAT_Q,&U);CHKERRQ(ierr); ierr = BVMultInPlace(eps->V,U,eps->nconv,k+l);CHKERRQ(ierr); ierr = MatDestroy(&U);CHKERRQ(ierr); if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) { ierr = BVCopyColumn(eps->V,nv,k+l);CHKERRQ(ierr); } eps->nconv = k; ierr = EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,nv);CHKERRQ(ierr); } if (harmonic) { ierr = PetscFree(g);CHKERRQ(ierr); } /* truncate Schur decomposition and change the state to raw so that PSVectors() computes eigenvectors from scratch */ ierr = DSSetDimensions(eps->ds,eps->nconv,0,0,0);CHKERRQ(ierr); ierr = DSSetState(eps->ds,DS_STATE_RAW);CHKERRQ(ierr); PetscFunctionReturn(0); }