Actual source code: arnoldi.c
slepc-3.7.1 2016-05-27
1: /*
3: SLEPc eigensolver: "arnoldi"
5: Method: Explicitly Restarted Arnoldi
7: Algorithm:
9: Arnoldi method with explicit restart and deflation.
11: References:
13: [1] "Arnoldi Methods in SLEPc", SLEPc Technical Report STR-4,
14: available at http://slepc.upv.es.
16: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
17: SLEPc - Scalable Library for Eigenvalue Problem Computations
18: Copyright (c) 2002-2016, Universitat Politecnica de Valencia, Spain
20: This file is part of SLEPc.
22: SLEPc is free software: you can redistribute it and/or modify it under the
23: terms of version 3 of the GNU Lesser General Public License as published by
24: the Free Software Foundation.
26: SLEPc is distributed in the hope that it will be useful, but WITHOUT ANY
27: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
28: FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
29: more details.
31: You should have received a copy of the GNU Lesser General Public License
32: along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
33: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
34: */
36: #include <slepc/private/epsimpl.h> /*I "slepceps.h" I*/
38: PetscErrorCode EPSSolve_Arnoldi(EPS);
40: typedef struct {
41: PetscBool delayed;
42: } EPS_ARNOLDI;
46: PetscErrorCode EPSSetUp_Arnoldi(EPS eps)
47: {
51: EPSSetDimensions_Default(eps,eps->nev,&eps->ncv,&eps->mpd);
52: if (eps->ncv>eps->nev+eps->mpd) SETERRQ(PetscObjectComm((PetscObject)eps),1,"The value of ncv must not be larger than nev+mpd");
53: if (!eps->max_it) eps->max_it = PetscMax(100,2*eps->n/eps->ncv);
54: if (!eps->which) { EPSSetWhichEigenpairs_Default(eps); }
55: if (eps->ishermitian && eps->ispositive && (eps->which==EPS_LARGEST_IMAGINARY || eps->which==EPS_SMALLEST_IMAGINARY)) SETERRQ(PetscObjectComm((PetscObject)eps),1,"Wrong value of eps->which");
57: if (!eps->extraction) {
58: EPSSetExtraction(eps,EPS_RITZ);
59: }
60: if (eps->arbitrary) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Arbitrary selection of eigenpairs not supported in this solver");
62: EPSAllocateSolution(eps,1);
63: EPS_SetInnerProduct(eps);
64: DSSetType(eps->ds,DSNHEP);
65: if (eps->extraction==EPS_REFINED || eps->extraction==EPS_REFINED_HARMONIC) {
66: DSSetRefined(eps->ds,PETSC_TRUE);
67: }
68: DSSetExtraRow(eps->ds,PETSC_TRUE);
69: DSAllocate(eps->ds,eps->ncv+1);
71: /* dispatch solve method */
72: if (eps->isgeneralized && eps->ishermitian && !eps->ispositive) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Requested method does not work for indefinite problems");
73: eps->ops->solve = EPSSolve_Arnoldi;
74: return(0);
75: }
79: PetscErrorCode EPSSolve_Arnoldi(EPS eps)
80: {
81: PetscErrorCode ierr;
82: PetscInt k,nv,ld;
83: Mat U;
84: PetscScalar *H,*X;
85: PetscReal beta,gamma=1.0;
86: PetscBool breakdown,harmonic,refined;
87: BVOrthogRefineType orthog_ref;
88: EPS_ARNOLDI *arnoldi = (EPS_ARNOLDI*)eps->data;
91: DSGetLeadingDimension(eps->ds,&ld);
92: DSGetRefined(eps->ds,&refined);
93: harmonic = (eps->extraction==EPS_HARMONIC || eps->extraction==EPS_REFINED_HARMONIC)?PETSC_TRUE:PETSC_FALSE;
94: BVGetOrthogonalization(eps->V,NULL,&orthog_ref,NULL,NULL);
96: /* Get the starting Arnoldi vector */
97: EPSGetStartVector(eps,0,NULL);
99: /* Restart loop */
100: while (eps->reason == EPS_CONVERGED_ITERATING) {
101: eps->its++;
103: /* Compute an nv-step Arnoldi factorization */
104: nv = PetscMin(eps->nconv+eps->mpd,eps->ncv);
105: DSSetDimensions(eps->ds,nv,0,eps->nconv,0);
106: DSGetArray(eps->ds,DS_MAT_A,&H);
107: if (!arnoldi->delayed) {
108: EPSBasicArnoldi(eps,PETSC_FALSE,H,ld,eps->nconv,&nv,&beta,&breakdown);
109: } else if (orthog_ref == BV_ORTHOG_REFINE_NEVER) {
110: EPSDelayedArnoldi1(eps,H,ld,eps->nconv,&nv,&beta,&breakdown);
111: } else {
112: EPSDelayedArnoldi(eps,H,ld,eps->nconv,&nv,&beta,&breakdown);
113: }
114: DSRestoreArray(eps->ds,DS_MAT_A,&H);
115: DSSetState(eps->ds,DS_STATE_INTERMEDIATE);
116: BVSetActiveColumns(eps->V,eps->nconv,nv);
118: /* Compute translation of Krylov decomposition if harmonic extraction used */
119: if (harmonic) {
120: DSTranslateHarmonic(eps->ds,eps->target,beta,PETSC_FALSE,NULL,&gamma);
121: }
123: /* Solve projected problem */
124: DSSolve(eps->ds,eps->eigr,eps->eigi);
125: DSSort(eps->ds,eps->eigr,eps->eigi,NULL,NULL,NULL);
126: DSUpdateExtraRow(eps->ds);
128: /* Check convergence */
129: EPSKrylovConvergence(eps,PETSC_FALSE,eps->nconv,nv-eps->nconv,beta,gamma,&k);
130: if (refined) {
131: DSGetArray(eps->ds,DS_MAT_X,&X);
132: BVMultColumn(eps->V,1.0,0.0,k,X+k*ld);
133: DSRestoreArray(eps->ds,DS_MAT_X,&X);
134: DSGetMat(eps->ds,DS_MAT_Q,&U);
135: BVMultInPlace(eps->V,U,eps->nconv,nv);
136: MatDestroy(&U);
137: BVOrthogonalizeColumn(eps->V,k,NULL,NULL,NULL);
138: } else {
139: DSGetMat(eps->ds,DS_MAT_Q,&U);
140: BVMultInPlace(eps->V,U,eps->nconv,nv);
141: MatDestroy(&U);
142: }
143: (*eps->stopping)(eps,eps->its,eps->max_it,k,eps->nev,&eps->reason,eps->stoppingctx);
144: if (eps->reason == EPS_CONVERGED_ITERATING && breakdown) {
145: PetscInfo2(eps,"Breakdown in Arnoldi method (it=%D norm=%g)\n",eps->its,(double)beta);
146: EPSGetStartVector(eps,k,&breakdown);
147: if (breakdown) {
148: eps->reason = EPS_DIVERGED_BREAKDOWN;
149: PetscInfo(eps,"Unable to generate more start vectors\n");
150: }
151: }
152: eps->nconv = k;
153: EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,nv);
154: }
156: /* truncate Schur decomposition and change the state to raw so that
157: DSVectors() computes eigenvectors from scratch */
158: DSSetDimensions(eps->ds,eps->nconv,0,0,0);
159: DSSetState(eps->ds,DS_STATE_RAW);
160: return(0);
161: }
165: PetscErrorCode EPSSetFromOptions_Arnoldi(PetscOptionItems *PetscOptionsObject,EPS eps)
166: {
168: PetscBool set,val;
169: EPS_ARNOLDI *arnoldi = (EPS_ARNOLDI*)eps->data;
172: PetscOptionsHead(PetscOptionsObject,"EPS Arnoldi Options");
173: PetscOptionsBool("-eps_arnoldi_delayed","Arnoldi with delayed reorthogonalization","EPSArnoldiSetDelayed",arnoldi->delayed,&val,&set);
174: if (set) {
175: EPSArnoldiSetDelayed(eps,val);
176: }
177: PetscOptionsTail();
178: return(0);
179: }
183: static PetscErrorCode EPSArnoldiSetDelayed_Arnoldi(EPS eps,PetscBool delayed)
184: {
185: EPS_ARNOLDI *arnoldi = (EPS_ARNOLDI*)eps->data;
188: arnoldi->delayed = delayed;
189: return(0);
190: }
194: /*@
195: EPSArnoldiSetDelayed - Activates or deactivates delayed reorthogonalization
196: in the Arnoldi iteration.
198: Logically Collective on EPS
200: Input Parameters:
201: + eps - the eigenproblem solver context
202: - delayed - boolean flag
204: Options Database Key:
205: . -eps_arnoldi_delayed - Activates delayed reorthogonalization in Arnoldi
207: Note:
208: Delayed reorthogonalization is an aggressive optimization for the Arnoldi
209: eigensolver than may provide better scalability, but sometimes makes the
210: solver converge less than the default algorithm.
212: Level: advanced
214: .seealso: EPSArnoldiGetDelayed()
215: @*/
216: PetscErrorCode EPSArnoldiSetDelayed(EPS eps,PetscBool delayed)
217: {
223: PetscTryMethod(eps,"EPSArnoldiSetDelayed_C",(EPS,PetscBool),(eps,delayed));
224: return(0);
225: }
229: static PetscErrorCode EPSArnoldiGetDelayed_Arnoldi(EPS eps,PetscBool *delayed)
230: {
231: EPS_ARNOLDI *arnoldi = (EPS_ARNOLDI*)eps->data;
234: *delayed = arnoldi->delayed;
235: return(0);
236: }
240: /*@
241: EPSArnoldiGetDelayed - Gets the type of reorthogonalization used during the Arnoldi
242: iteration.
244: Not Collective
246: Input Parameter:
247: . eps - the eigenproblem solver context
249: Input Parameter:
250: . delayed - boolean flag indicating if delayed reorthogonalization has been enabled
252: Level: advanced
254: .seealso: EPSArnoldiSetDelayed()
255: @*/
256: PetscErrorCode EPSArnoldiGetDelayed(EPS eps,PetscBool *delayed)
257: {
263: PetscUseMethod(eps,"EPSArnoldiGetDelayed_C",(EPS,PetscBool*),(eps,delayed));
264: return(0);
265: }
269: PetscErrorCode EPSDestroy_Arnoldi(EPS eps)
270: {
274: PetscFree(eps->data);
275: PetscObjectComposeFunction((PetscObject)eps,"EPSArnoldiSetDelayed_C",NULL);
276: PetscObjectComposeFunction((PetscObject)eps,"EPSArnoldiGetDelayed_C",NULL);
277: return(0);
278: }
282: PetscErrorCode EPSView_Arnoldi(EPS eps,PetscViewer viewer)
283: {
285: PetscBool isascii;
286: EPS_ARNOLDI *arnoldi = (EPS_ARNOLDI*)eps->data;
289: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
290: if (isascii) {
291: if (arnoldi->delayed) {
292: PetscViewerASCIIPrintf(viewer," Arnoldi: using delayed reorthogonalization\n");
293: }
294: }
295: return(0);
296: }
300: PETSC_EXTERN PetscErrorCode EPSCreate_Arnoldi(EPS eps)
301: {
302: EPS_ARNOLDI *ctx;
306: PetscNewLog(eps,&ctx);
307: eps->data = (void*)ctx;
309: eps->ops->setup = EPSSetUp_Arnoldi;
310: eps->ops->setfromoptions = EPSSetFromOptions_Arnoldi;
311: eps->ops->destroy = EPSDestroy_Arnoldi;
312: eps->ops->view = EPSView_Arnoldi;
313: eps->ops->backtransform = EPSBackTransform_Default;
314: eps->ops->computevectors = EPSComputeVectors_Schur;
315: PetscObjectComposeFunction((PetscObject)eps,"EPSArnoldiSetDelayed_C",EPSArnoldiSetDelayed_Arnoldi);
316: PetscObjectComposeFunction((PetscObject)eps,"EPSArnoldiGetDelayed_C",EPSArnoldiGetDelayed_Arnoldi);
317: return(0);
318: }