Subversion Repositories slepc-dev

Rev

Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2404 jroman 1
/*                      
2
 
3
   SLEPc eigensolver: "krylovschur"
4
 
5
   Method: Krylov-Schur with spectrum slicing for symmetric eigenproblems
6
 
7
   References:
8
 
9
       [1] R.G. Grimes et al., "A shifted block Lanczos algorithm for solving
10
           sparse symmetric generalized eigenproblems", SIAM J. Matrix Analysis
11
           and App., 15(1), pp. 228–272, 1994.
12
 
13
       [2] G.W. Stewart, "A Krylov-Schur Algorithm for Large Eigenproblems",
14
           SIAM J. Matrix Analysis and App., 23(3), pp. 601-614, 2001.
15
 
16
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
17
   SLEPc - Scalable Library for Eigenvalue Problem Computations
2575 eromero 18
   Copyright (c) 2002-2011, Universitat Politecnica de Valencia, Spain
2404 jroman 19
 
20
   This file is part of SLEPc.
2459 carcamgo 21
 
2404 jroman 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.
25
 
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.
30
 
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
*/
35
 
36
#include <private/epsimpl.h>                /*I "slepceps.h" I*/
37
#include <slepcblaslapack.h>
38
 
39
extern PetscErrorCode EPSProjectedKSSym(EPS,PetscInt,PetscInt,PetscReal*,PetscReal*,PetscScalar*,PetscScalar*,PetscReal*,PetscInt*);
40
 
2459 carcamgo 41
/* Type of data characterizing a shift (place from where an eps is applied) */
2708 carcamgo 42
typedef struct _n_shift *shift;
2459 carcamgo 43
struct _n_shift{
2708 carcamgo 44
  PetscReal     value;
45
  PetscInt      inertia;
46
  PetscBool     comp[2]; /* Shows completion of subintervals (left and right) */
47
  shift         neighb[2];/* Adjacent shifts */
48
  PetscInt      index;/* Index in eig where found values are stored */
49
  PetscInt      neigs; /* Number of values found */
50
  PetscReal     ext[2];   /* Limits for accepted values */
51
  PetscInt      nsch[2];  /* Number of missing values for each subinterval */
52
  PetscInt      nconv[2]; /* Converged on each side (accepted or not)*/
53
  PetscBool     expf;
2459 carcamgo 54
};
55
 
56
/* Type of data  for storing the state of spectrum slicing*/
2464 carcamgo 57
struct _n_SR{
2596 carcamgo 58
  PetscReal       int0,int1; /* Extremes of the interval */
59
  PetscInt        dir; /* Determines the order of values in eig (+1 incr, -1 decr) */
60
  PetscBool       hasEnd; /* Tells whether the interval has an end */
2459 carcamgo 61
  PetscInt        inertia0,inertia1;
62
  Vec             *V;
2629 carcamgo 63
  PetscScalar     *eig,*eigi,*monit,*back;
2596 carcamgo 64
  PetscReal       *errest;
65
  PetscInt        *perm;/* Permutation for keeping the eigenvalues in order */
66
  PetscInt        numEigs; /* Number of eigenvalues in the interval */
2459 carcamgo 67
  PetscInt        indexEig;
2596 carcamgo 68
  shift           sPres; /* Present shift */
69
  shift           *pending;/* Pending shifts array */
70
  PetscInt        nPend;/* Number of pending shifts */
71
  PetscInt        maxPend;/* Size of "pending" array */
72
  Vec             *VDef; /* Vector for deflation */
73
  PetscInt        *idxDef;/* For deflation */
2459 carcamgo 74
  PetscInt        nMAXCompl;
75
  PetscInt        iterCompl;
2596 carcamgo 76
  PetscInt        itsKs; /* Krylovschur restarts */
77
  PetscInt        nleap;
78
  shift           s0;/* Initial shift */
2708 carcamgo 79
  PetscScalar     *S;/* Matrix for projected problem */
80
  PetscInt        nS;
81
  PetscReal       beta;
82
  shift           sPrev;
2459 carcamgo 83
};
2464 carcamgo 84
typedef struct _n_SR  *SR;
85
 
86
/*
87
   Fills the fields of a shift structure
88
 
89
*/
2459 carcamgo 90
#undef __FUNCT__
91
#define __FUNCT__ "EPSCreateShift"
2470 jroman 92
static PetscErrorCode EPSCreateShift(EPS eps,PetscReal val, shift neighb0,shift neighb1)
2404 jroman 93
{
2459 carcamgo 94
  PetscErrorCode   ierr;
95
  shift            s,*pending2;
96
  PetscInt         i;
97
  SR               sr;
98
 
99
  PetscFunctionBegin;
100
  sr = (SR)(eps->data);
101
  ierr = PetscMalloc(sizeof(struct _n_shift),&s);CHKERRQ(ierr);
102
  s->value = val;
103
  s->neighb[0] = neighb0;
2464 carcamgo 104
  if(neighb0) neighb0->neighb[1] = s;
2459 carcamgo 105
  s->neighb[1] = neighb1;
2464 carcamgo 106
  if(neighb1) neighb1->neighb[0] = s;
2468 eromero 107
  s->comp[0] = PETSC_FALSE;
108
  s->comp[1] = PETSC_FALSE;
2459 carcamgo 109
  s->index = -1;
110
  s->neigs = 0;
2596 carcamgo 111
  s->nconv[0] = s->nconv[1] = 0;
2459 carcamgo 112
  s->nsch[0] = s->nsch[1]=0;
2596 carcamgo 113
  /* Inserts in the stack of pending shifts */
114
  /* If needed, the array is resized */
2459 carcamgo 115
  if(sr->nPend >= sr->maxPend){
116
    sr->maxPend *= 2;
117
    ierr = PetscMalloc((sr->maxPend)*sizeof(shift),&pending2);CHKERRQ(ierr);
118
    for(i=0;i < sr->nPend; i++)pending2[i] = sr->pending[i];
119
    ierr = PetscFree(sr->pending);CHKERRQ(ierr);
120
    sr->pending = pending2;
121
  }
122
  sr->pending[sr->nPend++]=s;
123
  PetscFunctionReturn(0);
124
}
125
 
