Subversion Repositories slepc-dev

Rev

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
 
2741 jroman 13
       [2] C. Campos and J. E. Roman, "Spectrum slicing strategies based on
14
           restarted Lanczos methods", Numer. Algor., 2012.
15
           DOI: 10.1007/s11075-012-9564-z
2404 jroman 16
 
17
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
18
   SLEPc - Scalable Library for Eigenvalue Problem Computations
2575 eromero 19
   Copyright (c) 2002-2011, Universitat Politecnica de Valencia, Spain
2404 jroman 20
 
21
   This file is part of SLEPc.
2459 carcamgo 22
 
2404 jroman 23
   SLEPc is free software: you can redistribute it and/or modify it under  the
24
   terms of version 3 of the GNU Lesser General Public License as published by
25
   the Free Software Foundation.
26
 
27
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
28
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
29
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
30
   more details.
31
 
32
   You  should have received a copy of the GNU Lesser General  Public  License
33
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
34
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
35
*/
36
 
2729 jroman 37
#include <slepc-private/epsimpl.h>                /*I "slepceps.h" I*/
2404 jroman 38
#include <slepcblaslapack.h>
2805 carcamgo 39
#include <slepc-private/psimpl.h>
2404 jroman 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;
2805 carcamgo 131
  PetscInt         iner,dir,i,k,ld;
132
  PetscScalar      *A;
2459 carcamgo 133
  Mat              F;
134
  PC               pc;
135
  KSP              ksp;
136
  SR               sr;
137
 
138
  PetscFunctionBegin;  
139
  sr = (SR)(eps->data);
140
  if(sr->nPend > 0){
2708 carcamgo 141
    sr->sPrev = sr->sPres;
2459 carcamgo 142
    sr->sPres = sr->pending[--sr->nPend];
143
    ierr = STSetShift(eps->OP, sr->sPres->value);CHKERRQ(ierr);
144
    ierr = STGetKSP(eps->OP, &ksp);CHKERRQ(ierr);
145
    ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
146
    ierr = PCFactorGetMatrix(pc,&F);CHKERRQ(ierr);
147
    ierr = MatGetInertia(F,&iner,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
148
    sr->sPres->inertia = iner;
149
    eps->target = sr->sPres->value;
150
    eps->reason = EPS_CONVERGED_ITERATING;
2596 carcamgo 151
    eps->its = 0;
2708 carcamgo 152
    sr->sPres->expf = PETSC_FALSE;
153
    /* For rational Krylov */
154
    if(sr->nS >0 && (sr->sPrev == sr->sPres->neighb[0] || sr->sPrev == sr->sPres->neighb[1]) ){
2805 carcamgo 155
      ierr = PSGetLeadingDimension(eps->ps,&ld);CHKERRQ(ierr);
2708 carcamgo 156
      dir = (sr->sPres->neighb[0] == sr->sPrev)?1:-1;
157
      dir*=sr->dir;
158
      k = 0;
159
      for(i=0;i<sr->nS;i++){
2716 jroman 160
        if(dir*PetscRealPart(sr->S[i])>0.0){
2708 carcamgo 161
          sr->S[k] = sr->S[i];
162
          sr->S[sr->nS+k] = sr->S[sr->nS+i];
163
          ierr = VecCopy(eps->V[eps->nconv+i],eps->V[k++]);CHKERRQ(ierr);
164
          if(k>=sr->nS/2)break;
165
        }
166
      }
2805 carcamgo 167
      /* Copy to PS */
168
      ierr = PSGetArray(eps->ps,PS_MAT_A,&A);CHKERRQ(ierr);
169
      ierr = PetscMemzero(A,ld*ld*sizeof(PetscScalar));
170
      for(i=0;i<k;i++){
171
        A[i*(1+ld)] = sr->S[i];
172
        A[k+i*ld] = sr->S[sr->nS+i];
173
      }
2708 carcamgo 174
      sr->nS = k;
2805 carcamgo 175
      ierr = PSRestoreArray(eps->ps,PS_MAT_A,&A);CHKERRQ(ierr);
176
      ierr = PSSetDimensions(eps->ps,ld,0,k);CHKERRQ(ierr);
2708 carcamgo 177
      /* Normalize u and append it to V */      
178
      ierr = VecAXPBY(eps->V[sr->nS],1.0/sr->beta,0.0,eps->work[0]);CHKERRQ(ierr);
179
    }
180
    eps->nconv = 0;
181
  }else sr->sPres = PETSC_NULL;
182
  PetscFunctionReturn(0);
2459 carcamgo 183
}
2708 carcamgo 184
 
