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++){
2716 jroman 158
        if(dir*PetscRealPart(sr->S[i])>0.0){
2708 carcamgo 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;
2709 carcamgo 365
  PetscReal      lambda;
2459 carcamgo 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++){      
2640 carcamgo 463
      lambda = PetscRealPart(sr->back[i]);
2709 carcamgo 464
      if( ((sr->dir)*(sPres->value - lambda) > 0) && ((sr->dir)*(lambda - sPres->ext[0]) > 0))count0++;
465
      if( ((sr->dir)*(lambda - sPres->value) > 0) && ((sr->dir)*(sPres->ext[1] - lambda) > 0))count1++;
2459 carcamgo 466
    }
2404 jroman 467
 
2596 carcamgo 468
    /* Checks completion */
2459 carcamgo 469
    if( (!sch0||count0 >= sPres->nsch[0]) && (!sch1 ||count1 >= sPres->nsch[1]) ) {
470
      eps->reason = EPS_CONVERGED_TOL;
471
    }else {
472
      if(!complIterating && eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
473
      if(complIterating){
474
        if(--iterCompl <= 0) eps->reason = EPS_DIVERGED_ITS;
2596 carcamgo 475
      }else if (k >= eps->nev) {
2459 carcamgo 476
        n0 = sPres->nsch[0]-count0;
477
        n1 = sPres->nsch[1]-count1;
2708 carcamgo 478
        if( sr->iterCompl>0 && ( (n0>0 && n0<= sr->nMAXCompl)||(n1>0&&n1<=sr->nMAXCompl) )){
2596 carcamgo 479
          /* Iterating for completion*/
2459 carcamgo 480
          complIterating = PETSC_TRUE;
481
          if(n0 >sr->nMAXCompl)sch0 = PETSC_FALSE;
482
          if(n1 >sr->nMAXCompl)sch1 = PETSC_FALSE;
483
          iterCompl = sr->iterCompl;
484
        }else eps->reason = EPS_CONVERGED_TOL;
485
      }      
486
    }
2404 jroman 487
    /* Update l */
2708 carcamgo 488
    if(eps->reason == EPS_CONVERGED_ITERATING )l = (eps->nconv+nv-k)/2;
489
    else l=eps->nconv+nv-k;
490
    if(breakdown)l=0;
2404 jroman 491
 
492
    if (eps->reason == EPS_CONVERGED_ITERATING) {
493
      if (breakdown) {
494
        /* Start a new Lanczos factorization */
2499 jroman 495
        ierr = PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%D norm=%G)\n",eps->its,beta);CHKERRQ(ierr);
2404 jroman 496
        ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
497
        if (breakdown) {
498
          eps->reason = EPS_DIVERGED_BREAKDOWN;
2499 jroman 499
          ierr = PetscInfo(eps,"Unable to generate more start vectors\n");CHKERRQ(ierr);
2404 jroman 500
        }
501
      } else {
502
        /* Prepare the Rayleigh quotient for restart */
503
        for (i=0;i<l;i++) {
504
          a[i] = PetscRealPart(eps->eigr[i+k]);
505
          b[i] = PetscRealPart(Q[nv-1+(i+k-eps->nconv)*nv]*beta);
506
        }
507
      }
508
    }
509
    /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
510
    ierr = SlepcUpdateVectors(nv,eps->V+eps->nconv,0,k+l-eps->nconv,Q,nv,PETSC_FALSE);CHKERRQ(ierr);
2708 carcamgo 511
    /* Purification */
512
    if(!sPres->expf){/* u not saved if breakdown */
513
      for(i=eps->nconv; i<k;i++){
514
        alpha = (Q[nv-1+(i-eps->nconv)*nv])/PetscRealPart(eps->eigr[i]);
515
        ierr = VecAXPY(eps->V[i], alpha, u);CHKERRQ(ierr);
516
      }
517
    }
2404 jroman 518
    /* Normalize u and append it to V */
2708 carcamgo 519
    if ( eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
2404 jroman 520
      ierr = VecAXPBY(eps->V[k+l],1.0/beta,0.0,u);CHKERRQ(ierr);
521
    }
2708 carcamgo 522
    /* Monitor */
2629 carcamgo 523
    if(eps->numbermonitors >0){
524
      aux = auxc = 0;
525
      for(i=0;i<nv+eps->nconv;i++){
526
        sr->back[i]=eps->eigr[i];
2599 carcamgo 527
      }
2629 carcamgo 528
      ierr = STBackTransform(eps->OP,nv+eps->nconv,sr->back,eps->eigi);CHKERRQ(ierr);
529
      for(i=0;i<nv+eps->nconv;i++){
2640 carcamgo 530
        lambda = PetscRealPart(sr->back[i]);
2629 carcamgo 531
        if( ((sr->dir)*(lambda - sPres->ext[0]) > 0)&& ((sr->dir)*(sPres->ext[1] - lambda) > 0)){
532
          sr->monit[sr->indexEig+aux]=eps->eigr[i];
533
          sr->errest[sr->indexEig+aux]=eps->errest[i];
534
          aux++;
535
          if(eps->errest[i] < eps->tol)auxc++;
536
        }
537
      }
538
      ierr = EPSMonitor(eps,eps->its,auxc+sr->indexEig,sr->monit,sr->eigi,sr->errest,sr->indexEig+aux);CHKERRQ(ierr);
2599 carcamgo 539
    }
2708 carcamgo 540
    conv = k - eps->nconv;
2404 jroman 541
    eps->nconv = k;
2708 carcamgo 542
 
543
    if(eps->reason != EPS_CONVERGED_ITERATING){
544
      /* Store approximated values for next shift */
545
      sr->nS = l;
546
      for (i=0;i<l;i++) {
547
        sr->S[i] = eps->eigr[i+k];/* Diagonal elements */
548
        sr->S[i+l] = Q[nv-1+(i+conv)*nv]*beta; /* Out of diagonal elements */
549
      }
550
      sr->beta = beta;
551
    }
2459 carcamgo 552
  }