126
/* Provides next shift to be computed */
127
#undef __FUNCT__
128
#define __FUNCT__ "EPSExtractShift"
129
static PetscErrorCode EPSExtractShift(EPS eps){
130
  PetscErrorCode   ierr;
2708 carcamgo 131
  PetscInt         iner,dir,i,k;
2459 carcamgo 132
  Mat              F;
133
  PC               pc;
134
  KSP              ksp;
135
  SR               sr;
136
 
137
  PetscFunctionBegin;  
138
  sr = (SR)(eps->data);
139
  if(sr->nPend > 0){
2708 carcamgo 140
    sr->sPrev = sr->sPres;
2459 carcamgo 141
    sr->sPres = sr->pending[--sr->nPend];
142
    ierr = STSetShift(eps->OP, sr->sPres->value);CHKERRQ(ierr);
143
    ierr = STGetKSP(eps->OP, &ksp);CHKERRQ(ierr);
144
    ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
145
    ierr = PCFactorGetMatrix(pc,&F);CHKERRQ(ierr);
146
    ierr = MatGetInertia(F,&iner,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
147
    sr->sPres->inertia = iner;
148
    eps->target = sr->sPres->value;
149
    eps->reason = EPS_CONVERGED_ITERATING;
2596 carcamgo 150
    eps->its = 0;
2708 carcamgo 151
    sr->sPres->expf = PETSC_FALSE;
152
    /* For rational Krylov */
153
    if(sr->nS >0 && (sr->sPrev == sr->sPres->neighb[0] || sr->sPrev == sr->sPres->neighb[1]) ){
154
      dir = (sr->sPres->neighb[0] == sr->sPrev)?1:-1;
155
      dir*=sr->dir;
156
      k = 0;
157
      for(i=0;i<sr->nS;i++){
158
        if(dir*sr->S[i] >0){
159
          sr->S[k] = sr->S[i];
160
          sr->S[sr->nS+k] = sr->S[sr->nS+i];
161
          ierr = VecCopy(eps->V[eps->nconv+i],eps->V[k++]);CHKERRQ(ierr);
162
          if(k>=sr->nS/2)break;
163
        }
164
      }
165
      for(i=0;i<k;i++)sr->S[k+i] = sr->S[sr->nS+i];
166
      sr->nS = k;
167
      /* Normalize u and append it to V */      
168
      ierr = VecAXPBY(eps->V[sr->nS],1.0/sr->beta,0.0,eps->work[0]);CHKERRQ(ierr);
169
    }
170
    eps->nconv = 0;
171
  }else sr->sPres = PETSC_NULL;
172
  PetscFunctionReturn(0);
2459 carcamgo 173
}
2708 carcamgo 174
 
175
#undef __FUNCT__  
176
#define __FUNCT__ "EPSUpdateShiftRKS"
177
static PetscErrorCode EPSUpdateShiftRKS(EPS eps,PetscInt n,PetscReal sigma1,PetscReal sigma2,PetscScalar *S)
178
{
179
  PetscErrorCode ierr;
180
  PetscInt       i,j;
181
  PetscScalar    *L,*tau,*work2,*R,*work,alpha;
182
  PetscBLASInt   n1,n0,lwork,info;
183
 
184
  PetscFunctionBegin;
185
  lwork = PetscBLASIntCast(n+1);
186
  i = 2*n*n+4*n+2;
187
  ierr = PetscMalloc(i*sizeof(PetscScalar),&work);CHKERRQ(ierr);  
188
  ierr = PetscMemzero(work,i*sizeof(PetscScalar));CHKERRQ(ierr);
189
  L = work;/* size (n+1)*(n+1) */
190
  tau = L+(n+1)*(n+1);
191
  work2 = tau+n;
192
  R = work2+(n+1);
2459 carcamgo 193
 
2708 carcamgo 194
  for (i=0;i<n;i++)
195
    L[i+i*(n+1)] = 1.0+(sigma1-sigma2)*S[i];
196
  for (i=0;i<n;i++)
197
    L[n+i*(n+1)] = (sigma1-sigma2)*S[n+i];
198
  ierr = PetscMemzero(S,(n+1)*n*sizeof(PetscScalar));CHKERRQ(ierr);
199
 
200
  /* Compute qr */
201
  n1 = PetscBLASIntCast(n+1);
202
  n0 = PetscBLASIntCast(n);
203
  LAPACKgeqrf_(&n1,&n0,L,&n1,tau,work2,&lwork,&info);
204
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xGEQRF %d",info);
205
  /* Copying R from L */
206
  for (j=0;j<n;j++)
207
    for(i=0;i<=j;i++)
208
      R[i+j*n]=L[i+j*(n+1)];
209
  /* Compute the orthogonal matrix in L */
210
  LAPACKorgqr_(&n1,&n1,&n0,L,&n1,tau,work2,&lwork,&info);
211
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGQR %d",info);
212
  /* Compute the updated matrix of projected problem */
213
  for(j=0;j<n;j++){
214
    for(i=0;i<n+1;i++)
215
      S[j*(n+1)+i]=L[i*(n+1)+j];
216
  }
217
  alpha = -1.0/(sigma1-sigma2);
218
  BLAStrsm_("R","U","N","N",&n1,&n0,&alpha,R,&n0,S,&n1);
219
  for(i=0;i<n;i++)
220
    S[(n+1)*i+i]-=alpha;
221
  /* Update vectors */
222
  ierr = SlepcUpdateVectors(n+1,eps->V,0,n+1,L,n+1,PETSC_FALSE);CHKERRQ(ierr);
223
  ierr = PetscFree(work);
224
  PetscFunctionReturn(0);
225
}
226
 
227
#undef __FUNCT__  
228
#define __FUNCT__ "EPSProjectedKS_Slice"
2459 carcamgo 229
/*
2708 carcamgo 230
   EPSProjectedKS_ - Solves the projected eigenproblem in the Krylov-Schur
231
   method (Spectrum Slicing).
232
 
233
   On input:
234
     n is the matrix dimension
235
     l is the number of vectors kept in previous restart
236
     a contains diagonal elements (length n)
237
     b contains offdiagonal elements (length n-1)
238
 
239
   On output:
240
     eig is the sorted list of eigenvalues
241
     Q is the eigenvector matrix (order n, leading dimension n)
242
 
243
   Workspace:
244
     work is workspace to store a real square matrix of order n
245
     perm is workspace to store 2n integers
246
*/
247
static PetscErrorCode EPSProjectedKS_Slice(EPS eps,PetscInt n_,PetscScalar *Z,PetscInt l,PetscReal *d,PetscReal *e,PetscScalar *eig,PetscScalar *Q,PetscReal *work,PetscInt *perm)
248
{
249
  PetscErrorCode ierr;
250
  PetscInt       i,j,k,p;
251
  PetscReal      rtmp,*Qreal = (PetscReal*)Q;
252
  PetscBLASInt   n,n1,n2,lwork,info;
253
 
254
#if defined(SLEPC_MISSING_LAPACK_SYTRD) || defined(SLEPC_MISSING_LAPACK_ORGTR) || defined(SLEPC_MISSING_LAPACK_STEQR)
255
  PetscFunctionBegin;
256
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SYTRD/ORGTR/STEQR - Lapack routine is unavailable.");
257
#else
258
  PetscFunctionBegin;
259
/* Compute eigendecomposition of projected matrix */
260
  ierr = PetscLogEventBegin(EPS_Dense,0,0,0,0);CHKERRQ(ierr);
261
  n = PetscBLASIntCast(n_);
262
  /* Quick return */
263
  if (n == 1) {
264
    Q[0] = 1.0;
265
    PetscFunctionReturn(0);    
266
  }
267
  n1 = PetscBLASIntCast(l+1);    /* size of leading block, including residuals */
268
  n2 = PetscBLASIntCast(n-l-1);  /* size of trailing block */
269
  ierr = PetscMemzero(work,n*n*sizeof(PetscReal));CHKERRQ(ierr);
270
  if(l>0){
271
    /* Flip matrix, copying the values saved in Q */
272
    if(!Z){
273
      for (i=0;i<n;i++)
274
        work[(n-1-i)+(n-1-i)*n] = d[i];
275
      for (i=0;i<l;i++)
276
        work[(n-1-i)+(n-1-l)*n] = e[i];
277
      for (i=l;i<n-1;i++)
278
        work[(n-1-i)+(n-1-i-1)*n] = e[i];
279
    }else{
280
      for(i=0;i<n_-l-1;i++){
281
        work[i*n_+i] = d[n_-1-i];
282
        work[i*n_+i+1] = e[n_-2-i];
283
      }
284
      for(j=n_-l-1;j<n_;j++){
285
        for(i=j;i<n_;i++){
286
          work[j*n_+i] = PetscRealPart(Z[(n_-i-1)*(l+1)+(n_-j-1)]);
287
        }
288
      }
289
      work[(n_-l-1)*(n_+1)]=d[l];
290
    }
291
    /* Reduce (2,2)-block of flipped S to tridiagonal form */
292
    lwork = PetscBLASIntCast(n_*n_-n_);
293
    LAPACKsytrd_("L",&n1,work+n2*(n+1),&n,d,e,Qreal,Qreal+n,&lwork,&info);
294
    if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
295
 
296
    /* Flip back diag and subdiag, put them in d and e */
297
    for (i=0;i<n-1;i++) {
298
      d[n-i-1] = work[i+i*n];
299
      e[n-i-2] = work[i+1+i*n];
300
    }
301
    d[0] = work[n-1+(n-1)*n];
302
 
303
    /* Compute the orthogonal matrix used for tridiagonalization */
304
    LAPACKorgtr_("L",&n1,work+n2*(n+1),&n,Qreal,Qreal+n,&lwork,&info);
305
    if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
306
 
307
    /* Create full-size Q, flipped back to original order */
308
    for (i=0;i<n;i++)
309
      for (j=0;j<n;j++)
310
        Qreal[i+j*n] = 0.0;
311
    for (i=n1;i<n;i++)
312
      Qreal[i+i*n] = 1.0;
313
    for (i=0;i<n1;i++)
314
      for (j=0;j<n1;j++)
315
        Qreal[i+j*n] = work[n-i-1+(n-j-1)*n];
316
 
317
    /* Solve the tridiagonal eigenproblem */
318
    LAPACKsteqr_("V",&n,d,e,Qreal,&n,work,&info);
319
  }else {
320
    LAPACKsteqr_("I",&n,d,e,Qreal,&n,work,&info);
321
  }
322
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSTEQR %d",info);
323
  /* Sort eigendecomposition according to eps->which */
324
  ierr = EPSSortEigenvaluesReal(eps,n,d,perm);CHKERRQ(ierr);
325
  for (i=0;i<n;i++)
326
    eig[i] = d[perm[i]];
327
  for (i=0;i<n;i++) {
328
    p = perm[i];
329
    if (p != i) {
330
      j = i + 1;
331
      while (perm[j] != i) j++;
332
      perm[j] = p; perm[i] = i;
333
      /* swap eigenvectors i and j */
334
      for (k=0;k<n;k++) {
335
        rtmp = Qreal[k+p*n]; Qreal[k+p*n] = Qreal[k+i*n]; Qreal[k+i*n] = rtmp;
336
      }
337
    }
338
  }
339
#if defined(PETSC_USE_COMPLEX)
340
  for (j=n-1;j>=0;j--)
341
    for (i=n-1;i>=0;i--)
342
      Q[i+j*n] = Qreal[i+j*n];
343
#endif
344
  ierr = PetscLogEventEnd(EPS_Dense,0,0,0,0);CHKERRQ(ierr);
345
  PetscFunctionReturn(0);
346
#endif
347
}
348
 
349
/*
2464 carcamgo 350
   Symmetric KrylovSchur adapted to spectrum slicing:
2596 carcamgo 351
   Allows searching an specific amount of eigenvalues in the subintervals left and right.
352
   Returns whether the search has succeeded
2459 carcamgo 353
*/
354
#undef __FUNCT__
355
#define __FUNCT__ "EPSKrylovSchur_Slice"
356
static PetscErrorCode EPSKrylovSchur_Slice(EPS eps)
357
{
2404 jroman 358
  PetscErrorCode ierr;
2459 carcamgo 359
  PetscInt       i,conv,k,l,lds,lt,nv,m,*iwork,p,j;
2404 jroman 360
  Vec            u=eps->work[0];
2708 carcamgo 361
  PetscScalar    *Q,nu,rtmp,alpha;
2640 carcamgo 362
  PetscReal      *a,*b,*work,beta;
2404 jroman 363
  PetscBool      breakdown;
2596 carcamgo 364
  PetscInt       count0,count1;
2459 carcamgo 365
  PetscReal      theta,lambda;
366
  shift          sPres;
2708 carcamgo 367
  PetscBool      complIterating,iscayley;
368
  PetscBool      sch0,sch1;
2599 carcamgo 369
  PetscInt       iterCompl=0,n0,n1,aux,auxc;
2459 carcamgo 370
  SR             sr;
371
 
2404 jroman 372
  PetscFunctionBegin;
2596 carcamgo 373
  /* Spectrum slicing data */
2459 carcamgo 374
  sr = (SR)eps->data;
375
  sPres = sr->sPres;
376
  complIterating =PETSC_FALSE;
377
  sch1 = sch0 = PETSC_TRUE;
2404 jroman 378
  lds = PetscMin(eps->mpd,eps->ncv);
379
  ierr = PetscMalloc(lds*lds*sizeof(PetscReal),&work);CHKERRQ(ierr);
380
  ierr = PetscMalloc(lds*lds*sizeof(PetscScalar),&Q);CHKERRQ(ierr);
381
  ierr = PetscMalloc(2*lds*sizeof(PetscInt),&iwork);CHKERRQ(ierr);
382
  lt = PetscMin(eps->nev+eps->mpd,eps->ncv);
2459 carcamgo 383
  ierr = PetscMalloc(lt*sizeof(PetscReal),&a);CHKERRQ(ierr);
384
  ierr = PetscMalloc(lt*sizeof(PetscReal),&b);CHKERRQ(ierr);
2596 carcamgo 385
  count0=0;count1=0; /* Found on both sides */
2708 carcamgo 386
  /* filling in values for the monitor */
2633 carcamgo 387
  if(eps->numbermonitors >0){
388
    ierr = PetscTypeCompare((PetscObject)eps->OP,STCAYLEY,&iscayley);CHKERRQ(ierr);
389
    if(iscayley){
390
      ierr = STCayleyGetAntishift(eps->OP,&nu);CHKERRQ(ierr);    
391
      for(i=0;i<sr->indexEig;i++){
392
        sr->monit[i]=(nu + sr->eig[i])/(sr->eig[i] - sPres->value);
393
      }
394
    }else{
395
      for(i=0;i<sr->indexEig;i++){
396
        sr->monit[i]=1.0/(sr->eig[i] - sPres->value);
397
      }
2629 carcamgo 398
    }
399
  }
2708 carcamgo 400
  if(sr->nS > 0 && (sPres->neighb[0] == sr->sPrev || sPres->neighb[1] == sr->sPrev) ){
401
    /* Rational Krylov */
402
    ierr = EPSUpdateShiftRKS(eps,sr->nS,sr->sPrev->value,sPres->value,sr->S);CHKERRQ(ierr);
403
    l = sr->nS;
404
  }else{
405
    /* Get the starting Lanczos vector */
406
    ierr = EPSGetStartVector(eps,0,eps->V[0],PETSC_NULL);CHKERRQ(ierr);
407
    l = 0;
408
  }
2404 jroman 409
  /* Restart loop */
410
  while (eps->reason == EPS_CONVERGED_ITERATING) {
2596 carcamgo 411
    eps->its++; sr->itsKs++;
2404 jroman 412
    /* Compute an nv-step Lanczos factorization */
413
    m = PetscMin(eps->nconv+eps->mpd,eps->ncv);
414
    ierr = EPSFullLanczos(eps,a+l,b+l,eps->V,eps->nconv+l,&m,u,&breakdown);CHKERRQ(ierr);
2708 carcamgo 415
    if(breakdown){/* explicit purification*/
416
      sPres->expf = PETSC_TRUE;    
417
    }
2404 jroman 418
    nv = m - eps->nconv;
419
    beta = b[nv-1];
2459 carcamgo 420
    /* Solve projected problem and compute residual norm estimates */
2708 carcamgo 421
    if(eps->its == 1 && l > 0){/* After rational update */
422
      ierr =  EPSProjectedKS_Slice(eps,nv,sr->S,l,a,b,eps->eigr+eps->nconv,Q,work,iwork);CHKERRQ(ierr);
423
    }else{/* Restart */
424
      ierr = EPSProjectedKS_Slice(eps,nv,PETSC_NULL,l,a,b,eps->eigr+eps->nconv,Q,work,iwork);CHKERRQ(ierr);
425
    }
2596 carcamgo 426
    /* Residual */
2583 jroman 427
    ierr = EPSKrylovConvergence(eps,PETSC_TRUE,PETSC_TRUE,eps->nconv,nv,PETSC_NULL,nv,Q,eps->V+eps->nconv,nv,beta,1.0,&k,PETSC_NULL);CHKERRQ(ierr);
2596 carcamgo 428
    /* Check convergence */
429
    conv=k=j=0;
430
    for(i=0;i<nv;i++)if(eps->errest[eps->nconv+i] < eps->tol)conv++;
431
    for(i=0;i<nv;i++){
432
      if(eps->errest[eps->nconv+i] < eps->tol){
433
        iwork[j++]=i;
434
      }else iwork[conv+k++]=i;
2459 carcamgo 435
    }
2596 carcamgo 436
    for(i=0;i<nv;i++){
2599 carcamgo 437
      a[i]=PetscRealPart(eps->eigr[eps->nconv+i]);
438
      b[i]=eps->errest[eps->nconv+i];
439
    }
440
    for(i=0;i<nv;i++){
2596 carcamgo 441
      eps->eigr[eps->nconv+i] = a[iwork[i]];
2599 carcamgo 442
      eps->errest[eps->nconv+i] = b[iwork[i]];
2459 carcamgo 443
    }
2596 carcamgo 444
    for( i=0;i<nv;i++){
445
      p=iwork[i];
2708 carcamgo 446
        if(p!=i){
447
          j=i+1;
448
          while(iwork[j]!=i)j++;
449
          iwork[j]=p;iwork[i]=i;
450
          for(k=0;k<nv;k++){
451
            rtmp=Q[k+p*nv];Q[k+p*nv]=Q[k+i*nv];Q[k+i*nv]=rtmp;
452
          }
453
        }
454
      }
455
      k=eps->nconv+conv;
2459 carcamgo 456
    /* Checking values obtained for completing */
2629 carcamgo 457
    for(i=0;i<k;i++){
458
      sr->back[i]=eps->eigr[i];
459
    }
460
    ierr = STBackTransform(eps->OP,k,sr->back,eps->eigi);CHKERRQ(ierr);
2459 carcamgo 461
    count0=count1=0;
462
    for(i=0;i<k;i++){      
463
      theta = PetscRealPart(eps->eigr[i]);
2640 carcamgo 464
      lambda = PetscRealPart(sr->back[i]);
2459 carcamgo 465
      if( ((sr->dir)*theta < 0) && ((sr->dir)*(lambda - sPres->ext[0]) > 0))count0++;
466
      if( ((sr->dir)*theta > 0) && ((sr->dir)*(sPres->ext[1] - lambda) > 0))count1++;
467
    }
2404 jroman 468
 
2596 carcamgo 469
    /* Checks completion */
2459 carcamgo 470
    if( (!sch0||count0 >= sPres->nsch[0]) && (!sch1 ||count1 >= sPres->nsch[1]) ) {
471
      eps->reason = EPS_CONVERGED_TOL;
472
    }else {
473
      if(!complIterating && eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
474
      if(complIterating){
475
        if(--iterCompl <= 0) eps->reason = EPS_DIVERGED_ITS;
2596 carcamgo 476
      }else if (k >= eps->nev) {
2459 carcamgo 477
        n0 = sPres->nsch[0]-count0;
478
        n1 = sPres->nsch[1]-count1;
2708 carcamgo 479
        if( sr->iterCompl>0 && ( (n0>0 && n0<= sr->nMAXCompl)||(n1>0&&n1<=sr->nMAXCompl) )){
2596 carcamgo 480
          /* Iterating for completion*/
2459 carcamgo 481
          complIterating = PETSC_TRUE;
482
          if(n0 >sr->nMAXCompl)sch0 = PETSC_FALSE;
483
          if(n1 >sr->nMAXCompl)sch1 = PETSC_FALSE;
484
          iterCompl = sr->iterCompl;
485
        }else eps->reason = EPS_CONVERGED_TOL;
486
      }      
487
    }
2404 jroman 488
    /* Update l */
2708 carcamgo 489
    if(eps->reason == EPS_CONVERGED_ITERATING )l = (eps->nconv+nv-k)/2;
490
    else l=eps->nconv+nv-k;
491
    if(breakdown)l=0;
2404 jroman 492
 
493
    if (eps->reason == EPS_CONVERGED_ITERATING) {
494
      if (breakdown) {
495
        /* Start a new Lanczos factorization */
2499 jroman 496
        ierr = PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%D norm=%G)\n",eps->its,beta);CHKERRQ(ierr);
2404 jroman 497
        ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
498
        if (breakdown) {
499
          eps->reason = EPS_DIVERGED_BREAKDOWN;
2499 jroman 500
          ierr = PetscInfo(eps,"Unable to generate more start vectors\n");CHKERRQ(ierr);
2404 jroman 501
        }
502
      } else {
503
        /* Prepare the Rayleigh quotient for restart */
504
        for (i=0;i<l;i++) {
505
          a[i] = PetscRealPart(eps->eigr[i+k]);
506
          b[i] = PetscRealPart(Q[nv-1+(i+k-eps->nconv)*nv]*beta);
507
        }
508
      }
509
    }
510
    /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
511
    ierr = SlepcUpdateVectors(nv,eps->V+eps->nconv,0,k+l-eps->nconv,Q,nv,PETSC_FALSE);CHKERRQ(ierr);
2708 carcamgo 512
    /* Purification */
513
    if(!sPres->expf){/* u not saved if breakdown */
514
      for(i=eps->nconv; i<k;i++){
515
        alpha = (Q[nv-1+(i-eps->nconv)*nv])/PetscRealPart(eps->eigr[i]);
516
        ierr = VecAXPY(eps->V[i], alpha, u);CHKERRQ(ierr);
517
      }
518
    }
2404 jroman 519
    /* Normalize u and append it to V */
2708 carcamgo 520
    if ( eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
2404 jroman 521
      ierr = VecAXPBY(eps->V[k+l],1.0/beta,0.0,u);CHKERRQ(ierr);
522
    }
2708 carcamgo 523
    /* Monitor */
2629 carcamgo 524
    if(eps->numbermonitors >0){
525
      aux = auxc = 0;
526
      for(i=0;i<nv+eps->nconv;i++){
527
        sr->back[i]=eps->eigr[i];
2599 carcamgo 528
      }
2629 carcamgo 529
      ierr = STBackTransform(eps->OP,nv+eps->nconv,sr->back,eps->eigi);CHKERRQ(ierr);
530
      for(i=0;i<nv+eps->nconv;i++){
2640 carcamgo 531
        lambda = PetscRealPart(sr->back[i]);
2629 carcamgo 532
        if( ((sr->dir)*(lambda - sPres->ext[0]) > 0)&& ((sr->dir)*(sPres->ext[1] - lambda) > 0)){
533
          sr->monit[sr->indexEig+aux]=eps->eigr[i];
534
          sr->errest[sr->indexEig+aux]=eps->errest[i];
535
          aux++;
536
          if(eps->errest[i] < eps->tol)auxc++;
537
        }
538
      }
539
      ierr = EPSMonitor(eps,eps->its,auxc+sr->indexEig,sr->monit,sr->eigi,sr->errest,sr->indexEig+aux);CHKERRQ(ierr);
2599 carcamgo 540
    }
2708 carcamgo 541
    conv = k - eps->nconv;
2404 jroman 542
    eps->nconv = k;
2708 carcamgo 543
 
544
    if(eps->reason != EPS_CONVERGED_ITERATING){
545
      /* Store approximated values for next shift */
546
      sr->nS = l;
547
      for (i=0;i<l;i++) {
548
        sr->S[i] = eps->eigr[i+k];/* Diagonal elements */
549
        sr->S[i+l] = Q[nv-1+(i+conv)*nv]*beta; /* Out of diagonal elements */
550
      }
551
      sr->beta = beta;
552
    }
2459 carcamgo 553
  }
2596 carcamgo 554
  /* Check for completion */
555
  for(i=0;i< eps->nconv; i++){
556
    if( (sr->dir)*PetscRealPart(eps->eigr[i])>0 )sPres->nconv[1]++;
557
    else sPres->nconv[0]++;
558
  }
2468 eromero 559
  sPres->comp[0] = (count0 >= sPres->nsch[0])?PETSC_TRUE:PETSC_FALSE;
560
  sPres->comp[1] = (count1 >= sPres->nsch[1])?PETSC_TRUE:PETSC_FALSE;
2701 carcamgo 561
  if(count0 > sPres->nsch[0] || count1 > sPres->nsch[1])SETERRQ(((PetscObject)eps)->comm,1,"Unexpected error in Spectrum Slicing!\nMismatch between number of values found and information from inertia");
562
 
2404 jroman 563
  ierr = PetscFree(Q);CHKERRQ(ierr);
564
  ierr = PetscFree(a);CHKERRQ(ierr);
565
  ierr = PetscFree(b);CHKERRQ(ierr);
566
  ierr = PetscFree(work);CHKERRQ(ierr);
567
  ierr = PetscFree(iwork);CHKERRQ(ierr);
568
  PetscFunctionReturn(0);
569
}
570
 
2459 carcamgo 571
/*
2596 carcamgo 572
  Obtains value of subsequent shift
2459 carcamgo 573
*/
574
#undef __FUNCT__
575
#define __FUNCT__ "EPSGetNewShiftValue"
2708 carcamgo 576
static PetscErrorCode EPSGetNewShiftValue(EPS eps,PetscInt side,PetscReal *newS)
577
{
2596 carcamgo 578
  PetscReal   lambda,d_prev;
2459 carcamgo 579
  PetscInt    i,idxP;
580
  SR          sr;
2666 eromero 581
  shift       sPres,s;
2459 carcamgo 582
 
583
  PetscFunctionBegin;  
584
  sr = (SR)eps->data;
585
  sPres = sr->sPres;
2464 carcamgo 586
  if( sPres->neighb[side]){
2596 carcamgo 587
  /* Completing a previous interval */
588
    if(!sPres->neighb[side]->neighb[side] && sPres->neighb[side]->nconv[side]==0){ /* One of the ends might be too far from eigenvalues */
589
      if(side) *newS = (sPres->value + PetscRealPart(sr->eig[sr->perm[sr->indexEig-1]]))/2;
590
      else *newS = (sPres->value + PetscRealPart(sr->eig[sr->perm[0]]))/2;
591
    }else *newS=(sPres->value + sPres->neighb[side]->value)/2;
592
  }else{ /* (Only for side=1). Creating a new interval. */
593
    if(sPres->neigs==0){/* No value has been accepted*/
2464 carcamgo 594
      if(sPres->neighb[0]){
2596 carcamgo 595
        /* Multiplying by 10 the previous distance */
2465 jroman 596
        *newS = sPres->value + 10*(sr->dir)*PetscAbsReal(sPres->value - sPres->neighb[0]->value);
2596 carcamgo 597
        sr->nleap++;
598
        /* Stops when the interval is open and no values are found in the last 5 shifts (there might be infinite eigenvalues) */
599
        if( !sr->hasEnd && sr->nleap > 5)SETERRQ(((PetscObject)eps)->comm,1,"Unable to compute the wanted eigenvalues with open interval");          
600
      }else {/* First shift */
2459 carcamgo 601
        if(eps->nconv != 0){
2596 carcamgo 602
           /* Unaccepted values give information for next shift */
603
           idxP=0;/* Number of values left from shift */
2459 carcamgo 604
           for(i=0;i<eps->nconv;i++){
605
             lambda = PetscRealPart(eps->eigr[i]);
606
             if( (sr->dir)*(lambda - sPres->value) <0)idxP++;
607
             else break;
608
           }
2596 carcamgo 609
           /* Avoiding subtraction of eigenvalues (might be the same).*/
2459 carcamgo 610
           if(idxP>0){
2465 jroman 611
             d_prev = PetscAbsReal(sPres->value - PetscRealPart(eps->eigr[0]))/(idxP+0.3);
2459 carcamgo 612
           }else {
2465 jroman 613
             d_prev = PetscAbsReal(sPres->value - PetscRealPart(eps->eigr[eps->nconv-1]))/(eps->nconv+0.3);
2459 carcamgo 614
           }
615
           *newS = sPres->value + ((sr->dir)*d_prev*eps->nev)/2;
2596 carcamgo 616
        }else{/* No values found, no information for next shift */
617
          SETERRQ(((PetscObject)eps)->comm,1,"First shift renders no information");
2459 carcamgo 618
        }
619
      }
2596 carcamgo 620
    }else{/* Accepted values found */
621
      sr->nleap = 0;
622
      /* Average distance of values in previous subinterval */
2666 eromero 623
      s = sPres->neighb[0];
2464 carcamgo 624
      while(s && PetscAbs(s->inertia - sPres->inertia)==0){
2596 carcamgo 625
        s = s->neighb[0];/* Looking for previous shifts with eigenvalues within */
2459 carcamgo 626
      }
2464 carcamgo 627
      if(s){
2465 jroman 628
        d_prev = PetscAbsReal( (sPres->value - s->value)/(sPres->inertia - s->inertia));
2596 carcamgo 629
      }else{/* First shift. Average distance obtained with values in this shift */
630
        /* first shift might be too far from first wanted eigenvalue (no values found outside the interval)*/
2609 carcamgo 631
        if( (sr->dir)*(PetscRealPart(sr->eig[0])-sPres->value)>0 && PetscAbsReal( (PetscRealPart(sr->eig[sr->indexEig-1]) - PetscRealPart(sr->eig[0]))/PetscRealPart(sr->eig[0])) > PetscSqrtReal(eps->tol) ){
2596 carcamgo 632
          d_prev =  PetscAbsReal( (PetscRealPart(sr->eig[sr->indexEig-1]) - PetscRealPart(sr->eig[0])))/(sPres->neigs+0.3);
633
        }else{
634
          d_prev = PetscAbsReal( PetscRealPart(sr->eig[sr->indexEig-1]) - sPres->value)/(sPres->neigs+0.3);          
635
        }
2459 carcamgo 636
      }
2596 carcamgo 637
      /* Average distance is used for next shift by adding it to value on the right or to shift */
2465 jroman 638
      if( (sr->dir)*(PetscRealPart(sr->eig[sPres->index + sPres->neigs -1]) - sPres->value) >0){
639
        *newS = PetscRealPart(sr->eig[sPres->index + sPres->neigs -1])+ ((sr->dir)*d_prev*(eps->nev))/2;  
2596 carcamgo 640
      }else{/* Last accepted value is on the left of shift. Adding to shift */
2459 carcamgo 641
        *newS = sPres->value + ((sr->dir)*d_prev*(eps->nev))/2;
642
      }
643
    }
2596 carcamgo 644
    /* End of interval can not be surpassed */
645
    if((sr->dir)*( sr->int1 - *newS) < 0) *newS = sr->int1;
2609 carcamgo 646
  }/* of neighb[side]==null */
2459 carcamgo 647
  PetscFunctionReturn(0);
648
}
649
 
650
/*
2596 carcamgo 651
  Function for sorting an array of real values
2459 carcamgo 652
*/
653
#undef __FUNCT__
654
#define __FUNCT__ "sortRealEigenvalues"
655
static PetscErrorCode sortRealEigenvalues(PetscScalar *r,PetscInt *perm,PetscInt nr,PetscBool prev,PetscInt dir)
656
{
657
  PetscReal      re;
658
  PetscInt       i,j,tmp;
659
 
660
  PetscFunctionBegin;
2464 carcamgo 661
  if(!prev) for (i=0; i < nr; i++) { perm[i] = i; }
2596 carcamgo 662
  /* Insertion sort */
2459 carcamgo 663
  for (i=1; i < nr; i++) {
664
    re = PetscRealPart(r[perm[i]]);
665
    j = i-1;
666
    while ( j>=0 && dir*(re - PetscRealPart(r[perm[j]])) <= 0 ) {
667
      tmp = perm[j]; perm[j] = perm[j+1]; perm[j+1] = tmp; j--;
668
    }
669
  }
670
  PetscFunctionReturn(0);
671
}
672
 
673
/* Stores the pairs obtained since the last shift in the global arrays */
674
#undef __FUNCT__
675
#define __FUNCT__ "EPSStoreEigenpairs"
676
PetscErrorCode EPSStoreEigenpairs(EPS eps)
677
{
678
  PetscErrorCode ierr;
2596 carcamgo 679
  PetscReal      lambda,err,norm;
2459 carcamgo 680
  PetscInt       i,count;
2641 jroman 681
  PetscBool      iscayley;
2459 carcamgo 682
  SR             sr;
683
  shift          sPres;
684
 
685
  PetscFunctionBegin;
686
  sr = (SR)(eps->data);
687
  sPres = sr->sPres;
688
  sPres->index = sr->indexEig;
689
  count = sr->indexEig;
2708 carcamgo 690
  /* Back-transform */
2629 carcamgo 691
  ierr = EPSBackTransform_Default(eps);CHKERRQ(ierr);
692
  ierr = PetscTypeCompare((PetscObject)eps->OP,STCAYLEY,&iscayley);CHKERRQ(ierr);
2596 carcamgo 693
  /* Sort eigenvalues */
2459 carcamgo 694
  ierr = sortRealEigenvalues(eps->eigr,eps->perm,eps->nconv,PETSC_FALSE,sr->dir);
2596 carcamgo 695
  /* Values stored in global array */
2459 carcamgo 696
  for( i=0; i < eps->nconv ;i++ ){
697
    lambda = PetscRealPart(eps->eigr[eps->perm[i]]);
2596 carcamgo 698
    err = eps->errest[eps->perm[i]];
2708 carcamgo 699
 
2596 carcamgo 700
    if(  (sr->dir)*(lambda - sPres->ext[0]) > 0 && (sr->dir)*(sPres->ext[1] - lambda) > 0  ){/* Valid value */
701
      if(count>=sr->numEigs){/* Error found */
2629 carcamgo 702
         SETERRQ(((PetscObject)eps)->comm,1,"Unexpected error in Spectrum Slicing!");
703
      }
2459 carcamgo 704
      sr->eig[count] = lambda;
2596 carcamgo 705
      sr->errest[count] = err;
2708 carcamgo 706
      /* Unlikely explicit purification */
707
      if (sPres->expf && eps->isgeneralized && !iscayley){
2609 carcamgo 708
        ierr = STApply(eps->OP,eps->V[eps->perm[i]],sr->V[count]);CHKERRQ(ierr);
709
        ierr = IPNorm(eps->ip,sr->V[count],&norm);CHKERRQ(ierr);
710
        ierr = VecScale(sr->V[count],1.0/norm);CHKERRQ(ierr);
711
      }else{
712
        ierr = VecCopy(eps->V[eps->perm[i]], sr->V[count]);CHKERRQ(ierr);
713
      }
2459 carcamgo 714
      count++;
2596 carcamgo 715
    }
2459 carcamgo 716
  }
717
  sPres->neigs = count - sr->indexEig;
718
  sr->indexEig = count;
2596 carcamgo 719
  /* Global ordering array updating */
2459 carcamgo 720
  ierr = sortRealEigenvalues(sr->eig,sr->perm,count,PETSC_TRUE,sr->dir);CHKERRQ(ierr);
721
  PetscFunctionReturn(0);
722
}
723
 
724
#undef __FUNCT__
725
#define __FUNCT__ "EPSLookForDeflation"
726
PetscErrorCode EPSLookForDeflation(EPS eps)
727
{
2596 carcamgo 728
  PetscReal       val;
2459 carcamgo 729
  PetscInt        i,count0=0,count1=0;
730
  shift           sPres;
2596 carcamgo 731
  PetscInt        ini,fin,k,idx0,idx1;
2459 carcamgo 732
  SR              sr;
733
 
734
  PetscFunctionBegin;
735
  sr = (SR)(eps->data);
736
  sPres = sr->sPres;
737
 
2464 carcamgo 738
  if(sPres->neighb[0]) ini = (sr->dir)*(sPres->neighb[0]->inertia - sr->inertia0);
2459 carcamgo 739
  else ini = 0;
740
  fin = sr->indexEig;
2596 carcamgo 741
  /* Selection of ends for searching new values */
742
  if(!sPres->neighb[0]) sPres->ext[0] = sr->int0;/* First shift */
2459 carcamgo 743
  else sPres->ext[0] = sPres->neighb[0]->value;
2464 carcamgo 744
  if(!sPres->neighb[1]) {
2459 carcamgo 745
    if(sr->hasEnd) sPres->ext[1] = sr->int1;
746
    else sPres->ext[1] = (sr->dir > 0)?PETSC_MAX_REAL:PETSC_MIN_REAL;
747
  }else sPres->ext[1] = sPres->neighb[1]->value;
2596 carcamgo 748
  /* Selection of values between right and left ends */
2459 carcamgo 749
  for(i=ini;i<fin;i++){
750
    val=PetscRealPart(sr->eig[sr->perm[i]]);
2596 carcamgo 751
    /* Values to the right of left shift */
2459 carcamgo 752
    if( (sr->dir)*(val - sPres->ext[1]) < 0 ){
753
      if((sr->dir)*(val - sPres->value) < 0)count0++;
754
      else count1++;
755
    }else break;
756
  }
2596 carcamgo 757
  /* The number of values on each side are found */
2629 carcamgo 758
  if(sPres->neighb[0]){
2459 carcamgo 759
     sPres->nsch[0] = (sr->dir)*(sPres->inertia - sPres->neighb[0]->inertia)-count0;
2629 carcamgo 760
     if(sPres->nsch[0]<0)SETERRQ(((PetscObject)eps)->comm,1,"Unexpected error in Spectrum Slicing!\nMismatch between number of values found and information from inertia");
761
  }else sPres->nsch[0] = 0;
2459 carcamgo 762
 
2629 carcamgo 763
  if(sPres->neighb[1]){
2459 carcamgo 764
    sPres->nsch[1] = (sr->dir)*(sPres->neighb[1]->inertia - sPres->inertia) - count1;
2629 carcamgo 765
    if(sPres->nsch[1]<0)SETERRQ(((PetscObject)eps)->comm,1,"Unexpected error in Spectrum Slicing!\nMismatch between number of values found and information from inertia");
766
  }else sPres->nsch[1] = (sr->dir)*(sr->inertia1 - sPres->inertia);
2708 carcamgo 767
 
2596 carcamgo 768
  /* Completing vector of indexes for deflation */
769
  idx0 = ini;
770
  idx1 = ini+count0+count1;
2459 carcamgo 771
  k=0;
772
  for(i=idx0;i<idx1;i++)sr->idxDef[k++]=sr->perm[i];
773
  for(i=0;i<k;i++)sr->VDef[i]=sr->V[sr->idxDef[i]];
774
  eps->DS = sr->VDef;
775
  eps->nds = k;
776
  PetscFunctionReturn(0);
777
}
778
 
779
#undef __FUNCT__
780
#define __FUNCT__ "EPSSolve_KrylovSchur_Slice"
781
PetscErrorCode EPSSolve_KrylovSchur_Slice(EPS eps)
782
{
783
  PetscErrorCode ierr;
2708 carcamgo 784
  PetscInt       i,lds;
2459 carcamgo 785
  PetscReal      newS;
786
  KSP            ksp;
787
  PC             pc;
2596 carcamgo 788
  Mat            F;  
789
  PetscReal      *errest_left;
790
  Vec            t;
2459 carcamgo 791
  SR             sr;
792
 
793
  PetscFunctionBegin;
2629 carcamgo 794
#if defined(PETSC_USE_COMPLEX)
795
  SETERRQ(((PetscObject)eps)->comm,PETSC_ERR_SUP,"Spectrum slicing not supported in complex scalars");
796
#endif
2464 carcamgo 797
  ierr = PetscMalloc(sizeof(struct _n_SR),&sr);CHKERRQ(ierr);
2459 carcamgo 798
  eps->data = sr;
2596 carcamgo 799
  sr->itsKs = 0;
800
  sr->nleap = 0;
801
  sr->nMAXCompl = eps->nev/4;
802
  sr->iterCompl = eps->max_it/4;
2708 carcamgo 803
  sr->sPres = PETSC_NULL;
804
  sr->nS = 0;
805
  lds = PetscMin(eps->mpd,eps->ncv);
2596 carcamgo 806
  /* Checking presence of ends and finding direction */
2459 carcamgo 807
  if( eps->inta > PETSC_MIN_REAL){
808
    sr->int0 = eps->inta;
809
    sr->int1 = eps->intb;
810
    sr->dir = 1;
2596 carcamgo 811
    if(eps->intb >= PETSC_MAX_REAL){ /* Right-open interval */
2459 carcamgo 812
      sr->hasEnd = PETSC_FALSE;
813
      sr->inertia1 = eps->n;
814
    }else sr->hasEnd = PETSC_TRUE;
2596 carcamgo 815
  }else{ /* Left-open interval */
2459 carcamgo 816
    sr->int0 = eps->intb;
817
    sr->int1 = eps->inta;
818
    sr->dir = -1;
819
    sr->hasEnd = PETSC_FALSE;
820
    sr->inertia1 = 0;
821
  }
2596 carcamgo 822
  /* Array of pending shifts */
823
  sr->maxPend = 100;/* Initial size */
2459 carcamgo 824
  ierr = PetscMalloc((sr->maxPend)*sizeof(shift),&sr->pending);CHKERRQ(ierr);
825
  if(sr->hasEnd){
826
    ierr = STGetKSP(eps->OP, &ksp);CHKERRQ(ierr);
827
    ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
828
    ierr = PCFactorGetMatrix(pc,&F);CHKERRQ(ierr);
2596 carcamgo 829
    /* Not looking for values in b (just inertia).*/
2459 carcamgo 830
    ierr = MatGetInertia(F,&sr->inertia1,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
2629 carcamgo 831
    ierr = PCReset(pc);CHKERRQ(ierr); /* avoiding memory leak */
2459 carcamgo 832
  }
833
  sr->nPend = 0;
834
  ierr = EPSCreateShift(eps,sr->int0,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
835
  ierr = EPSExtractShift(eps);
836
  sr->s0 = sr->sPres;
837
  sr->inertia0 = sr->s0->inertia;
838
  sr->numEigs = (sr->dir)*(sr->inertia1 - sr->inertia0);
839
  sr->indexEig = 0;
2596 carcamgo 840
  /* Only with eigenvalues present in the interval ...*/
2464 carcamgo 841
  if(sr->numEigs==0){
842
    eps->reason = EPS_CONVERGED_TOL;
2596 carcamgo 843
    ierr = PetscFree(sr->s0);CHKERRQ(ierr);
844
    ierr = PetscFree(sr->pending);CHKERRQ(ierr);
845
    ierr = PetscFree(sr);CHKERRQ(ierr);
2464 carcamgo 846
    PetscFunctionReturn(0);
847
  }
2596 carcamgo 848
  /* Memory reservation for eig, V and perm */
2708 carcamgo 849
  ierr = PetscMalloc(lds*lds*sizeof(PetscScalar),&sr->S);CHKERRQ(ierr);
850
  ierr = PetscMemzero(sr->S,lds*lds*sizeof(PetscScalar));CHKERRQ(ierr);
2464 carcamgo 851
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscScalar),&sr->eig);CHKERRQ(ierr);
2596 carcamgo 852
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscScalar),&sr->eigi);CHKERRQ(ierr);
2599 carcamgo 853
  ierr = PetscMalloc((sr->numEigs+eps->ncv) *sizeof(PetscReal),&sr->errest);CHKERRQ(ierr);