2459 carcamgo 185
/*
2464 carcamgo 186
   Symmetric KrylovSchur adapted to spectrum slicing:
2596 carcamgo 187
   Allows searching an specific amount of eigenvalues in the subintervals left and right.
188
   Returns whether the search has succeeded
2459 carcamgo 189
*/
190
#undef __FUNCT__
191
#define __FUNCT__ "EPSKrylovSchur_Slice"
192
static PetscErrorCode EPSKrylovSchur_Slice(EPS eps)
193
{
2404 jroman 194
  PetscErrorCode ierr;
2805 carcamgo 195
  PetscInt       i,conv,k,l,ld,nv,m,*iwork,p,j;
2404 jroman 196
  Vec            u=eps->work[0];
2805 carcamgo 197
  PetscScalar    *Q,*A,nu,rtmp,alpha;
198
  PetscReal      *a,*b,beta;
2404 jroman 199
  PetscBool      breakdown;
2596 carcamgo 200
  PetscInt       count0,count1;
2709 carcamgo 201
  PetscReal      lambda;
2459 carcamgo 202
  shift          sPres;
2708 carcamgo 203
  PetscBool      complIterating,iscayley;
204
  PetscBool      sch0,sch1;
2599 carcamgo 205
  PetscInt       iterCompl=0,n0,n1,aux,auxc;
2459 carcamgo 206
  SR             sr;
207
 
2404 jroman 208
  PetscFunctionBegin;
2596 carcamgo 209
  /* Spectrum slicing data */
2459 carcamgo 210
  sr = (SR)eps->data;
211
  sPres = sr->sPres;
212
  complIterating =PETSC_FALSE;
213
  sch1 = sch0 = PETSC_TRUE;
2805 carcamgo 214
  ierr = PSGetLeadingDimension(eps->ps,&ld);CHKERRQ(ierr);
215
  ierr = PetscMalloc(2*ld*sizeof(PetscInt),&iwork);CHKERRQ(ierr);
2596 carcamgo 216
  count0=0;count1=0; /* Found on both sides */
2708 carcamgo 217
  /* filling in values for the monitor */
2633 carcamgo 218
  if(eps->numbermonitors >0){
219
    ierr = PetscTypeCompare((PetscObject)eps->OP,STCAYLEY,&iscayley);CHKERRQ(ierr);
220
    if(iscayley){
221
      ierr = STCayleyGetAntishift(eps->OP,&nu);CHKERRQ(ierr);    
222
      for(i=0;i<sr->indexEig;i++){
223
        sr->monit[i]=(nu + sr->eig[i])/(sr->eig[i] - sPres->value);
224
      }
225
    }else{
226
      for(i=0;i<sr->indexEig;i++){
227
        sr->monit[i]=1.0/(sr->eig[i] - sPres->value);
228
      }
2629 carcamgo 229
    }
230
  }
2708 carcamgo 231
  if(sr->nS > 0 && (sPres->neighb[0] == sr->sPrev || sPres->neighb[1] == sr->sPrev) ){
232
    /* Rational Krylov */
2814 jroman 233
    ierr = PSTranslateRKS(eps->ps,sr->sPrev->value-sPres->value);CHKERRQ(ierr);
2805 carcamgo 234
    ierr = PSGetArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
235
    ierr = PSGetDimensions(eps->ps,PETSC_NULL,PETSC_NULL,&l);CHKERRQ(ierr);
236
    ierr = SlepcUpdateVectors(l+1,eps->V,0,l+1,Q,ld,PETSC_FALSE);CHKERRQ(ierr);
237
    ierr = PSRestoreArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
2708 carcamgo 238
  }else{
239
    /* Get the starting Lanczos vector */
240
    ierr = EPSGetStartVector(eps,0,eps->V[0],PETSC_NULL);CHKERRQ(ierr);
241
    l = 0;
242
  }
2404 jroman 243
  /* Restart loop */
244
  while (eps->reason == EPS_CONVERGED_ITERATING) {
2596 carcamgo 245
    eps->its++; sr->itsKs++;
2404 jroman 246
    /* Compute an nv-step Lanczos factorization */
247
    m = PetscMin(eps->nconv+eps->mpd,eps->ncv);
2805 carcamgo 248
    ierr = PSGetArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
249
    b = a + ld;
2404 jroman 250
    ierr = EPSFullLanczos(eps,a+l,b+l,eps->V,eps->nconv+l,&m,u,&breakdown);CHKERRQ(ierr);
2708 carcamgo 251
    if(breakdown){/* explicit purification*/
252
      sPres->expf = PETSC_TRUE;    
253
    }
2404 jroman 254
    nv = m - eps->nconv;
255
    beta = b[nv-1];
2805 carcamgo 256
    ierr = PSRestoreArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
257
    ierr = PSSetDimensions(eps->ps,nv,0,l);CHKERRQ(ierr);
258
    if (l==0) {
259
      ierr = PSSetState(eps->ps,PS_STATE_INTERMEDIATE);CHKERRQ(ierr);
260
    } else {
261
      ierr = PSSetState(eps->ps,PS_STATE_RAW);CHKERRQ(ierr);
262
    }
263
 
2459 carcamgo 264
    /* Solve projected problem and compute residual norm estimates */
2708 carcamgo 265
    if(eps->its == 1 && l > 0){/* After rational update */
2805 carcamgo 266
      ierr = PSGetArray(eps->ps,PS_MAT_A,&A);CHKERRQ(ierr);
267
      ierr = PSGetArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
268
      b = a + ld;
269
      A[l*ld+l-1] = A[(l-1)*ld+l];
270
      A[l*ld+l] = a[l];
271
      for(j=l+1; j< nv; j++){
272
        A[j*ld+j] = a[j];
273
        A[j*ld+j-1] = b[j-1] ;
274
        A[(j-1)*ld+j] = b[j-1];
275
      }
276
      ierr = PSRestoreArray(eps->ps,PS_MAT_A,&A);CHKERRQ(ierr);
277
      ierr = PSRestoreArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
278
      ierr = PSSolve(eps->ps,eps->eigr+eps->nconv,PETSC_NULL);CHKERRQ(ierr);
2708 carcamgo 279
    }else{/* Restart */
2805 carcamgo 280
      ierr = PSSolve(eps->ps,eps->eigr+eps->nconv,PETSC_NULL);CHKERRQ(ierr);
2708 carcamgo 281
    }
2805 carcamgo 282
    ierr = PSSort(eps->ps,eps->eigr+eps->nconv,PETSC_NULL,eps->which_func,eps->which_ctx);CHKERRQ(ierr);
2596 carcamgo 283
    /* Residual */
2805 carcamgo 284
    ierr = PSGetArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
2818 jroman 285
    ierr = EPSKrylovConvergence(eps,PETSC_TRUE,eps->nconv,nv,eps->V+eps->nconv,nv,beta,1.0,&k);CHKERRQ(ierr);
2596 carcamgo 286
    /* Check convergence */
2805 carcamgo 287
    ierr = PSGetArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
288
    b = a + ld;
2596 carcamgo 289
    conv=k=j=0;
290
    for(i=0;i<nv;i++)if(eps->errest[eps->nconv+i] < eps->tol)conv++;
291
    for(i=0;i<nv;i++){
292
      if(eps->errest[eps->nconv+i] < eps->tol){
293
        iwork[j++]=i;
294
      }else iwork[conv+k++]=i;
2459 carcamgo 295
    }
2596 carcamgo 296
    for(i=0;i<nv;i++){
2599 carcamgo 297
      a[i]=PetscRealPart(eps->eigr[eps->nconv+i]);
298
      b[i]=eps->errest[eps->nconv+i];
299
    }
300
    for(i=0;i<nv;i++){
2596 carcamgo 301
      eps->eigr[eps->nconv+i] = a[iwork[i]];
2599 carcamgo 302
      eps->errest[eps->nconv+i] = b[iwork[i]];
2459 carcamgo 303
    }
2596 carcamgo 304
    for( i=0;i<nv;i++){
305
      p=iwork[i];
2805 carcamgo 306
      if(p!=i){
307
        j=i+1;
308
        while(iwork[j]!=i)j++;
309
        iwork[j]=p;iwork[i]=i;
310
        for(k=0;k<nv;k++){
311
          rtmp=Q[k+p*ld];Q[k+p*ld]=Q[k+i*ld];Q[k+i*ld]=rtmp;
312
        }
313
      }
314
    }
315
    k=eps->nconv+conv;
316
    ierr = PSRestoreArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
317
    ierr = PSRestoreArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
318
 
2459 carcamgo 319
    /* Checking values obtained for completing */
2629 carcamgo 320
    for(i=0;i<k;i++){
321
      sr->back[i]=eps->eigr[i];
322
    }
323
    ierr = STBackTransform(eps->OP,k,sr->back,eps->eigi);CHKERRQ(ierr);
2459 carcamgo 324
    count0=count1=0;
2805 carcamgo 325
    for(i=0;i<k;i++){
2640 carcamgo 326
      lambda = PetscRealPart(sr->back[i]);
2709 carcamgo 327
      if( ((sr->dir)*(sPres->value - lambda) > 0) && ((sr->dir)*(lambda - sPres->ext[0]) > 0))count0++;
328
      if( ((sr->dir)*(lambda - sPres->value) > 0) && ((sr->dir)*(sPres->ext[1] - lambda) > 0))count1++;
2459 carcamgo 329
    }
2404 jroman 330
 
2596 carcamgo 331
    /* Checks completion */
2459 carcamgo 332
    if( (!sch0||count0 >= sPres->nsch[0]) && (!sch1 ||count1 >= sPres->nsch[1]) ) {
333
      eps->reason = EPS_CONVERGED_TOL;
334
    }else {
335
      if(!complIterating && eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
336
      if(complIterating){
337
        if(--iterCompl <= 0) eps->reason = EPS_DIVERGED_ITS;
2596 carcamgo 338
      }else if (k >= eps->nev) {
2459 carcamgo 339
        n0 = sPres->nsch[0]-count0;
340
        n1 = sPres->nsch[1]-count1;
2708 carcamgo 341
        if( sr->iterCompl>0 && ( (n0>0 && n0<= sr->nMAXCompl)||(n1>0&&n1<=sr->nMAXCompl) )){
2596 carcamgo 342
          /* Iterating for completion*/
2459 carcamgo 343
          complIterating = PETSC_TRUE;
344
          if(n0 >sr->nMAXCompl)sch0 = PETSC_FALSE;
345
          if(n1 >sr->nMAXCompl)sch1 = PETSC_FALSE;
346
          iterCompl = sr->iterCompl;
347
        }else eps->reason = EPS_CONVERGED_TOL;
348
      }      
349
    }
2404 jroman 350
    /* Update l */
2708 carcamgo 351
    if(eps->reason == EPS_CONVERGED_ITERATING )l = (eps->nconv+nv-k)/2;
352
    else l=eps->nconv+nv-k;
353
    if(breakdown)l=0;
2404 jroman 354
 
355
    if (eps->reason == EPS_CONVERGED_ITERATING) {
356
      if (breakdown) {
357
        /* Start a new Lanczos factorization */
2499 jroman 358
        ierr = PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%D norm=%G)\n",eps->its,beta);CHKERRQ(ierr);
2404 jroman 359
        ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
360
        if (breakdown) {
361
          eps->reason = EPS_DIVERGED_BREAKDOWN;
2499 jroman 362
          ierr = PetscInfo(eps,"Unable to generate more start vectors\n");CHKERRQ(ierr);
2404 jroman 363
        }
364
      } else {
365
        /* Prepare the Rayleigh quotient for restart */
2805 carcamgo 366
        ierr = PSGetArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
367
        ierr = PSGetArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
368
        b = a + ld;
2404 jroman 369
        for (i=0;i<l;i++) {
370
          a[i] = PetscRealPart(eps->eigr[i+k]);
2805 carcamgo 371
          b[i] = PetscRealPart(Q[nv-1+(i+k-eps->nconv)*ld]*beta);
2404 jroman 372
        }
2805 carcamgo 373
        ierr = PSRestoreArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
374
        ierr = PSRestoreArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
2404 jroman 375
      }
376
    }
377
    /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
2805 carcamgo 378
    ierr = PSGetArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
379
    ierr = SlepcUpdateVectors(nv,eps->V+eps->nconv,0,k+l-eps->nconv,Q,ld,PETSC_FALSE);CHKERRQ(ierr);
2708 carcamgo 380
    /* Purification */
381
    if(!sPres->expf){/* u not saved if breakdown */
382
      for(i=eps->nconv; i<k;i++){
2805 carcamgo 383
        alpha = (Q[nv-1+(i-eps->nconv)*ld])/PetscRealPart(eps->eigr[i]);
2708 carcamgo 384
        ierr = VecAXPY(eps->V[i], alpha, u);CHKERRQ(ierr);
385
      }
386
    }
2805 carcamgo 387
    ierr = PSRestoreArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
2404 jroman 388
    /* Normalize u and append it to V */
2708 carcamgo 389
    if ( eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
2404 jroman 390
      ierr = VecAXPBY(eps->V[k+l],1.0/beta,0.0,u);CHKERRQ(ierr);
391
    }
2708 carcamgo 392
    /* Monitor */
2629 carcamgo 393
    if(eps->numbermonitors >0){
394
      aux = auxc = 0;
395
      for(i=0;i<nv+eps->nconv;i++){
396
        sr->back[i]=eps->eigr[i];
2599 carcamgo 397
      }
2629 carcamgo 398
      ierr = STBackTransform(eps->OP,nv+eps->nconv,sr->back,eps->eigi);CHKERRQ(ierr);
399
      for(i=0;i<nv+eps->nconv;i++){
2640 carcamgo 400
        lambda = PetscRealPart(sr->back[i]);
2629 carcamgo 401
        if( ((sr->dir)*(lambda - sPres->ext[0]) > 0)&& ((sr->dir)*(sPres->ext[1] - lambda) > 0)){
402
          sr->monit[sr->indexEig+aux]=eps->eigr[i];
403
          sr->errest[sr->indexEig+aux]=eps->errest[i];
404
          aux++;
405
          if(eps->errest[i] < eps->tol)auxc++;
406
        }
407
      }
408
      ierr = EPSMonitor(eps,eps->its,auxc+sr->indexEig,sr->monit,sr->eigi,sr->errest,sr->indexEig+aux);CHKERRQ(ierr);
2599 carcamgo 409
    }
2708 carcamgo 410
    conv = k - eps->nconv;
2404 jroman 411
    eps->nconv = k;
2708 carcamgo 412
    if(eps->reason != EPS_CONVERGED_ITERATING){
413
      /* Store approximated values for next shift */
2805 carcamgo 414
      ierr = PSGetArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
2708 carcamgo 415
      sr->nS = l;
416
      for (i=0;i<l;i++) {
417
        sr->S[i] = eps->eigr[i+k];/* Diagonal elements */
2805 carcamgo 418
        sr->S[i+l] = Q[nv-1+(i+conv)*ld]*beta; /* Out of diagonal elements */
2708 carcamgo 419
      }
420
      sr->beta = beta;
2805 carcamgo 421
      ierr = PSRestoreArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
2708 carcamgo 422
    }
2459 carcamgo 423
  }
2596 carcamgo 424
  /* Check for completion */
425
  for(i=0;i< eps->nconv; i++){
426
    if( (sr->dir)*PetscRealPart(eps->eigr[i])>0 )sPres->nconv[1]++;
427
    else sPres->nconv[0]++;
428
  }
2468 eromero 429
  sPres->comp[0] = (count0 >= sPres->nsch[0])?PETSC_TRUE:PETSC_FALSE;
430
  sPres->comp[1] = (count1 >= sPres->nsch[1])?PETSC_TRUE:PETSC_FALSE;
2701 carcamgo 431
  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");
2805 carcamgo 432
  ierr = PetscFree(iwork);CHKERRQ(ierr);  
2404 jroman 433
  PetscFunctionReturn(0);
434
}
435
 