2596 carcamgo 553
  /* Check for completion */
554
  for(i=0;i< eps->nconv; i++){
555
    if( (sr->dir)*PetscRealPart(eps->eigr[i])>0 )sPres->nconv[1]++;
556
    else sPres->nconv[0]++;
557
  }
2468 eromero 558
  sPres->comp[0] = (count0 >= sPres->nsch[0])?PETSC_TRUE:PETSC_FALSE;
559
  sPres->comp[1] = (count1 >= sPres->nsch[1])?PETSC_TRUE:PETSC_FALSE;
2701 carcamgo 560
  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");
561
 
2404 jroman 562
  ierr = PetscFree(Q);CHKERRQ(ierr);
563
  ierr = PetscFree(a);CHKERRQ(ierr);
564
  ierr = PetscFree(b);CHKERRQ(ierr);
565
  ierr = PetscFree(work);CHKERRQ(ierr);
566
  ierr = PetscFree(iwork);CHKERRQ(ierr);
567
  PetscFunctionReturn(0);
568
}
569
 
2459 carcamgo 570
/*
2596 carcamgo 571
  Obtains value of subsequent shift
2459 carcamgo 572
*/
573
#undef __FUNCT__
574
#define __FUNCT__ "EPSGetNewShiftValue"
2708 carcamgo 575
static PetscErrorCode EPSGetNewShiftValue(EPS eps,PetscInt side,PetscReal *newS)
576
{
2596 carcamgo 577
  PetscReal   lambda,d_prev;
2459 carcamgo 578
  PetscInt    i,idxP;
579
  SR          sr;
2666 eromero 580
  shift       sPres,s;
2459 carcamgo 581
 
582
  PetscFunctionBegin;  
583
  sr = (SR)eps->data;
584
  sPres = sr->sPres;
2464 carcamgo 585
  if( sPres->neighb[side]){
2596 carcamgo 586
  /* Completing a previous interval */
587
    if(!sPres->neighb[side]->neighb[side] && sPres->neighb[side]->nconv[side]==0){ /* One of the ends might be too far from eigenvalues */
588
      if(side) *newS = (sPres->value + PetscRealPart(sr->eig[sr->perm[sr->indexEig-1]]))/2;
589
      else *newS = (sPres->value + PetscRealPart(sr->eig[sr->perm[0]]))/2;
590
    }else *newS=(sPres->value + sPres->neighb[side]->value)/2;
591
  }else{ /* (Only for side=1). Creating a new interval. */
592
    if(sPres->neigs==0){/* No value has been accepted*/
2464 carcamgo 593
      if(sPres->neighb[0]){
2596 carcamgo 594
        /* Multiplying by 10 the previous distance */
2465 jroman 595
        *newS = sPres->value + 10*(sr->dir)*PetscAbsReal(sPres->value - sPres->neighb[0]->value);
2596 carcamgo 596
        sr->nleap++;
597
        /* Stops when the interval is open and no values are found in the last 5 shifts (there might be infinite eigenvalues) */
598
        if( !sr->hasEnd && sr->nleap > 5)SETERRQ(((PetscObject)eps)->comm,1,"Unable to compute the wanted eigenvalues with open interval");          
599
      }else {/* First shift */
2459 carcamgo 600
        if(eps->nconv != 0){
2596 carcamgo 601
           /* Unaccepted values give information for next shift */
602
           idxP=0;/* Number of values left from shift */
2459 carcamgo 603
           for(i=0;i<eps->nconv;i++){
604
             lambda = PetscRealPart(eps->eigr[i]);
605
             if( (sr->dir)*(lambda - sPres->value) <0)idxP++;
606
             else break;
607
           }
2596 carcamgo 608
           /* Avoiding subtraction of eigenvalues (might be the same).*/
2459 carcamgo 609
           if(idxP>0){
2465 jroman 610
             d_prev = PetscAbsReal(sPres->value - PetscRealPart(eps->eigr[0]))/(idxP+0.3);
2459 carcamgo 611
           }else {
2465 jroman 612
             d_prev = PetscAbsReal(sPres->value - PetscRealPart(eps->eigr[eps->nconv-1]))/(eps->nconv+0.3);
2459 carcamgo 613
           }
614
           *newS = sPres->value + ((sr->dir)*d_prev*eps->nev)/2;
2596 carcamgo 615
        }else{/* No values found, no information for next shift */
616
          SETERRQ(((PetscObject)eps)->comm,1,"First shift renders no information");
2459 carcamgo 617
        }
618
      }
2596 carcamgo 619
    }else{/* Accepted values found */
620
      sr->nleap = 0;
621
      /* Average distance of values in previous subinterval */
2666 eromero 622
      s = sPres->neighb[0];
2464 carcamgo 623
      while(s && PetscAbs(s->inertia - sPres->inertia)==0){
2596 carcamgo 624
        s = s->neighb[0];/* Looking for previous shifts with eigenvalues within */
2459 carcamgo 625
      }
2464 carcamgo 626
      if(s){
2465 jroman 627
        d_prev = PetscAbsReal( (sPres->value - s->value)/(sPres->inertia - s->inertia));
2596 carcamgo 628
      }else{/* First shift. Average distance obtained with values in this shift */
629
        /* first shift might be too far from first wanted eigenvalue (no values found outside the interval)*/
2609 carcamgo 630
        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 631
          d_prev =  PetscAbsReal( (PetscRealPart(sr->eig[sr->indexEig-1]) - PetscRealPart(sr->eig[0])))/(sPres->neigs+0.3);
632
        }else{
633
          d_prev = PetscAbsReal( PetscRealPart(sr->eig[sr->indexEig-1]) - sPres->value)/(sPres->neigs+0.3);          
634
        }
2459 carcamgo 635
      }
2596 carcamgo 636
      /* Average distance is used for next shift by adding it to value on the right or to shift */
2465 jroman 637
      if( (sr->dir)*(PetscRealPart(sr->eig[sPres->index + sPres->neigs -1]) - sPres->value) >0){
638
        *newS = PetscRealPart(sr->eig[sPres->index + sPres->neigs -1])+ ((sr->dir)*d_prev*(eps->nev))/2;  
2596 carcamgo 639
      }else{/* Last accepted value is on the left of shift. Adding to shift */
2459 carcamgo 640
        *newS = sPres->value + ((sr->dir)*d_prev*(eps->nev))/2;
641
      }
642
    }
2596 carcamgo 643
    /* End of interval can not be surpassed */
644
    if((sr->dir)*( sr->int1 - *newS) < 0) *newS = sr->int1;
2609 carcamgo 645
  }/* of neighb[side]==null */
