| 6 |
dsic.upv.es!jroman |
1 |
|
|
|
2 |
/*
|
|
|
3 |
This implements the subspace iteration method for finding the
|
|
|
4 |
eigenpairs associtated to the eigenvalues with largest magnitude.
|
|
|
5 |
*/
|
|
|
6 |
#include "src/eps/epsimpl.h"
|
|
|
7 |
|
|
|
8 |
typedef struct {
|
|
|
9 |
int inner;
|
|
|
10 |
} EPS_SUBSPACE;
|
|
|
11 |
|
|
|
12 |
#undef __FUNCT__
|
|
|
13 |
#define __FUNCT__ "EPSSetUp_SUBSPACE"
|
|
|
14 |
static int EPSSetUp_SUBSPACE(EPS eps)
|
|
|
15 |
{
|
|
|
16 |
int ierr;
|
|
|
17 |
|
|
|
18 |
PetscFunctionBegin;
|
|
|
19 |
ierr = EPSDefaultGetWork(eps,1);CHKERRQ(ierr);
|
|
|
20 |
PetscFunctionReturn(0);
|
|
|
21 |
}
|
|
|
22 |
|
|
|
23 |
#undef __FUNCT__
|
|
|
24 |
#define __FUNCT__ "EPSSetDefaults_SUBSPACE"
|
|
|
25 |
static int EPSSetDefaults_SUBSPACE(EPS eps)
|
|
|
26 |
{
|
|
|
27 |
int ierr, N;
|
|
|
28 |
EPS_SUBSPACE *subspace = (EPS_SUBSPACE *)eps->data;
|
|
|
29 |
|
|
|
30 |
PetscFunctionBegin;
|
|
|
31 |
ierr = VecGetSize(eps->vec_initial,&N);CHKERRQ(ierr);
|
|
|
32 |
if (eps->ncv) {
|
|
|
33 |
if (eps->ncv<eps->nev) SETERRQ(1,"The value of ncv must be at least nev");
|
|
|
34 |
}
|
|
|
35 |
else eps->ncv = PetscMax(2*eps->nev,eps->nev+8);
|
|
|
36 |
if (!eps->max_it) eps->max_it = PetscMax(100,N);
|
|
|
37 |
if (!subspace->inner) {
|
|
|
38 |
if (eps->ishermitian) subspace->inner = 10;
|
|
|
39 |
else subspace->inner = 4;
|
|
|
40 |
}
|
|
|
41 |
if (!eps->tol) eps->tol = 1.e-7;
|
|
|
42 |
PetscFunctionReturn(0);
|
|
|
43 |
}
|
|
|
44 |
|
|
|
45 |
#undef __FUNCT__
|
|
|
46 |
#define __FUNCT__ "EPSSolve_SUBSPACE"
|
|
|
47 |
static int EPSSolve_SUBSPACE(EPS eps,int *its)
|
|
|
48 |
{
|
|
|
49 |
int ierr, i, j, k, maxit=eps->max_it, ncv = eps->ncv;
|
|
|
50 |
Vec w;
|
|
|
51 |
PetscReal relerr, tol=eps->tol;
|
|
|
52 |
PetscScalar alpha, *H, *S;
|
|
|
53 |
EPS_SUBSPACE *subspace = (EPS_SUBSPACE *)eps->data;
|
|
|
54 |
|
|
|
55 |
PetscFunctionBegin;
|
|
|
56 |
w = eps->work[0];
|
|
|
57 |
ierr = PetscMalloc(ncv*ncv*sizeof(PetscScalar),&H);CHKERRQ(ierr);
|
|
|
58 |
ierr = PetscMalloc(ncv*ncv*sizeof(PetscScalar),&S);CHKERRQ(ierr);
|
|
|
59 |
|
|
|
60 |
/* Build Z from initial vector */
|
|
|
61 |
ierr = VecCopy(eps->vec_initial,eps->V[0]);CHKERRQ(ierr);
|
|
|
62 |
for (k=1; k<ncv; k++) {
|
|
|
63 |
ierr = STApply(eps->OP,eps->V[k-1],eps->V[k]); CHKERRQ(ierr);
|
|
|
64 |
}
|
|
|
65 |
/* QR-Factorize V R = Z */
|
|
|
66 |
ierr = EPSQRDecomposition(eps,0,ncv,PETSC_NULL,ncv);CHKERRQ(ierr);
|
|
|
67 |
|
|
|
68 |
i = 0;
|
|
|
69 |
*its = 0;
|
|
|
70 |
|
|
|
71 |
while (*its<maxit) {
|
|
|
72 |
|
|
|
73 |
/* Y = OP^inner V */
|
|
|
74 |
for (k=i;k<ncv;k++) {
|
|
|
75 |
for (j=i;j<subspace->inner;j++) {
|
|
|
76 |
ierr = STApply(eps->OP,eps->V[k],w);CHKERRQ(ierr);
|
|
|
77 |
ierr = VecCopy(w,eps->V[k]);CHKERRQ(ierr);
|
|
|
78 |
}
|
|
|
79 |
}
|
|
|
80 |
|
|
|
81 |
/* QR-Factorize V R = Y */
|
|
|
82 |
ierr = EPSQRDecomposition(eps,i,ncv,PETSC_NULL,ncv);CHKERRQ(ierr);
|
|
|
83 |
|
|
|
84 |
/* compute the projected matrix, H = V^* A V */
|
|
|
85 |
for (j=i;j<ncv;j++) {
|
|
|
86 |
ierr = STApply(eps->OP,eps->V[j],w);CHKERRQ(ierr);
|
|
|
87 |
for (k=i;k<ncv;k++) {
|
|
|
88 |
ierr = VecDot(w,eps->V[k],H+(k-i)+(ncv-i)*(j-i));CHKERRQ(ierr);
|
|
|
89 |
}
|
|
|
90 |
}
|
|
|
91 |
|
|
|
92 |
/* solve the reduced problem, compute the
|
|
|
93 |
eigendecomposition H = S Theta S^* */
|
|
|
94 |
ierr = EPSDenseNHEP(ncv-i,H,eps->eigr+i,eps->eigi+i,S);CHKERRQ(ierr);
|
|
|
95 |
|
|
|
96 |
/* update V = V S */
|
|
|
97 |
ierr = EPSReverseProjection(eps,i,ncv-i,S);CHKERRQ(ierr);
|
|
|
98 |
|
|
|
99 |
/* check eigenvalue convergence */
|
|
|
100 |
for (j=i;j<ncv;j++) {
|
|
|
101 |
ierr = STApply(eps->OP,eps->V[j],w);CHKERRQ(ierr);
|
|
|
102 |
alpha = -eps->eigr[j];
|
|
|
103 |
ierr = VecAXPY(&alpha,eps->V[j],w);CHKERRQ(ierr);
|
|
|
104 |
ierr = VecNorm(w,NORM_2,&relerr);CHKERRQ(ierr);
|
|
|
105 |
eps->errest[j] = relerr;
|
|
|
106 |
}
|
|
|
107 |
|
|
|
108 |
/* lock converged Ritz pairs */
|
|
|
109 |
eps->nconv = i;
|
|
|
110 |
for (j=i;j<ncv;j++) {
|
|
|
111 |
if (eps->errest[j]<tol) {
|
|
|
112 |
if (j>eps->nconv) {
|
|
|
113 |
ierr = EPSSwapEigenpairs(eps,eps->nconv,j);CHKERRQ(ierr);
|
|
|
114 |
}
|
|
|
115 |
eps->nconv = eps->nconv + 1;
|
|
|
116 |
}
|
|
|
117 |
}
|
|
|
118 |
i = eps->nconv;
|
|
|
119 |
|
|
|
120 |
*its = *its + 1;
|
|
|
121 |
EPSMonitorEstimates(eps,*its,eps->nconv,eps->errest,ncv);
|
|
|
122 |
EPSMonitorValues(eps,*its,eps->nconv,eps->eigr,PETSC_NULL,ncv);
|
|
|
123 |
|
|
|
124 |
if (eps->nconv>=eps->nev) break;
|
|
|
125 |
|
|
|
126 |
}
|
|
|
127 |
|
|
|
128 |
ierr = PetscFree(H);CHKERRQ(ierr);
|
|
|
129 |
ierr = PetscFree(S);CHKERRQ(ierr);
|
|
|
130 |
|
|
|
131 |
if( *its==maxit ) *its = *its - 1;
|
|
|
132 |
eps->its = *its;
|
|
|
133 |
if( eps->nconv == eps->nev ) eps->reason = EPS_CONVERGED_TOL;
|
|
|
134 |
else eps->reason = EPS_DIVERGED_ITS;
|
|
|
135 |
#if defined(PETSC_USE_COMPLEX)
|
|
|
136 |
for (i=0;i<eps->nconv;i++) eps->eigi[i]=0.0;
|
|
|
137 |
#endif
|
|
|
138 |
|
|
|
139 |
PetscFunctionReturn(0);
|
|
|
140 |
}
|
|
|
141 |
|
|
|
142 |
#undef __FUNCT__
|
|
|
143 |
#define __FUNCT__ "EPSView_SUBSPACE"
|
|
|
144 |
static int EPSView_SUBSPACE(EPS eps,PetscViewer viewer)
|
|
|
145 |
{
|
|
|
146 |
EPS_SUBSPACE *subspace = (EPS_SUBSPACE *) eps->data;
|
|
|
147 |
int ierr;
|
|
|
148 |
PetscTruth isascii;
|
|
|
149 |
|
|
|
150 |
PetscFunctionBegin;
|
|
|
151 |
ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
|
|
|
152 |
if (!isascii) {
|
|
|
153 |
SETERRQ1(1,"Viewer type %s not supported for EPSSUBSPACE",((PetscObject)viewer)->type_name);
|
|
|
154 |
}
|
|
|
155 |
ierr = PetscViewerASCIIPrintf(viewer,"number of inner iterations: %d\n",subspace->inner);CHKERRQ(ierr);
|
|
|
156 |
PetscFunctionReturn(0);
|
|
|
157 |
}
|
|
|
158 |
|
|
|
159 |
#undef __FUNCT__
|
|
|
160 |
#define __FUNCT__ "EPSSetFromOptions_SUBSPACE"
|
|
|
161 |
static int EPSSetFromOptions_SUBSPACE(EPS eps)
|
|
|
162 |
{
|
|
|
163 |
EPS_SUBSPACE *subspace = (EPS_SUBSPACE *)eps->data;
|
|
|
164 |
int ierr,val;
|
|
|
165 |
PetscTruth flg;
|
|
|
166 |
|
|
|
167 |
PetscFunctionBegin;
|
|
|
168 |
ierr = PetscOptionsHead("SUBSPACE options");CHKERRQ(ierr);
|
|
|
169 |
val = subspace->inner;
|
|
|
170 |
ierr = PetscOptionsInt("-eps_subspace_inner","Number of inner iterations","EPSSubspaceSetInner",val,&val,&flg);CHKERRQ(ierr);
|
|
|
171 |
if (flg) {ierr = EPSSubspaceSetInner(eps,val);CHKERRQ(ierr);}
|
|
|
172 |
ierr = PetscOptionsTail();CHKERRQ(ierr);
|
|
|
173 |
PetscFunctionReturn(0);
|
|
|
174 |
}
|
|
|
175 |
|
|
|
176 |
EXTERN_C_BEGIN
|
|
|
177 |
#undef __FUNCT__
|
|
|
178 |
#define __FUNCT__ "EPSSubspaceSetInner_SUBSPACE"
|
|
|
179 |
int EPSSubspaceSetInner_SUBSPACE(EPS eps,int val)
|
|
|
180 |
{
|
|
|
181 |
EPS_SUBSPACE *subspace;
|
|
|
182 |
|
|
|
183 |
PetscFunctionBegin;
|
|
|
184 |
subspace = (EPS_SUBSPACE *) eps->data;
|
|
|
185 |
subspace->inner = val;
|
|
|
186 |
PetscFunctionReturn(0);
|
|
|
187 |
}
|
|
|
188 |
EXTERN_C_END
|
|
|
189 |
|
|
|
190 |
#undef __FUNCT__
|
|
|
191 |
#define __FUNCT__ "EPSSubspaceSetInner"
|
|
|
192 |
/*@
|
|
|
193 |
EPSSubspaceSetInner - Sets the number of inner iterations performed by
|
|
|
194 |
the Subspace Iteration method.
|
|
|
195 |
|
|
|
196 |
Collective on EPS
|
|
|
197 |
|
|
|
198 |
Input Parameters:
|
|
|
199 |
+ eps - the eigenproblem solver context
|
|
|
200 |
- val - number of iterations to perform
|
|
|
201 |
|
|
|
202 |
Options Database Key:
|
|
|
203 |
. -eps_subspace_inner - Sets the value of the inner iterations
|
|
|
204 |
|
|
|
205 |
Notes:
|
|
|
206 |
This value specifies how many matrix-vector products have to be carried
|
|
|
207 |
out in the Subspace Iteration method between the orthogonalization steps.
|
|
|
208 |
|
|
|
209 |
The default value is 10 for Hermitian problems and 4 for non-Hermitian ones.
|
|
|
210 |
|
|
|
211 |
Level: advanced
|
|
|
212 |
|
|
|
213 |
@*/
|
|
|
214 |
int EPSSubspaceSetInner(EPS eps,int val)
|
|
|
215 |
{
|
|
|
216 |
int ierr, (*f)(EPS,int);
|
|
|
217 |
|
|
|
218 |
PetscFunctionBegin;
|
| 25 |
dsic.upv.es!jroman |
219 |
PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
|
| 6 |
dsic.upv.es!jroman |
220 |
ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSSubspaceSetInner_C",(void (**)(void))&f);CHKERRQ(ierr);
|
|
|
221 |
if (f) {
|
|
|
222 |
ierr = (*f)(eps,val);CHKERRQ(ierr);
|
|
|
223 |
}
|
|
|
224 |
PetscFunctionReturn(0);
|
|
|
225 |
}
|
|
|
226 |
|
|
|
227 |
EXTERN_C_BEGIN
|
|
|
228 |
#undef __FUNCT__
|
|
|
229 |
#define __FUNCT__ "EPSCreate_SUBSPACE"
|
|
|
230 |
int EPSCreate_SUBSPACE(EPS eps)
|
|
|
231 |
{
|
|
|
232 |
EPS_SUBSPACE *subspace;
|
|
|
233 |
int ierr;
|
|
|
234 |
|
|
|
235 |
PetscFunctionBegin;
|
|
|
236 |
ierr = PetscNew(EPS_SUBSPACE,&subspace);CHKERRQ(ierr);
|
|
|
237 |
PetscMemzero(subspace,sizeof(EPS_SUBSPACE));
|
|
|
238 |
PetscLogObjectMemory(eps,sizeof(EPS_SUBSPACE));
|
|
|
239 |
eps->data = (void *) subspace;
|
|
|
240 |
eps->ops->setup = EPSSetUp_SUBSPACE;
|
|
|
241 |
eps->ops->setdefaults = EPSSetDefaults_SUBSPACE;
|
|
|
242 |
eps->ops->solve = EPSSolve_SUBSPACE;
|
|
|
243 |
eps->ops->destroy = EPSDefaultDestroy;
|
|
|
244 |
eps->ops->setfromoptions = EPSSetFromOptions_SUBSPACE;
|
|
|
245 |
eps->ops->view = EPSView_SUBSPACE;
|
|
|
246 |
|
|
|
247 |
subspace->inner = 0;
|
|
|
248 |
ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSSubspaceSetInner_C","EPSSubspaceSetInner_SUBSPACE",EPSSubspaceSetInner_SUBSPACE);CHKERRQ(ierr);
|
|
|
249 |
|
|
|
250 |
PetscFunctionReturn(0);
|
|
|
251 |
}
|
|
|
252 |
EXTERN_C_END
|
|
|
253 |
|