854
  ierr = PetscMalloc((sr->numEigs+eps->ncv)*sizeof(PetscReal),&errest_left);CHKERRQ(ierr);
2609 carcamgo 855
  ierr = PetscMalloc((sr->numEigs+eps->ncv)*sizeof(PetscScalar),&sr->monit);CHKERRQ(ierr);
2629 carcamgo 856
  ierr = PetscMalloc((eps->ncv)*sizeof(PetscScalar),&sr->back);CHKERRQ(ierr);
2599 carcamgo 857
  for(i=0;i<sr->numEigs;i++){sr->eigi[i]=0;sr->eig[i] = 0;}
858
  for(i=0;i<sr->numEigs+eps->ncv;i++){errest_left[i]=0;sr->errest[i]=0;sr->monit[i]=0;}
2464 carcamgo 859
  ierr = VecCreateMPI(((PetscObject)eps)->comm,eps->nloc,PETSC_DECIDE,&t);CHKERRQ(ierr);
860
  ierr = VecDuplicateVecs(t,sr->numEigs,&sr->V);CHKERRQ(ierr);
861
  ierr = VecDestroy(&t);CHKERRQ(ierr);
2596 carcamgo 862
  /* Vector for maintaining order of eigenvalues */
2464 carcamgo 863
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscInt),&sr->perm);CHKERRQ(ierr);
864
  for(i=0;i< sr->numEigs;i++)sr->perm[i]=i;