2459 carcamgo 646
  PetscFunctionReturn(0);
647
}
648
 
649
/*
2596 carcamgo 650
  Function for sorting an array of real values
2459 carcamgo 651
*/
652
#undef __FUNCT__
653
#define __FUNCT__ "sortRealEigenvalues"
654
static PetscErrorCode sortRealEigenvalues(PetscScalar *r,PetscInt *perm,PetscInt nr,PetscBool prev,PetscInt dir)
655
{
656
  PetscReal      re;
657
  PetscInt       i,j,tmp;
658
 
659
  PetscFunctionBegin;
2464 carcamgo 660
  if(!prev) for (i=0; i < nr; i++) { perm[i] = i; }
2596 carcamgo 661
  /* Insertion sort */
2459 carcamgo 662
  for (i=1; i < nr; i++) {
663
    re = PetscRealPart(r[perm[i]]);
664
    j = i-1;
665
    while ( j>=0 && dir*(re - PetscRealPart(r[perm[j]])) <= 0 ) {
666
      tmp = perm[j]; perm[j] = perm[j+1]; perm[j+1] = tmp; j--;
667
    }
668
  }
669
  PetscFunctionReturn(0);
670
}
671
 
672
/* Stores the pairs obtained since the last shift in the global arrays */
673
#undef __FUNCT__
674
#define __FUNCT__ "EPSStoreEigenpairs"
675
PetscErrorCode EPSStoreEigenpairs(EPS eps)
676
{
677
  PetscErrorCode ierr;
2596 carcamgo 678
  PetscReal      lambda,err,norm;
2459 carcamgo 679
  PetscInt       i,count;
2641 jroman 680
  PetscBool      iscayley;
2459 carcamgo 681
  SR             sr;
682
  shift          sPres;
683
 
684
  PetscFunctionBegin;
685
  sr = (SR)(eps->data);
686
  sPres = sr->sPres;
687
  sPres->index = sr->indexEig;
688
  count = sr->indexEig;
2708 carcamgo 689
  /* Back-transform */
2629 carcamgo 690
  ierr = EPSBackTransform_Default(eps);CHKERRQ(ierr);
691
  ierr = PetscTypeCompare((PetscObject)eps->OP,STCAYLEY,&iscayley);CHKERRQ(ierr);
2596 carcamgo 692
  /* Sort eigenvalues */
2459 carcamgo 693
  ierr = sortRealEigenvalues(eps->eigr,eps->perm,eps->nconv,PETSC_FALSE,sr->dir);
2596 carcamgo 694
  /* Values stored in global array */
2459 carcamgo 695
  for( i=0; i < eps->nconv ;i++ ){
696
    lambda = PetscRealPart(eps->eigr[eps->perm[i]]);
2596 carcamgo 697
    err = eps->errest[eps->perm[i]];
2708 carcamgo 698
 
2596 carcamgo 699
    if(  (sr->dir)*(lambda - sPres->ext[0]) > 0 && (sr->dir)*(sPres->ext[1] - lambda) > 0  ){/* Valid value */
700
      if(count>=sr->numEigs){/* Error found */
2629 carcamgo 701
         SETERRQ(((PetscObject)eps)->comm,1,"Unexpected error in Spectrum Slicing!");
702
      }
2459 carcamgo 703
      sr->eig[count] = lambda;
2596 carcamgo 704
      sr->errest[count] = err;
2708 carcamgo 705
      /* Unlikely explicit purification */
706
      if (sPres->expf && eps->isgeneralized && !iscayley){
2609 carcamgo 707
        ierr = STApply(eps->OP,eps->V[eps->perm[i]],sr->V[count]);CHKERRQ(ierr);
708
        ierr = IPNorm(eps->ip,sr->V[count],&norm);CHKERRQ(ierr);
709
        ierr = VecScale(sr->V[count],1.0/norm);CHKERRQ(ierr);
710
      }else{
711
        ierr = VecCopy(eps->V[eps->perm[i]], sr->V[count]);CHKERRQ(ierr);
712
      }
2459 carcamgo 713
      count++;
2596 carcamgo 714
    }
2459 carcamgo 715
  }
716
  sPres->neigs = count - sr->indexEig;
717
  sr->indexEig = count;
2596 carcamgo 718
  /* Global ordering array updating */
2459 carcamgo 719
  ierr = sortRealEigenvalues(sr->eig,sr->perm,count,PETSC_TRUE,sr->dir);CHKERRQ(ierr);
720
  PetscFunctionReturn(0);
721
}
722
 