2459 carcamgo 436
/*
2596 carcamgo 437
  Obtains value of subsequent shift
2459 carcamgo 438
*/
439
#undef __FUNCT__
440
#define __FUNCT__ "EPSGetNewShiftValue"
2708 carcamgo 441
static PetscErrorCode EPSGetNewShiftValue(EPS eps,PetscInt side,PetscReal *newS)
442
{
2596 carcamgo 443
  PetscReal   lambda,d_prev;
2459 carcamgo 444
  PetscInt    i,idxP;
445
  SR          sr;
2666 eromero 446
  shift       sPres,s;
2459 carcamgo 447
 
448
  PetscFunctionBegin;  
449
  sr = (SR)eps->data;
450
  sPres = sr->sPres;
2464 carcamgo 451
  if( sPres->neighb[side]){
2596 carcamgo 452
  /* Completing a previous interval */
453
    if(!sPres->neighb[side]->neighb[side] && sPres->neighb[side]->nconv[side]==0){ /* One of the ends might be too far from eigenvalues */
454
      if(side) *newS = (sPres->value + PetscRealPart(sr->eig[sr->perm[sr->indexEig-1]]))/2;
455
      else *newS = (sPres->value + PetscRealPart(sr->eig[sr->perm[0]]))/2;
456
    }else *newS=(sPres->value + sPres->neighb[side]->value)/2;
457
  }else{ /* (Only for side=1). Creating a new interval. */
458
    if(sPres->neigs==0){/* No value has been accepted*/
2464 carcamgo 459
      if(sPres->neighb[0]){
2596 carcamgo 460
        /* Multiplying by 10 the previous distance */
2465 jroman 461
        *newS = sPres->value + 10*(sr->dir)*PetscAbsReal(sPres->value - sPres->neighb[0]->value);
2596 carcamgo 462
        sr->nleap++;
463
        /* Stops when the interval is open and no values are found in the last 5 shifts (there might be infinite eigenvalues) */
464
        if( !sr->hasEnd && sr->nleap > 5)SETERRQ(((PetscObject)eps)->comm,1,"Unable to compute the wanted eigenvalues with open interval");          
465
      }else {/* First shift */
2459 carcamgo 466
        if(eps->nconv != 0){
2596 carcamgo 467
           /* Unaccepted values give information for next shift */
468
           idxP=0;/* Number of values left from shift */
2459 carcamgo 469
           for(i=0;i<eps->nconv;i++){
470
             lambda = PetscRealPart(eps->eigr[i]);
471
             if( (sr->dir)*(lambda - sPres->value) <0)idxP++;
472
             else break;
473
           }
2596 carcamgo 474
           /* Avoiding subtraction of eigenvalues (might be the same).*/
2459 carcamgo 475
           if(idxP>0){
2465 jroman 476
             d_prev = PetscAbsReal(sPres->value - PetscRealPart(eps->eigr[0]))/(idxP+0.3);
2459 carcamgo 477
           }else {
2465 jroman 478
             d_prev = PetscAbsReal(sPres->value - PetscRealPart(eps->eigr[eps->nconv-1]))/(eps->nconv+0.3);
2459 carcamgo 479
           }
480
           *newS = sPres->value + ((sr->dir)*d_prev*eps->nev)/2;
2596 carcamgo 481
        }else{/* No values found, no information for next shift */
482
          SETERRQ(((PetscObject)eps)->comm,1,"First shift renders no information");
2459 carcamgo 483
        }
484
      }
2596 carcamgo 485
    }else{/* Accepted values found */
486
      sr->nleap = 0;
487
      /* Average distance of values in previous subinterval */
2666 eromero 488
      s = sPres->neighb[0];
2464 carcamgo 489
      while(s && PetscAbs(s->inertia - sPres->inertia)==0){
2596 carcamgo 490
        s = s->neighb[0];/* Looking for previous shifts with eigenvalues within */
2459 carcamgo 491
      }
2464 carcamgo 492
      if(s){
2465 jroman 493
        d_prev = PetscAbsReal( (sPres->value - s->value)/(sPres->inertia - s->inertia));
2596 carcamgo 494
      }else{/* First shift. Average distance obtained with values in this shift */
495
        /* first shift might be too far from first wanted eigenvalue (no values found outside the interval)*/
2609 carcamgo 496
        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 497
          d_prev =  PetscAbsReal( (PetscRealPart(sr->eig[sr->indexEig-1]) - PetscRealPart(sr->eig[0])))/(sPres->neigs+0.3);
498
        }else{
499
          d_prev = PetscAbsReal( PetscRealPart(sr->eig[sr->indexEig-1]) - sPres->value)/(sPres->neigs+0.3);          
500
        }
2459 carcamgo 501
      }
2596 carcamgo 502
      /* Average distance is used for next shift by adding it to value on the right or to shift */
2465 jroman 503
      if( (sr->dir)*(PetscRealPart(sr->eig[sPres->index + sPres->neigs -1]) - sPres->value) >0){
504
        *newS = PetscRealPart(sr->eig[sPres->index + sPres->neigs -1])+ ((sr->dir)*d_prev*(eps->nev))/2;  
2596 carcamgo 505
      }else{/* Last accepted value is on the left of shift. Adding to shift */
2459 carcamgo 506
        *newS = sPres->value + ((sr->dir)*d_prev*(eps->nev))/2;
507
      }
508
    }
2596 carcamgo 509
    /* End of interval can not be surpassed */
510
    if((sr->dir)*( sr->int1 - *newS) < 0) *newS = sr->int1;
2609 carcamgo 511
  }/* of neighb[side]==null */