2596 carcamgo 865
  /* Vectors for deflation */
866
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscInt),&sr->idxDef);CHKERRQ(ierr);
2464 carcamgo 867
  ierr = PetscMalloc((sr->numEigs)*sizeof(Vec),&sr->VDef);CHKERRQ(ierr);
868
  sr->indexEig = 0;
2708 carcamgo 869
  /* Main loop */
2464 carcamgo 870
  while(sr->sPres){
2596 carcamgo 871
    /* Search for deflation */
2464 carcamgo 872
    ierr = EPSLookForDeflation(eps);CHKERRQ(ierr);
2596 carcamgo 873
    /* KrylovSchur */
2464 carcamgo 874
    ierr = EPSKrylovSchur_Slice(eps);CHKERRQ(ierr);
2596 carcamgo 875
 
2464 carcamgo 876
    ierr = EPSStoreEigenpairs(eps);CHKERRQ(ierr);
2596 carcamgo 877
    /* Select new shift */
2468 eromero 878
    if(!sr->sPres->comp[1]){
2464 carcamgo 879
      ierr = EPSGetNewShiftValue(eps,1,&newS);CHKERRQ(ierr);
880
      ierr = EPSCreateShift(eps,newS,sr->sPres,sr->sPres->neighb[1]);
881
    }
2468 eromero 882
    if(!sr->sPres->comp[0]){
2596 carcamgo 883
      /* Completing earlier interval */
2464 carcamgo 884
      ierr = EPSGetNewShiftValue(eps,0,&newS);CHKERRQ(ierr);
885
      ierr = EPSCreateShift(eps,newS,sr->sPres->neighb[0],sr->sPres);
886
    }
2596 carcamgo 887
    /* Preparing for a new search of values */
2464 carcamgo 888
    ierr = EPSExtractShift(eps);CHKERRQ(ierr);
889
  }
