| 1878 |
antodo |
1 |
/*
|
|
|
2 |
|
|
|
3 |
SLEPc eigensolver: "dsitrlanczos"
|
|
|
4 |
|
|
|
5 |
Method: Thick restart Lanczos with full reorthogonalization and dynamic shift and invert
|
|
|
6 |
|
|
|
7 |
Last update: Jan 2010
|
|
|
8 |
|
|
|
9 |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
10 |
SLEPc - Scalable Library for Eigenvalue Problem Computations
|
| 2116 |
eromero |
11 |
Copyright (c) 2002-2010, Universidad Politecnica de Valencia, Spain
|
| 1878 |
antodo |
12 |
|
|
|
13 |
This file is part of SLEPc.
|
|
|
14 |
|
|
|
15 |
SLEPc is free software: you can redistribute it and/or modify it under the
|
|
|
16 |
terms of version 3 of the GNU Lesser General Public License as published by
|
|
|
17 |
the Free Software Foundation.
|
|
|
18 |
|
|
|
19 |
SLEPc is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
20 |
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
21 |
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
|
|
22 |
more details.
|
|
|
23 |
|
|
|
24 |
You should have received a copy of the GNU Lesser General Public License
|
|
|
25 |
along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
|
|
|
26 |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
27 |
*/
|
|
|
28 |
|
|
|
29 |
#include "private/epsimpl.h" /*I "slepceps.h" I*/
|
|
|
30 |
#include "slepcblaslapack.h"
|
|
|
31 |
|
| 1947 |
jroman |
32 |
PetscErrorCode EPSSolve_DSITRLANCZOS(EPS);
|
|
|
33 |
|
| 1878 |
antodo |
34 |
extern PetscErrorCode EPSProjectedKSSym(EPS eps,PetscInt n,PetscInt l,PetscReal *a,PetscReal *b,PetscScalar *eig,PetscScalar *Q,PetscReal *work,PetscInt *perm);
|
|
|
35 |
|
|
|
36 |
#undef __FUNCT__
|
|
|
37 |
#define __FUNCT__ "EPSSetUp_DSITRLANCZOS"
|
|
|
38 |
PetscErrorCode EPSSetUp_DSITRLANCZOS(EPS eps)
|
|
|
39 |
{
|
|
|
40 |
PetscErrorCode ierr;
|
|
|
41 |
PetscTruth isSinv;
|
|
|
42 |
|
|
|
43 |
PetscFunctionBegin;
|
|
|
44 |
if (eps->ncv) { /* ncv set */
|
|
|
45 |
if (eps->ncv<eps->nev) SETERRQ(1,"The value of ncv must be at least nev");
|
|
|
46 |
}
|
|
|
47 |
else if (eps->mpd) { /* mpd set */
|
| 1928 |
jroman |
48 |
eps->ncv = PetscMin(eps->n,eps->nev+eps->mpd);
|
| 1878 |
antodo |
49 |
}
|
|
|
50 |
else { /* neither set: defaults depend on nev being small or large */
|
| 1928 |
jroman |
51 |
if (eps->nev<500) eps->ncv = PetscMin(eps->n,PetscMax(2*eps->nev,eps->nev+15));
|
|
|
52 |
else { eps->mpd = 500; eps->ncv = PetscMin(eps->n,eps->nev+eps->mpd); }
|
| 1878 |
antodo |
53 |
}
|
|
|
54 |
if (!eps->mpd) eps->mpd = eps->ncv;
|
|
|
55 |
if (eps->ncv>eps->nev+eps->mpd) SETERRQ(1,"The value of ncv must not be larger than nev+mpd");
|
| 1928 |
jroman |
56 |
if (!eps->max_it) eps->max_it = PetscMax(100,2*eps->n/eps->ncv);
|
| 1878 |
antodo |
57 |
|
|
|
58 |
if (!eps->ishermitian)
|
|
|
59 |
SETERRQ(PETSC_ERR_SUP,"Requested method is only available for Hermitian problems");
|
| 1942 |
jroman |
60 |
if (!eps->which) eps->which = EPS_LARGEST_MAGNITUDE;
|
| 1878 |
antodo |
61 |
if (eps->which==EPS_LARGEST_IMAGINARY || eps->which==EPS_SMALLEST_IMAGINARY)
|
|
|
62 |
SETERRQ(1,"Wrong value of eps->which");
|
|
|
63 |
|
|
|
64 |
if (!eps->extraction) {
|
|
|
65 |
ierr = EPSSetExtraction(eps,EPS_RITZ);CHKERRQ(ierr);
|
|
|
66 |
} if (eps->extraction != EPS_RITZ) {
|
|
|
67 |
SETERRQ(PETSC_ERR_SUP,"Unsupported extraction type");
|
|
|
68 |
}
|
|
|
69 |
|
| 2092 |
jroman |
70 |
ierr = PetscTypeCompare((PetscObject)eps->OP,STSINVERT,&isSinv);CHKERRQ(ierr);
|
| 1878 |
antodo |
71 |
if (!isSinv) {
|
|
|
72 |
SETERRQ(PETSC_ERR_SUP,"Shift-and-invert ST is needed");
|
|
|
73 |
}
|
|
|
74 |
|
|
|
75 |
ierr = EPSAllocateSolution(eps);CHKERRQ(ierr);
|
|
|
76 |
ierr = EPSDefaultGetWork(eps,1);CHKERRQ(ierr);
|
| 1947 |
jroman |
77 |
|
|
|
78 |
/* dispatch solve method */
|
|
|
79 |
if (eps->leftvecs) SETERRQ(PETSC_ERR_SUP,"Left vectors not supported in this solver");
|
|
|
80 |
eps->ops->solve = EPSSolve_DSITRLANCZOS;
|
| 1878 |
antodo |
81 |
PetscFunctionReturn(0);
|
|
|
82 |
}
|
|
|
83 |
|
|
|
84 |
#undef __FUNCT__
|
|
|
85 |
#define __FUNCT__ "EPSSolve_DSITRLANCZOS"
|
|
|
86 |
PetscErrorCode EPSSolve_DSITRLANCZOS(EPS eps)
|
|
|
87 |
{
|
|
|
88 |
PetscErrorCode ierr;
|
|
|
89 |
PetscInt i,k,l,lds,lt,nv,m;
|
|
|
90 |
Vec u=eps->work[0];
|
|
|
91 |
PetscScalar *Q, sigma, lambda, zero = 0.0;
|
|
|
92 |
PetscReal *a,*b,*work,beta,distance = 1e-3;
|
|
|
93 |
PetscInt *iwork;
|
|
|
94 |
PetscTruth breakdown;
|
|
|
95 |
|
|
|
96 |
PetscFunctionBegin;
|
|
|
97 |
ierr = PetscOptionsGetReal(PETSC_NULL,"-eps_distance",&distance,PETSC_NULL);CHKERRQ(ierr);
|
|
|
98 |
lds = PetscMin(eps->mpd,eps->ncv);
|
|
|
99 |
ierr = PetscMalloc(lds*lds*sizeof(PetscReal),&work);CHKERRQ(ierr);
|
| 2062 |
jroman |
100 |
ierr = PetscMalloc(lds*lds*sizeof(PetscScalar),&Q);CHKERRQ(ierr);
|
| 1878 |
antodo |
101 |
ierr = PetscMalloc(2*lds*sizeof(PetscInt),&iwork);CHKERRQ(ierr);
|
|
|
102 |
lt = PetscMin(eps->nev+eps->mpd,eps->ncv);
|
|
|
103 |
ierr = PetscMalloc(lt*sizeof(PetscReal),&a);CHKERRQ(ierr);
|
|
|
104 |
ierr = PetscMalloc(lt*sizeof(PetscReal),&b);CHKERRQ(ierr);
|
|
|
105 |
|
|
|
106 |
/* Get the starting Lanczos vector */
|
|
|
107 |
ierr = EPSGetStartVector(eps,0,eps->V[0],PETSC_NULL);CHKERRQ(ierr);
|
|
|
108 |
l = 0;
|
|
|
109 |
|
|
|
110 |
/* Restart loop */
|
|
|
111 |
while (eps->reason == EPS_CONVERGED_ITERATING) {
|
|
|
112 |
eps->its++;
|
|
|
113 |
|
|
|
114 |
/* Compute an nv-step Lanczos factorization */
|
|
|
115 |
m = PetscMin(eps->nconv+eps->mpd,eps->ncv);
|
|
|
116 |
ierr = EPSFullLanczos(eps,a+l,b+l,eps->V,eps->nconv+l,&m,u,&breakdown);CHKERRQ(ierr);
|
|
|
117 |
nv = m - eps->nconv;
|
|
|
118 |
beta = b[nv-1];
|
|
|
119 |
|
|
|
120 |
/* Solve projected problem and compute residual norm estimates */
|
|
|
121 |
ierr = EPSProjectedKSSym(eps,nv,l,a,b,eps->eigr+eps->nconv,Q,work,iwork);CHKERRQ(ierr);
|
|
|
122 |
|
|
|
123 |
/* Check convergence */
|
| 2062 |
jroman |
124 |
ierr = EPSKrylovConvergence(eps,PETSC_TRUE,eps->nconv,nv,PETSC_NULL,nv,Q,eps->V+eps->nconv,nv,beta,1.0,&k,PETSC_NULL);CHKERRQ(ierr);
|
| 1878 |
antodo |
125 |
if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
|
|
|
126 |
if (k >= eps->nev) eps->reason = EPS_CONVERGED_TOL;
|
|
|
127 |
|
|
|
128 |
/* Transform converged eigenvalues to the original problem */
|
|
|
129 |
ierr = STBackTransform(eps->OP,k-eps->nconv,eps->eigr+eps->nconv,eps->eigi+eps->nconv);CHKERRQ(ierr);
|
|
|
130 |
|
|
|
131 |
/* Update l */
|
|
|
132 |
if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0;
|
|
|
133 |
else {
|
|
|
134 |
l = (eps->nconv+nv-k)/2;
|
|
|
135 |
/* Update shift */
|
|
|
136 |
ierr = STGetShift(eps->OP,&sigma);CHKERRQ(ierr);
|
|
|
137 |
lambda = eps->eigr[k+1];
|
|
|
138 |
ierr = STBackTransform(eps->OP,1,&lambda,&zero);CHKERRQ(ierr);
|
|
|
139 |
if (PetscAbsScalar(lambda - sigma)/PetscAbsScalar(sigma) > distance) {
|
|
|
140 |
ierr = PetscInfo2(eps,"Shift update its=%i sigma=%g\n",eps->its,lambda);
|
|
|
141 |
PetscPushErrorHandler(PetscReturnErrorHandler,PETSC_NULL);
|
|
|
142 |
ierr = STSetShift(eps->OP,lambda);
|
|
|
143 |
PetscPopErrorHandler();
|
|
|
144 |
switch (ierr) {
|
|
|
145 |
case PETSC_ERR_MAT_LU_ZRPVT:
|
|
|
146 |
case PETSC_ERR_MAT_CH_ZRPVT:
|
|
|
147 |
ierr = PetscInfo2(eps,"Factorization error in shift update its=%i sigma=%g\n",eps->its,lambda);
|
|
|
148 |
ierr = STSetShift(eps->OP,sigma);CHKERRQ(ierr);
|
|
|
149 |
break;
|
|
|
150 |
default:
|
|
|
151 |
CHKERRQ(ierr);
|
|
|
152 |
l = 0; /* do not use restart vectors */
|
|
|
153 |
}
|
|
|
154 |
}
|
|
|
155 |
}
|
|
|
156 |
|
|
|
157 |
if (eps->reason == EPS_CONVERGED_ITERATING) {
|
|
|
158 |
if (breakdown) {
|
|
|
159 |
/* Start a new Lanczos factorization */
|
|
|
160 |
PetscInfo2(eps,"Breakdown in TR Lanczos method (it=%i norm=%g)\n",eps->its,beta);
|
|
|
161 |
ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
|
|
|
162 |
if (breakdown) {
|
|
|
163 |
eps->reason = EPS_DIVERGED_BREAKDOWN;
|
|
|
164 |
PetscInfo(eps,"Unable to generate more start vectors\n");
|
|
|
165 |
}
|
|
|
166 |
} else {
|
|
|
167 |
/* Prepare the Rayleigh quotient for restart */
|
|
|
168 |
for (i=0;i<l;i++) {
|
|
|
169 |
a[i] = PetscRealPart(eps->eigr[i+k]);
|
|
|
170 |
b[i] = PetscRealPart(Q[nv-1+(i+k-eps->nconv)*nv]*beta);
|
|
|
171 |
}
|
|
|
172 |
}
|
|
|
173 |
}
|
|
|
174 |
/* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
|
|
|
175 |
ierr = SlepcUpdateVectors(nv,eps->V+eps->nconv,0,k+l-eps->nconv,Q,nv,PETSC_FALSE);CHKERRQ(ierr);
|
|
|
176 |
/* Normalize u and append it to V */
|
|
|
177 |
if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
|
|
|
178 |
ierr = VecAXPBY(eps->V[k+l],1.0/beta,0.0,u);CHKERRQ(ierr);
|
|
|
179 |
}
|
|
|
180 |
|
|
|
181 |
EPSMonitor(eps,eps->its,k,eps->eigr,eps->eigi,eps->errest,nv+eps->nconv);
|
|
|
182 |
eps->nconv = k;
|
|
|
183 |
|
|
|
184 |
}
|
|
|
185 |
|
| 2062 |
jroman |
186 |
ierr = PetscFree(Q);CHKERRQ(ierr);
|
| 1878 |
antodo |
187 |
ierr = PetscFree(a);CHKERRQ(ierr);
|
|
|
188 |
ierr = PetscFree(b);CHKERRQ(ierr);
|
|
|
189 |
ierr = PetscFree(work);CHKERRQ(ierr);
|
|
|
190 |
ierr = PetscFree(iwork);CHKERRQ(ierr);
|
|
|
191 |
PetscFunctionReturn(0);
|
|
|
192 |
}
|
|
|
193 |
|
|
|
194 |
EXTERN_C_BEGIN
|
|
|
195 |
#undef __FUNCT__
|
|
|
196 |
#define __FUNCT__ "EPSCreate_DSITRLANCZOS"
|
|
|
197 |
PetscErrorCode EPSCreate_DSITRLANCZOS(EPS eps)
|
|
|
198 |
{
|
|
|
199 |
PetscFunctionBegin;
|
|
|
200 |
eps->data = PETSC_NULL;
|
|
|
201 |
eps->ops->setup = EPSSetUp_DSITRLANCZOS;
|
|
|
202 |
eps->ops->setfromoptions = PETSC_NULL;
|
|
|
203 |
eps->ops->destroy = EPSDestroy_Default;
|
|
|
204 |
eps->ops->view = PETSC_NULL;
|
|
|
205 |
eps->ops->computevectors = EPSComputeVectors_Default;
|
|
|
206 |
PetscFunctionReturn(0);
|
|
|
207 |
}
|
|
|
208 |
EXTERN_C_END
|
|
|
209 |
|