2459 carcamgo 512
  PetscFunctionReturn(0);
513
}
514
 
515
/*
2596 carcamgo 516
  Function for sorting an array of real values
2459 carcamgo 517
*/
518
#undef __FUNCT__
519
#define __FUNCT__ "sortRealEigenvalues"
520
static PetscErrorCode sortRealEigenvalues(PetscScalar *r,PetscInt *perm,PetscInt nr,PetscBool prev,PetscInt dir)
521
{
522
  PetscReal      re;
523
  PetscInt       i,j,tmp;
524
 
525
  PetscFunctionBegin;
2464 carcamgo 526
  if(!prev) for (i=0; i < nr; i++) { perm[i] = i; }
2596 carcamgo 527
  /* Insertion sort */
2459 carcamgo 528
  for (i=1; i < nr; i++) {
529
    re = PetscRealPart(r[perm[i]]);
530
    j = i-1;
531
    while ( j>=0 && dir*(re - PetscRealPart(r[perm[j]])) <= 0 ) {
532
      tmp = perm[j]; perm[j] = perm[j+1]; perm[j+1] = tmp; j--;
533
    }
534
  }
535
  PetscFunctionReturn(0);
536
}
537
 
538
/* Stores the pairs obtained since the last shift in the global arrays */
539
#undef __FUNCT__
540
#define __FUNCT__ "EPSStoreEigenpairs"
541
PetscErrorCode EPSStoreEigenpairs(EPS eps)
542
{
543
  PetscErrorCode ierr;
2596 carcamgo 544
  PetscReal      lambda,err,norm;
2459 carcamgo 545
  PetscInt       i,count;
2641 jroman 546
  PetscBool      iscayley;
2459 carcamgo 547
  SR             sr;
548
  shift          sPres;
549
 
550
  PetscFunctionBegin;
551
  sr = (SR)(eps->data);
552
  sPres = sr->sPres;
553
  sPres->index = sr->indexEig;
554
  count = sr->indexEig;
2708 carcamgo 555
  /* Back-transform */
2629 carcamgo 556
  ierr = EPSBackTransform_Default(eps);CHKERRQ(ierr);
557
  ierr = PetscTypeCompare((PetscObject)eps->OP,STCAYLEY,&iscayley);CHKERRQ(ierr);
2596 carcamgo 558
  /* Sort eigenvalues */
2459 carcamgo 559
  ierr = sortRealEigenvalues(eps->eigr,eps->perm,eps->nconv,PETSC_FALSE,sr->dir);
2596 carcamgo 560
  /* Values stored in global array */
2459 carcamgo 561
  for( i=0; i < eps->nconv ;i++ ){
562
    lambda = PetscRealPart(eps->eigr[eps->perm[i]]);
2596 carcamgo 563
    err = eps->errest[eps->perm[i]];
2708 carcamgo 564
 
2596 carcamgo 565
    if(  (sr->dir)*(lambda - sPres->ext[0]) > 0 && (sr->dir)*(sPres->ext[1] - lambda) > 0  ){/* Valid value */
566
      if(count>=sr->numEigs){/* Error found */
2629 carcamgo 567
         SETERRQ(((PetscObject)eps)->comm,1,"Unexpected error in Spectrum Slicing!");
568
      }
2459 carcamgo 569
      sr->eig[count] = lambda;
2596 carcamgo 570
      sr->errest[count] = err;
2708 carcamgo 571
      /* Unlikely explicit purification */
572
      if (sPres->expf && eps->isgeneralized && !iscayley){
2609 carcamgo 573
        ierr = STApply(eps->OP,eps->V[eps->perm[i]],sr->V[count]);CHKERRQ(ierr);
574
        ierr = IPNorm(eps->ip,sr->V[count],&norm);CHKERRQ(ierr);
575
        ierr = VecScale(sr->V[count],1.0/norm);CHKERRQ(ierr);
576
      }else{
577
        ierr = VecCopy(eps->V[eps->perm[i]], sr->V[count]);CHKERRQ(ierr);
578
      }
2459 carcamgo 579
      count++;
2596 carcamgo 580
    }
2459 carcamgo 581
  }
582
  sPres->neigs = count - sr->indexEig;
583
  sr->indexEig = count;
2596 carcamgo 584
  /* Global ordering array updating */
2459 carcamgo 585
  ierr = sortRealEigenvalues(sr->eig,sr->perm,count,PETSC_TRUE,sr->dir);CHKERRQ(ierr);
586
  PetscFunctionReturn(0);
587
}
588
 
