Actual source code: ks-indef.c
slepc-3.6.1 2015-09-03
1: /*
3: SLEPc eigensolver: "krylovschur"
5: Method: Krylov-Schur for symmetric-indefinite eigenproblems
7: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
8: SLEPc - Scalable Library for Eigenvalue Problem Computations
9: Copyright (c) 2002-2015, Universitat Politecnica de Valencia, Spain
11: This file is part of SLEPc.
13: SLEPc is free software: you can redistribute it and/or modify it under the
14: terms of version 3 of the GNU Lesser General Public License as published by
15: the Free Software Foundation.
17: SLEPc is distributed in the hope that it will be useful, but WITHOUT ANY
18: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19: FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
20: more details.
22: You should have received a copy of the GNU Lesser General Public License
23: along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
24: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
25: */
26: #include <slepc/private/epsimpl.h>
27: #include krylovschur.h
31: PetscErrorCode EPSSolve_KrylovSchur_Indefinite(EPS eps)
32: {
33: PetscErrorCode ierr;
34: EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
35: PetscInt i,k,l,ld,nv,t,nconv=0;
36: Mat U;
37: Vec vomega,w=eps->work[0];
38: PetscScalar *Q,*aux;
39: PetscReal *a,*b,*r,beta,beta1=1.0,*omega;
40: PetscBool breakdown=PETSC_FALSE,symmlost=PETSC_FALSE;
43: DSGetLeadingDimension(eps->ds,&ld);
45: /* Get the starting Lanczos vector */
46: EPSGetStartVector(eps,0,NULL);
48: /* Extract sigma[0] from BV, computed during normalization */
49: BVSetActiveColumns(eps->V,0,1);
50: VecCreateSeq(PETSC_COMM_SELF,1,&vomega);
51: BVGetSignature(eps->V,vomega);
52: VecGetArray(vomega,&aux);
53: DSGetArrayReal(eps->ds,DS_MAT_D,&omega);
54: omega[0] = PetscRealPart(aux[0]);
55: DSRestoreArrayReal(eps->ds,DS_MAT_D,&omega);
56: VecRestoreArray(vomega,&aux);
57: VecDestroy(&vomega);
58: l = 0;
60: /* Restart loop */
61: while (eps->reason == EPS_CONVERGED_ITERATING) {
62: eps->its++;
64: /* Compute an nv-step Lanczos factorization */
65: nv = PetscMin(eps->nconv+eps->mpd,eps->ncv);
66: DSGetArrayReal(eps->ds,DS_MAT_T,&a);
67: b = a + ld;
68: DSGetArrayReal(eps->ds,DS_MAT_D,&omega);
69: EPSPseudoLanczos(eps,a,b,omega,eps->nconv+l,&nv,&breakdown,&symmlost,NULL,w);
70: if (symmlost) {
71: eps->reason = EPS_DIVERGED_SYMMETRY_LOST;
72: if (nv==eps->nconv+l+1) { eps->nconv = nconv; break; }
73: }
74: beta = b[nv-1];
75: DSRestoreArrayReal(eps->ds,DS_MAT_T,&a);
76: DSRestoreArrayReal(eps->ds,DS_MAT_D,&omega);
77: DSSetDimensions(eps->ds,nv,0,eps->nconv,eps->nconv+l);
78: if (l==0) {
79: DSSetState(eps->ds,DS_STATE_INTERMEDIATE);
80: } else {
81: DSSetState(eps->ds,DS_STATE_RAW);
82: }
83: BVSetActiveColumns(eps->V,eps->nconv,nv);
85: /* Solve projected problem */
86: DSSolve(eps->ds,eps->eigr,eps->eigi);
87: DSSort(eps->ds,eps->eigr,eps->eigi,NULL,NULL,NULL);
89: /* Check convergence */
90: DSGetDimensions(eps->ds,NULL,NULL,NULL,NULL,&t);
91: #if 0
92: /* take into account also left residual */
93: BVGetColumn(eps->V,nv,&u);
94: VecNorm(u,NORM_2,&beta1);
95: BVRestoreColumn(eps->V,nv,&u);
96: VecNorm(w,NORM_2,&beta2); /* w contains B*V[nv] */
97: beta1 = PetscMax(beta1,beta2);
98: #endif
99: EPSKrylovConvergence(eps,PETSC_FALSE,eps->nconv,t-eps->nconv,beta*beta1,1.0,&k);
100: if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
101: if (k >= eps->nev) eps->reason = EPS_CONVERGED_TOL;
102: nconv = k;
104: /* Update l */
105: if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0;
106: else {
107: l = PetscMax(1,(PetscInt)((nv-k)*ctx->keep));
108: l = PetscMin(l,t);
109: DSGetArrayReal(eps->ds,DS_MAT_T,&a);
110: if (*(a+ld+k+l-1)!=0) {
111: if (k+l<t-1) l = l+1;
112: else l = l-1;
113: }
114: DSRestoreArrayReal(eps->ds,DS_MAT_T,&a);
115: }
116: if (!ctx->lock && l>0) { l += k; k = 0; } /* non-locking variant: reset no. of converged pairs */
118: if (eps->reason == EPS_CONVERGED_ITERATING) {
119: if (breakdown) {
120: SETERRQ1(PetscObjectComm((PetscObject)eps),PETSC_ERR_CONV_FAILED,"Breakdown in Indefinite Krylov-Schur (beta=%g)",beta);
121: } else {
122: /* Prepare the Rayleigh quotient for restart */
123: DSGetArray(eps->ds,DS_MAT_Q,&Q);
124: DSGetArrayReal(eps->ds,DS_MAT_T,&a);
125: DSGetArrayReal(eps->ds,DS_MAT_D,&omega);
126: b = a + ld;
127: r = a + 2*ld;
128: for (i=k;i<k+l;i++) {
129: r[i] = PetscRealPart(Q[nv-1+i*ld]*beta);
130: }
131: b[k+l-1] = r[k+l-1];
132: omega[k+l] = omega[nv];
133: DSRestoreArrayReal(eps->ds,DS_MAT_T,&a);
134: DSRestoreArray(eps->ds,DS_MAT_Q,&Q);
135: DSRestoreArrayReal(eps->ds,DS_MAT_D,&omega);
136: }
137: }
138: /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
139: DSGetMat(eps->ds,DS_MAT_Q,&U);
140: BVMultInPlace(eps->V,U,eps->nconv,k+l);
141: MatDestroy(&U);
143: /* Move restart vector and update signature */
144: if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
145: BVCopyColumn(eps->V,nv,k+l);
146: DSGetArrayReal(eps->ds,DS_MAT_D,&omega);
147: VecCreateSeq(PETSC_COMM_SELF,k+l,&vomega);
148: VecGetArray(vomega,&aux);
149: for (i=0;i<k+l;i++) aux[i] = omega[i];
150: VecRestoreArray(vomega,&aux);
151: BVSetActiveColumns(eps->V,0,k+l);
152: BVSetSignature(eps->V,vomega);
153: VecDestroy(&vomega);
154: DSRestoreArrayReal(eps->ds,DS_MAT_D,&omega);
155: }
157: eps->nconv = k;
158: EPSMonitor(eps,eps->its,nconv,eps->eigr,eps->eigi,eps->errest,nv);
159: }
160: DSSetDimensions(eps->ds,eps->nconv,0,0,0);
161: DSSetState(eps->ds,DS_STATE_RAW);
162: return(0);
163: }