723
#undef __FUNCT__
724
#define __FUNCT__ "EPSLookForDeflation"
725
PetscErrorCode EPSLookForDeflation(EPS eps)
726
{
2596 carcamgo 727
  PetscReal       val;
2459 carcamgo 728
  PetscInt        i,count0=0,count1=0;
729
  shift           sPres;
2596 carcamgo 730
  PetscInt        ini,fin,k,idx0,idx1;
2459 carcamgo 731
  SR              sr;
732
 
733
  PetscFunctionBegin;
734
  sr = (SR)(eps->data);
735
  sPres = sr->sPres;
736
 
2464 carcamgo 737
  if(sPres->neighb[0]) ini = (sr->dir)*(sPres->neighb[0]->inertia - sr->inertia0);
2459 carcamgo 738
  else ini = 0;
739
  fin = sr->indexEig;
2596 carcamgo 740
  /* Selection of ends for searching new values */
741
  if(!sPres->neighb[0]) sPres->ext[0] = sr->int0;/* First shift */
2459 carcamgo 742
  else sPres->ext[0] = sPres->neighb[0]->value;
2464 carcamgo 743
  if(!sPres->neighb[1]) {
2459 carcamgo 744
    if(sr->hasEnd) sPres->ext[1] = sr->int1;
745
    else sPres->ext[1] = (sr->dir > 0)?PETSC_MAX_REAL:PETSC_MIN_REAL;
746
  }else sPres->ext[1] = sPres->neighb[1]->value;
2596 carcamgo 747
  /* Selection of values between right and left ends */
2459 carcamgo 748
  for(i=ini;i<fin;i++){
749
    val=PetscRealPart(sr->eig[sr->perm[i]]);
2596 carcamgo 750
    /* Values to the right of left shift */
2459 carcamgo 751
    if( (sr->dir)*(val - sPres->ext[1]) < 0 ){
752
      if((sr->dir)*(val - sPres->value) < 0)count0++;
753
      else count1++;
754
    }else break;
755
  }
2596 carcamgo 756
  /* The number of values on each side are found */
2629 carcamgo 757
  if(sPres->neighb[0]){
2459 carcamgo 758
     sPres->nsch[0] = (sr->dir)*(sPres->inertia - sPres->neighb[0]->inertia)-count0;
2629 carcamgo 759
     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");
760
  }else sPres->nsch[0] = 0;
2459 carcamgo 761
 
2629 carcamgo 762
  if(sPres->neighb[1]){
2459 carcamgo 763
    sPres->nsch[1] = (sr->dir)*(sPres->neighb[1]->inertia - sPres->inertia) - count1;
2629 carcamgo 764
    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");
765
  }else sPres->nsch[1] = (sr->dir)*(sr->inertia1 - sPres->inertia);
2708 carcamgo 766
 
2596 carcamgo 767
  /* Completing vector of indexes for deflation */
768
  idx0 = ini;
769
  idx1 = ini+count0+count1;
2459 carcamgo 770
  k=0;
771
  for(i=idx0;i<idx1;i++)sr->idxDef[k++]=sr->perm[i];
772
  for(i=0;i<k;i++)sr->VDef[i]=sr->V[sr->idxDef[i]];
773
  eps->DS = sr->VDef;
774
  eps->nds = k;
775
  PetscFunctionReturn(0);
776
}
777
 
778
#undef __FUNCT__
779
#define __FUNCT__ "EPSSolve_KrylovSchur_Slice"
780
PetscErrorCode EPSSolve_KrylovSchur_Slice(EPS eps)
781
{
782
  PetscErrorCode ierr;
2708 carcamgo 783
  PetscInt       i,lds;
2459 carcamgo 784
  PetscReal      newS;
785
  KSP            ksp;
786
  PC             pc;
2596 carcamgo 787
  Mat            F;  
788
  PetscReal      *errest_left;
789
  Vec            t;
2459 carcamgo 790
  SR             sr;
2713 jroman 791
  shift          s;
2459 carcamgo 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 */
2713 jroman 919
  s = sr->s0;
2464 carcamgo 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
}