589
#undef __FUNCT__
590
#define __FUNCT__ "EPSLookForDeflation"
591
PetscErrorCode EPSLookForDeflation(EPS eps)
592
{
2596 carcamgo 593
  PetscReal       val;
2459 carcamgo 594
  PetscInt        i,count0=0,count1=0;
595
  shift           sPres;
2596 carcamgo 596
  PetscInt        ini,fin,k,idx0,idx1;
2459 carcamgo 597
  SR              sr;
598
 
599
  PetscFunctionBegin;
600
  sr = (SR)(eps->data);
601
  sPres = sr->sPres;
602
 
2464 carcamgo 603
  if(sPres->neighb[0]) ini = (sr->dir)*(sPres->neighb[0]->inertia - sr->inertia0);
2459 carcamgo 604
  else ini = 0;
605
  fin = sr->indexEig;
2596 carcamgo 606
  /* Selection of ends for searching new values */
607
  if(!sPres->neighb[0]) sPres->ext[0] = sr->int0;/* First shift */
2459 carcamgo 608
  else sPres->ext[0] = sPres->neighb[0]->value;
2464 carcamgo 609
  if(!sPres->neighb[1]) {
2459 carcamgo 610
    if(sr->hasEnd) sPres->ext[1] = sr->int1;
611
    else sPres->ext[1] = (sr->dir > 0)?PETSC_MAX_REAL:PETSC_MIN_REAL;
612
  }else sPres->ext[1] = sPres->neighb[1]->value;
2596 carcamgo 613
  /* Selection of values between right and left ends */
2459 carcamgo 614
  for(i=ini;i<fin;i++){
615
    val=PetscRealPart(sr->eig[sr->perm[i]]);
2596 carcamgo 616
    /* Values to the right of left shift */
2459 carcamgo 617
    if( (sr->dir)*(val - sPres->ext[1]) < 0 ){
618
      if((sr->dir)*(val - sPres->value) < 0)count0++;
619
      else count1++;
620
    }else break;
621
  }
2596 carcamgo 622
  /* The number of values on each side are found */
2629 carcamgo 623
  if(sPres->neighb[0]){
2459 carcamgo 624
     sPres->nsch[0] = (sr->dir)*(sPres->inertia - sPres->neighb[0]->inertia)-count0;
2629 carcamgo 625
     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");
626
  }else sPres->nsch[0] = 0;
2459 carcamgo 627
 
2629 carcamgo 628
  if(sPres->neighb[1]){
2459 carcamgo 629
    sPres->nsch[1] = (sr->dir)*(sPres->neighb[1]->inertia - sPres->inertia) - count1;
2629 carcamgo 630
    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");
631
  }else sPres->nsch[1] = (sr->dir)*(sr->inertia1 - sPres->inertia);
2708 carcamgo 632
 
2596 carcamgo 633
  /* Completing vector of indexes for deflation */
634
  idx0 = ini;
635
  idx1 = ini+count0+count1;
2459 carcamgo 636
  k=0;
637
  for(i=idx0;i<idx1;i++)sr->idxDef[k++]=sr->perm[i];
638
  for(i=0;i<k;i++)sr->VDef[i]=sr->V[sr->idxDef[i]];
639
  eps->DS = sr->VDef;
640
  eps->nds = k;
641
  PetscFunctionReturn(0);
642
}
643
 