2596 carcamgo 890
 
891
  /* Updating eps values prior to exit */
2629 carcamgo 892
 
2464 carcamgo 893
  ierr = VecDestroyVecs(eps->allocated_ncv,&eps->V);CHKERRQ(ierr);
894
  eps->V = sr->V;
2708 carcamgo 895
  ierr = PetscFree(sr->S);CHKERRQ(ierr);
2464 carcamgo 896
  ierr = PetscFree(eps->eigr);CHKERRQ(ierr);
897
  ierr = PetscFree(eps->eigi);CHKERRQ(ierr);
898
  ierr = PetscFree(eps->errest);CHKERRQ(ierr);
899
  ierr = PetscFree(eps->errest_left);CHKERRQ(ierr);
900
  ierr = PetscFree(eps->perm);CHKERRQ(ierr);
2596 carcamgo 901
  eps->eigr = sr->eig;
902
  eps->eigi = sr->eigi;
903
  eps->errest = sr->errest;
904
  eps->errest_left = errest_left;
2464 carcamgo 905
  eps->perm = sr->perm;
2596 carcamgo 906
  eps->ncv = eps->allocated_ncv = sr->numEigs;
2464 carcamgo 907
  eps->nconv = sr->indexEig;
908
  eps->reason = EPS_CONVERGED_TOL;