644
#undef __FUNCT__
645
#define __FUNCT__ "EPSSolve_KrylovSchur_Slice"
646
PetscErrorCode EPSSolve_KrylovSchur_Slice(EPS eps)
647
{
648
  PetscErrorCode ierr;
2708 carcamgo 649
  PetscInt       i,lds;
2459 carcamgo 650
  PetscReal      newS;
651
  KSP            ksp;
652
  PC             pc;
2596 carcamgo 653
  Mat            F;  
654
  PetscReal      *errest_left;
655
  Vec            t;
2459 carcamgo 656
  SR             sr;
2713 jroman 657
  shift          s;
2459 carcamgo 658
 
659
  PetscFunctionBegin;
2629 carcamgo 660
#if defined(PETSC_USE_COMPLEX)
661
  SETERRQ(((PetscObject)eps)->comm,PETSC_ERR_SUP,"Spectrum slicing not supported in complex scalars");
662
#endif
2464 carcamgo 663
  ierr = PetscMalloc(sizeof(struct _n_SR),&sr);CHKERRQ(ierr);
2459 carcamgo 664
  eps->data = sr;
2596 carcamgo 665
  sr->itsKs = 0;
666
  sr->nleap = 0;
667
  sr->nMAXCompl = eps->nev/4;
668
  sr->iterCompl = eps->max_it/4;
2708 carcamgo 669
  sr->sPres = PETSC_NULL;
670
  sr->nS = 0;
671
  lds = PetscMin(eps->mpd,eps->ncv);
2596 carcamgo 672
  /* Checking presence of ends and finding direction */
2459 carcamgo 673
  if( eps->inta > PETSC_MIN_REAL){
674
    sr->int0 = eps->inta;
675
    sr->int1 = eps->intb;
676
    sr->dir = 1;
2596 carcamgo 677
    if(eps->intb >= PETSC_MAX_REAL){ /* Right-open interval */
2459 carcamgo 678
      sr->hasEnd = PETSC_FALSE;
679
      sr->inertia1 = eps->n;
680
    }else sr->hasEnd = PETSC_TRUE;
2596 carcamgo 681
  }else{ /* Left-open interval */
2459 carcamgo 682
    sr->int0 = eps->intb;
683
    sr->int1 = eps->inta;
684
    sr->dir = -1;
685
    sr->hasEnd = PETSC_FALSE;
686
    sr->inertia1 = 0;
687
  }
2596 carcamgo 688
  /* Array of pending shifts */
689
  sr->maxPend = 100;/* Initial size */
2459 carcamgo 690
  ierr = PetscMalloc((sr->maxPend)*sizeof(shift),&sr->pending);CHKERRQ(ierr);
691
  if(sr->hasEnd){
692
    ierr = STGetKSP(eps->OP, &ksp);CHKERRQ(ierr);
693
    ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
694
    ierr = PCFactorGetMatrix(pc,&F);CHKERRQ(ierr);
2596 carcamgo 695
    /* Not looking for values in b (just inertia).*/
2459 carcamgo 696
    ierr = MatGetInertia(F,&sr->inertia1,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
2629 carcamgo 697
    ierr = PCReset(pc);CHKERRQ(ierr); /* avoiding memory leak */
2459 carcamgo 698
  }
699
  sr->nPend = 0;
700
  ierr = EPSCreateShift(eps,sr->int0,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
701
  ierr = EPSExtractShift(eps);
702
  sr->s0 = sr->sPres;
703
  sr->inertia0 = sr->s0->inertia;
704
  sr->numEigs = (sr->dir)*(sr->inertia1 - sr->inertia0);
705
  sr->indexEig = 0;
2596 carcamgo 706
  /* Only with eigenvalues present in the interval ...*/
2464 carcamgo 707
  if(sr->numEigs==0){
708
    eps->reason = EPS_CONVERGED_TOL;
2596 carcamgo 709
    ierr = PetscFree(sr->s0);CHKERRQ(ierr);
710
    ierr = PetscFree(sr->pending);CHKERRQ(ierr);
711
    ierr = PetscFree(sr);CHKERRQ(ierr);
2464 carcamgo 712
    PetscFunctionReturn(0);
713
  }
2596 carcamgo 714
  /* Memory reservation for eig, V and perm */
2708 carcamgo 715
  ierr = PetscMalloc(lds*lds*sizeof(PetscScalar),&sr->S);CHKERRQ(ierr);
716
  ierr = PetscMemzero(sr->S,lds*lds*sizeof(PetscScalar));CHKERRQ(ierr);
2464 carcamgo 717
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscScalar),&sr->eig);CHKERRQ(ierr);
2596 carcamgo 718
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscScalar),&sr->eigi);CHKERRQ(ierr);
2599 carcamgo 719
  ierr = PetscMalloc((sr->numEigs+eps->ncv) *sizeof(PetscReal),&sr->errest);CHKERRQ(ierr);
720
  ierr = PetscMalloc((sr->numEigs+eps->ncv)*sizeof(PetscReal),&errest_left);CHKERRQ(ierr);
2609 carcamgo 721
  ierr = PetscMalloc((sr->numEigs+eps->ncv)*sizeof(PetscScalar),&sr->monit);CHKERRQ(ierr);
2629 carcamgo 722
  ierr = PetscMalloc((eps->ncv)*sizeof(PetscScalar),&sr->back);CHKERRQ(ierr);
2599 carcamgo 723
  for(i=0;i<sr->numEigs;i++){sr->eigi[i]=0;sr->eig[i] = 0;}
724
  for(i=0;i<sr->numEigs+eps->ncv;i++){errest_left[i]=0;sr->errest[i]=0;sr->monit[i]=0;}
2464 carcamgo 725
  ierr = VecCreateMPI(((PetscObject)eps)->comm,eps->nloc,PETSC_DECIDE,&t);CHKERRQ(ierr);
726
  ierr = VecDuplicateVecs(t,sr->numEigs,&sr->V);CHKERRQ(ierr);
727
  ierr = VecDestroy(&t);CHKERRQ(ierr);
2596 carcamgo 728
  /* Vector for maintaining order of eigenvalues */
2464 carcamgo 729
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscInt),&sr->perm);CHKERRQ(ierr);
730
  for(i=0;i< sr->numEigs;i++)sr->perm[i]=i;