2596 carcamgo 909
  eps->its = sr->itsKs;
2464 carcamgo 910
  eps->nds = 0;
911
  eps->DS = PETSC_NULL;
2596 carcamgo 912
  eps->evecsavailable = PETSC_TRUE;
2464 carcamgo 913
  ierr = PetscFree(sr->VDef);CHKERRQ(ierr);
914
  ierr = PetscFree(sr->idxDef);CHKERRQ(ierr);
915
  ierr = PetscFree(sr->pending);CHKERRQ(ierr);
2599 carcamgo 916
  ierr = PetscFree(sr->monit);CHKERRQ(ierr);
2629 carcamgo 917
  ierr = PetscFree(sr->back);CHKERRQ(ierr);
2596 carcamgo 918
  /* Reviewing list of shifts to free memory */
2464 carcamgo 919
  shift s = sr->s0;
920
  if(s){
921
    while(s->neighb[1]){
922
      s = s->neighb[1];
923
      ierr = PetscFree(s->neighb[0]);CHKERRQ(ierr);
2459 carcamgo 924
    }
2464 carcamgo 925
    ierr = PetscFree(s);CHKERRQ(ierr);
2459 carcamgo 926
  }
2464 carcamgo 927
  ierr = PetscFree(sr);CHKERRQ(ierr);
2459 carcamgo 928
  PetscFunctionReturn(0);
2599 carcamgo 929
}