2596 carcamgo 731
  /* Vectors for deflation */
732
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscInt),&sr->idxDef);CHKERRQ(ierr);
2464 carcamgo 733
  ierr = PetscMalloc((sr->numEigs)*sizeof(Vec),&sr->VDef);CHKERRQ(ierr);
734
  sr->indexEig = 0;
2708 carcamgo 735
  /* Main loop */
2464 carcamgo 736
  while(sr->sPres){
2596 carcamgo 737
    /* Search for deflation */
2464 carcamgo 738
    ierr = EPSLookForDeflation(eps);CHKERRQ(ierr);
2596 carcamgo 739
    /* KrylovSchur */
2464 carcamgo 740
    ierr = EPSKrylovSchur_Slice(eps);CHKERRQ(ierr);
2596 carcamgo 741
 
2464 carcamgo 742
    ierr = EPSStoreEigenpairs(eps);CHKERRQ(ierr);
2596 carcamgo 743
    /* Select new shift */
2468 eromero 744
    if(!sr->sPres->comp[1]){
2464 carcamgo 745
      ierr = EPSGetNewShiftValue(eps,1,&newS);CHKERRQ(ierr);
746
      ierr = EPSCreateShift(eps,newS,sr->sPres,sr->sPres->neighb[1]);
747
    }
2468 eromero 748
    if(!sr->sPres->comp[0]){
2596 carcamgo 749
      /* Completing earlier interval */
2464 carcamgo 750
      ierr = EPSGetNewShiftValue(eps,0,&newS);CHKERRQ(ierr);
751
      ierr = EPSCreateShift(eps,newS,sr->sPres->neighb[0],sr->sPres);
752
    }
2596 carcamgo 753
    /* Preparing for a new search of values */
2464 carcamgo 754
    ierr = EPSExtractShift(eps);CHKERRQ(ierr);
755
  }
2596 carcamgo 756
 
757
  /* Updating eps values prior to exit */
2629 carcamgo 758
 
2464 carcamgo 759
  ierr = VecDestroyVecs(eps->allocated_ncv,&eps->V);CHKERRQ(ierr);
760
  eps->V = sr->V;
2708 carcamgo 761
  ierr = PetscFree(sr->S);CHKERRQ(ierr);
2464 carcamgo 762
  ierr = PetscFree(eps->eigr);CHKERRQ(ierr);
763
  ierr = PetscFree(eps->eigi);CHKERRQ(ierr);
764
  ierr = PetscFree(eps->errest);CHKERRQ(ierr);
765
  ierr = PetscFree(eps->errest_left);CHKERRQ(ierr);
766
  ierr = PetscFree(eps->perm);CHKERRQ(ierr);
2596 carcamgo 767
  eps->eigr = sr->eig;
768
  eps->eigi = sr->eigi;
769
  eps->errest = sr->errest;
770
  eps->errest_left = errest_left;
2464 carcamgo 771
  eps->perm = sr->perm;
2596 carcamgo 772
  eps->ncv = eps->allocated_ncv = sr->numEigs;
2464 carcamgo 773
  eps->nconv = sr->indexEig;
774
  eps->reason = EPS_CONVERGED_TOL;
2596 carcamgo 775
  eps->its = sr->itsKs;
2464 carcamgo 776
  eps->nds = 0;
777
  eps->DS = PETSC_NULL;
2596 carcamgo 778
  eps->evecsavailable = PETSC_TRUE;
2464 carcamgo 779
  ierr = PetscFree(sr->VDef);CHKERRQ(ierr);
780
  ierr = PetscFree(sr->idxDef);CHKERRQ(ierr);
781
  ierr = PetscFree(sr->pending);CHKERRQ(ierr);
2599 carcamgo 782
  ierr = PetscFree(sr->monit);CHKERRQ(ierr);
2629 carcamgo 783
  ierr = PetscFree(sr->back);CHKERRQ(ierr);
2596 carcamgo 784
  /* Reviewing list of shifts to free memory */
2713 jroman 785
  s = sr->s0;
2464 carcamgo 786
  if(s){
787
    while(s->neighb[1]){
788
      s = s->neighb[1];
789
      ierr = PetscFree(s->neighb[0]);CHKERRQ(ierr);
2459 carcamgo 790
    }
2464 carcamgo 791
    ierr = PetscFree(s);CHKERRQ(ierr);
2459 carcamgo 792
  }
2464 carcamgo 793
  ierr = PetscFree(sr);CHKERRQ(ierr);
2459 carcamgo 794
  PetscFunctionReturn(0);
2599 carcamgo 795
}