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;
2820 carcamgo 195
  PetscInt       i,conv,k,l,ld,nv,*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 */
2820 carcamgo 247
    nv = PetscMin(eps->nconv+eps->mpd,eps->ncv);
2805 carcamgo 248
    ierr = PSGetArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
249
    b = a + ld;
2820 carcamgo 250
    ierr = EPSFullLanczos(eps,a,b,eps->V,eps->nconv+l,&nv,u,&breakdown);CHKERRQ(ierr);
2708 carcamgo 251
    if(breakdown){/* explicit purification*/
252
      sPres->expf = PETSC_TRUE;    
253
    }
2404 jroman 254
    beta = b[nv-1];
2805 carcamgo 255
    ierr = PSRestoreArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
2820 carcamgo 256
    ierr = PSSetDimensions(eps->ps,nv,eps->nconv,eps->nconv+l);CHKERRQ(ierr);
2805 carcamgo 257
    if (l==0) {
258
      ierr = PSSetState(eps->ps,PS_STATE_INTERMEDIATE);CHKERRQ(ierr);
259
    } else {
260
      ierr = PSSetState(eps->ps,PS_STATE_RAW);CHKERRQ(ierr);
261
    }
262
 
2459 carcamgo 263
    /* Solve projected problem and compute residual norm estimates */
2708 carcamgo 264
    if(eps->its == 1 && l > 0){/* After rational update */
2805 carcamgo 265
      ierr = PSGetArray(eps->ps,PS_MAT_A,&A);CHKERRQ(ierr);
266
      ierr = PSGetArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
267
      b = a + ld;
2820 carcamgo 268
      k = eps->nconv+l;
269
      A[k*ld+k-1] = A[(k-1)*ld+k];
270
      A[k*ld+k] = a[k];
271
      for(j=k+1; j< nv; j++){
2805 carcamgo 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);
2820 carcamgo 278
      ierr = PSSolve(eps->ps,eps->eigr,PETSC_NULL);CHKERRQ(ierr);
279
      ierr = PSSetCompact(eps->ps,PETSC_TRUE);
2708 carcamgo 280
    }else{/* Restart */
2820 carcamgo 281
      ierr = PSSolve(eps->ps,eps->eigr,PETSC_NULL);CHKERRQ(ierr);
2708 carcamgo 282
    }
2820 carcamgo 283
    ierr = PSSort(eps->ps,eps->eigr,PETSC_NULL,eps->which_func,eps->which_ctx);CHKERRQ(ierr);
2596 carcamgo 284
    /* Residual */
2820 carcamgo 285
    ierr = EPSKrylovConvergence(eps,PETSC_TRUE,eps->nconv,nv-eps->nconv,eps->V,nv,beta,1.0,&k);CHKERRQ(ierr);
286
    /* Check convergence */
287
 
2805 carcamgo 288
    ierr = PSGetArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
289
    b = a + ld;
2820 carcamgo 290
    conv = 0;
291
    j = k = eps->nconv;
292
    for(i=eps->nconv;i<nv;i++)if(eps->errest[i] < eps->tol)conv++;
293
    for(i=eps->nconv;i<nv;i++){
294
      if(eps->errest[i] < eps->tol){
2596 carcamgo 295
        iwork[j++]=i;
296
      }else iwork[conv+k++]=i;
2459 carcamgo 297
    }
2820 carcamgo 298
    for(i=eps->nconv;i<nv;i++){
299
      a[i]=PetscRealPart(eps->eigr[i]);
300
      b[i]=eps->errest[i];
2599 carcamgo 301
    }
2820 carcamgo 302
    for(i=eps->nconv;i<nv;i++){
303
      eps->eigr[i] = a[iwork[i]];
304
      eps->errest[i] = b[iwork[i]];
2459 carcamgo 305
    }
2820 carcamgo 306
    for(i=eps->nconv;i<nv;i++){
307
      a[i]=PetscRealPart(eps->eigr[i]);
308
      b[i]=eps->errest[i];
2805 carcamgo 309
    }
2820 carcamgo 310
 
2805 carcamgo 311
    k=eps->nconv+conv;
2820 carcamgo 312
    ierr = PSPermuteColumns_Private(eps->ps,eps->nconv,nv,PS_MAT_Q,iwork);CHKERRQ(ierr);
2805 carcamgo 313
    ierr = PSRestoreArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
314
 
2459 carcamgo 315
    /* Checking values obtained for completing */
2629 carcamgo 316
    for(i=0;i<k;i++){
317
      sr->back[i]=eps->eigr[i];
318
    }
319
    ierr = STBackTransform(eps->OP,k,sr->back,eps->eigi);CHKERRQ(ierr);
2459 carcamgo 320
    count0=count1=0;
2805 carcamgo 321
    for(i=0;i<k;i++){
2640 carcamgo 322
      lambda = PetscRealPart(sr->back[i]);
2709 carcamgo 323
      if( ((sr->dir)*(sPres->value - lambda) > 0) && ((sr->dir)*(lambda - sPres->ext[0]) > 0))count0++;
324
      if( ((sr->dir)*(lambda - sPres->value) > 0) && ((sr->dir)*(sPres->ext[1] - lambda) > 0))count1++;
2459 carcamgo 325
    }
2404 jroman 326
 
2596 carcamgo 327
    /* Checks completion */
2459 carcamgo 328
    if( (!sch0||count0 >= sPres->nsch[0]) && (!sch1 ||count1 >= sPres->nsch[1]) ) {
329
      eps->reason = EPS_CONVERGED_TOL;
330
    }else {
331
      if(!complIterating && eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
332
      if(complIterating){
333
        if(--iterCompl <= 0) eps->reason = EPS_DIVERGED_ITS;
2596 carcamgo 334
      }else if (k >= eps->nev) {
2459 carcamgo 335
        n0 = sPres->nsch[0]-count0;
336
        n1 = sPres->nsch[1]-count1;
2708 carcamgo 337
        if( sr->iterCompl>0 && ( (n0>0 && n0<= sr->nMAXCompl)||(n1>0&&n1<=sr->nMAXCompl) )){
2596 carcamgo 338
          /* Iterating for completion*/
2459 carcamgo 339
          complIterating = PETSC_TRUE;
340
          if(n0 >sr->nMAXCompl)sch0 = PETSC_FALSE;
341
          if(n1 >sr->nMAXCompl)sch1 = PETSC_FALSE;
342
          iterCompl = sr->iterCompl;
343
        }else eps->reason = EPS_CONVERGED_TOL;
344
      }      
345
    }
2404 jroman 346
    /* Update l */
2820 carcamgo 347
    if(eps->reason == EPS_CONVERGED_ITERATING )l = (nv-k)/2;
348
    else l=nv-k;
2708 carcamgo 349
    if(breakdown)l=0;
2404 jroman 350
 
351
    if (eps->reason == EPS_CONVERGED_ITERATING) {
352
      if (breakdown) {
353
        /* Start a new Lanczos factorization */
2499 jroman 354
        ierr = PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%D norm=%G)\n",eps->its,beta);CHKERRQ(ierr);
2404 jroman 355
        ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
356
        if (breakdown) {
357
          eps->reason = EPS_DIVERGED_BREAKDOWN;
2499 jroman 358
          ierr = PetscInfo(eps,"Unable to generate more start vectors\n");CHKERRQ(ierr);
2404 jroman 359
        }
360
      } else {
361
        /* Prepare the Rayleigh quotient for restart */
2805 carcamgo 362
        ierr = PSGetArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
363
        ierr = PSGetArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
364
        b = a + ld;
2820 carcamgo 365
        for (i=k;i<k+l;i++) {
366
          a[i] = PetscRealPart(eps->eigr[i]);
367
          b[i] = PetscRealPart(Q[nv-1+i*ld]*beta);
2404 jroman 368
        }
2805 carcamgo 369
        ierr = PSRestoreArrayReal(eps->ps,PS_MAT_T,&a);CHKERRQ(ierr);
370
        ierr = PSRestoreArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
2404 jroman 371
      }
372
    }
373
    /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
2805 carcamgo 374
    ierr = PSGetArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
2820 carcamgo 375
    ierr = SlepcUpdateVectors(nv,eps->V,eps->nconv,k+l,Q,ld,PETSC_FALSE);CHKERRQ(ierr);
2708 carcamgo 376
    /* Purification */
2820 carcamgo 377
 
2708 carcamgo 378
    if(!sPres->expf){/* u not saved if breakdown */
379
      for(i=eps->nconv; i<k;i++){
2820 carcamgo 380
        alpha = (Q[nv-1+i*ld])/PetscRealPart(eps->eigr[i]);
2708 carcamgo 381
        ierr = VecAXPY(eps->V[i], alpha, u);CHKERRQ(ierr);
382
      }
383
    }
2820 carcamgo 384
 
2805 carcamgo 385
    ierr = PSRestoreArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
2404 jroman 386
    /* Normalize u and append it to V */
2708 carcamgo 387
    if ( eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
2404 jroman 388
      ierr = VecAXPBY(eps->V[k+l],1.0/beta,0.0,u);CHKERRQ(ierr);
389
    }
2708 carcamgo 390
    /* Monitor */
2629 carcamgo 391
    if(eps->numbermonitors >0){
392
      aux = auxc = 0;
2820 carcamgo 393
      for(i=0;i<nv;i++){
2629 carcamgo 394
        sr->back[i]=eps->eigr[i];
2599 carcamgo 395
      }
2820 carcamgo 396
      ierr = STBackTransform(eps->OP,nv,sr->back,eps->eigi);CHKERRQ(ierr);
397
      for(i=0;i<nv;i++){
2640 carcamgo 398
        lambda = PetscRealPart(sr->back[i]);
2629 carcamgo 399
        if( ((sr->dir)*(lambda - sPres->ext[0]) > 0)&& ((sr->dir)*(sPres->ext[1] - lambda) > 0)){
400
          sr->monit[sr->indexEig+aux]=eps->eigr[i];
401
          sr->errest[sr->indexEig+aux]=eps->errest[i];
402
          aux++;
403
          if(eps->errest[i] < eps->tol)auxc++;
404
        }
405
      }
406
      ierr = EPSMonitor(eps,eps->its,auxc+sr->indexEig,sr->monit,sr->eigi,sr->errest,sr->indexEig+aux);CHKERRQ(ierr);
2599 carcamgo 407
    }
2404 jroman 408
    eps->nconv = k;
2708 carcamgo 409
    if(eps->reason != EPS_CONVERGED_ITERATING){
410
      /* Store approximated values for next shift */
2805 carcamgo 411
      ierr = PSGetArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
2708 carcamgo 412
      sr->nS = l;
413
      for (i=0;i<l;i++) {
414
        sr->S[i] = eps->eigr[i+k];/* Diagonal elements */
2820 carcamgo 415
        sr->S[i+l] = Q[nv-1+(i+k)*ld]*beta; /* Out of diagonal elements */
2708 carcamgo 416
      }
417
      sr->beta = beta;
2805 carcamgo 418
      ierr = PSRestoreArray(eps->ps,PS_MAT_Q,&Q);CHKERRQ(ierr);
2708 carcamgo 419
    }
2459 carcamgo 420
  }
2596 carcamgo 421
  /* Check for completion */
422
  for(i=0;i< eps->nconv; i++){
423
    if( (sr->dir)*PetscRealPart(eps->eigr[i])>0 )sPres->nconv[1]++;
424
    else sPres->nconv[0]++;
425
  }
2468 eromero 426
  sPres->comp[0] = (count0 >= sPres->nsch[0])?PETSC_TRUE:PETSC_FALSE;
427
  sPres->comp[1] = (count1 >= sPres->nsch[1])?PETSC_TRUE:PETSC_FALSE;
2701 carcamgo 428
  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 429
  ierr = PetscFree(iwork);CHKERRQ(ierr);  
2404 jroman 430
  PetscFunctionReturn(0);
431
}
432
 
2459 carcamgo 433
/*
2596 carcamgo 434
  Obtains value of subsequent shift
2459 carcamgo 435
*/
436
#undef __FUNCT__
437
#define __FUNCT__ "EPSGetNewShiftValue"
2708 carcamgo 438
static PetscErrorCode EPSGetNewShiftValue(EPS eps,PetscInt side,PetscReal *newS)
439
{
2596 carcamgo 440
  PetscReal   lambda,d_prev;
2459 carcamgo 441
  PetscInt    i,idxP;
442
  SR          sr;
2666 eromero 443
  shift       sPres,s;
2459 carcamgo 444
 
445
  PetscFunctionBegin;  
446
  sr = (SR)eps->data;
447
  sPres = sr->sPres;
2464 carcamgo 448
  if( sPres->neighb[side]){
2596 carcamgo 449
  /* Completing a previous interval */
450
    if(!sPres->neighb[side]->neighb[side] && sPres->neighb[side]->nconv[side]==0){ /* One of the ends might be too far from eigenvalues */
451
      if(side) *newS = (sPres->value + PetscRealPart(sr->eig[sr->perm[sr->indexEig-1]]))/2;
452
      else *newS = (sPres->value + PetscRealPart(sr->eig[sr->perm[0]]))/2;
453
    }else *newS=(sPres->value + sPres->neighb[side]->value)/2;
454
  }else{ /* (Only for side=1). Creating a new interval. */
455
    if(sPres->neigs==0){/* No value has been accepted*/
2464 carcamgo 456
      if(sPres->neighb[0]){
2596 carcamgo 457
        /* Multiplying by 10 the previous distance */
2465 jroman 458
        *newS = sPres->value + 10*(sr->dir)*PetscAbsReal(sPres->value - sPres->neighb[0]->value);
2596 carcamgo 459
        sr->nleap++;
460
        /* Stops when the interval is open and no values are found in the last 5 shifts (there might be infinite eigenvalues) */
461
        if( !sr->hasEnd && sr->nleap > 5)SETERRQ(((PetscObject)eps)->comm,1,"Unable to compute the wanted eigenvalues with open interval");          
462
      }else {/* First shift */
2459 carcamgo 463
        if(eps->nconv != 0){
2596 carcamgo 464
           /* Unaccepted values give information for next shift */
465
           idxP=0;/* Number of values left from shift */
2459 carcamgo 466
           for(i=0;i<eps->nconv;i++){
467
             lambda = PetscRealPart(eps->eigr[i]);
468
             if( (sr->dir)*(lambda - sPres->value) <0)idxP++;
469
             else break;
470
           }
2596 carcamgo 471
           /* Avoiding subtraction of eigenvalues (might be the same).*/
2459 carcamgo 472
           if(idxP>0){
2465 jroman 473
             d_prev = PetscAbsReal(sPres->value - PetscRealPart(eps->eigr[0]))/(idxP+0.3);
2459 carcamgo 474
           }else {
2465 jroman 475
             d_prev = PetscAbsReal(sPres->value - PetscRealPart(eps->eigr[eps->nconv-1]))/(eps->nconv+0.3);
2459 carcamgo 476
           }
477
           *newS = sPres->value + ((sr->dir)*d_prev*eps->nev)/2;
2596 carcamgo 478
        }else{/* No values found, no information for next shift */
479
          SETERRQ(((PetscObject)eps)->comm,1,"First shift renders no information");
2459 carcamgo 480
        }
481
      }
2596 carcamgo 482
    }else{/* Accepted values found */
483
      sr->nleap = 0;
484
      /* Average distance of values in previous subinterval */
2666 eromero 485
      s = sPres->neighb[0];
2464 carcamgo 486
      while(s && PetscAbs(s->inertia - sPres->inertia)==0){
2596 carcamgo 487
        s = s->neighb[0];/* Looking for previous shifts with eigenvalues within */
2459 carcamgo 488
      }
2464 carcamgo 489
      if(s){
2465 jroman 490
        d_prev = PetscAbsReal( (sPres->value - s->value)/(sPres->inertia - s->inertia));
2596 carcamgo 491
      }else{/* First shift. Average distance obtained with values in this shift */
492
        /* first shift might be too far from first wanted eigenvalue (no values found outside the interval)*/
2609 carcamgo 493
        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 494
          d_prev =  PetscAbsReal( (PetscRealPart(sr->eig[sr->indexEig-1]) - PetscRealPart(sr->eig[0])))/(sPres->neigs+0.3);
495
        }else{
496
          d_prev = PetscAbsReal( PetscRealPart(sr->eig[sr->indexEig-1]) - sPres->value)/(sPres->neigs+0.3);          
497
        }
2459 carcamgo 498
      }
2596 carcamgo 499
      /* Average distance is used for next shift by adding it to value on the right or to shift */
2465 jroman 500
      if( (sr->dir)*(PetscRealPart(sr->eig[sPres->index + sPres->neigs -1]) - sPres->value) >0){
501
        *newS = PetscRealPart(sr->eig[sPres->index + sPres->neigs -1])+ ((sr->dir)*d_prev*(eps->nev))/2;  
2596 carcamgo 502
      }else{/* Last accepted value is on the left of shift. Adding to shift */
2459 carcamgo 503
        *newS = sPres->value + ((sr->dir)*d_prev*(eps->nev))/2;
504
      }
505
    }
2596 carcamgo 506
    /* End of interval can not be surpassed */
507
    if((sr->dir)*( sr->int1 - *newS) < 0) *newS = sr->int1;
2609 carcamgo 508
  }/* of neighb[side]==null */
2459 carcamgo 509
  PetscFunctionReturn(0);
510
}
511
 
512
/*
2596 carcamgo 513
  Function for sorting an array of real values
2459 carcamgo 514
*/
515
#undef __FUNCT__
516
#define __FUNCT__ "sortRealEigenvalues"
517
static PetscErrorCode sortRealEigenvalues(PetscScalar *r,PetscInt *perm,PetscInt nr,PetscBool prev,PetscInt dir)
518
{
519
  PetscReal      re;
520
  PetscInt       i,j,tmp;
521
 
522
  PetscFunctionBegin;
2464 carcamgo 523
  if(!prev) for (i=0; i < nr; i++) { perm[i] = i; }
2596 carcamgo 524
  /* Insertion sort */
2459 carcamgo 525
  for (i=1; i < nr; i++) {
526
    re = PetscRealPart(r[perm[i]]);
527
    j = i-1;
528
    while ( j>=0 && dir*(re - PetscRealPart(r[perm[j]])) <= 0 ) {
529
      tmp = perm[j]; perm[j] = perm[j+1]; perm[j+1] = tmp; j--;
530
    }
531
  }
532
  PetscFunctionReturn(0);
533
}
534
 
535
/* Stores the pairs obtained since the last shift in the global arrays */
536
#undef __FUNCT__
537
#define __FUNCT__ "EPSStoreEigenpairs"
538
PetscErrorCode EPSStoreEigenpairs(EPS eps)
539
{
540
  PetscErrorCode ierr;
2596 carcamgo 541
  PetscReal      lambda,err,norm;
2459 carcamgo 542
  PetscInt       i,count;
2641 jroman 543
  PetscBool      iscayley;
2459 carcamgo 544
  SR             sr;
545
  shift          sPres;
546
 
547
  PetscFunctionBegin;
548
  sr = (SR)(eps->data);
549
  sPres = sr->sPres;
550
  sPres->index = sr->indexEig;
551
  count = sr->indexEig;
2708 carcamgo 552
  /* Back-transform */
2629 carcamgo 553
  ierr = EPSBackTransform_Default(eps);CHKERRQ(ierr);
554
  ierr = PetscTypeCompare((PetscObject)eps->OP,STCAYLEY,&iscayley);CHKERRQ(ierr);
2596 carcamgo 555
  /* Sort eigenvalues */
2459 carcamgo 556
  ierr = sortRealEigenvalues(eps->eigr,eps->perm,eps->nconv,PETSC_FALSE,sr->dir);
2596 carcamgo 557
  /* Values stored in global array */
2459 carcamgo 558
  for( i=0; i < eps->nconv ;i++ ){
559
    lambda = PetscRealPart(eps->eigr[eps->perm[i]]);
2596 carcamgo 560
    err = eps->errest[eps->perm[i]];
2708 carcamgo 561
 
2596 carcamgo 562
    if(  (sr->dir)*(lambda - sPres->ext[0]) > 0 && (sr->dir)*(sPres->ext[1] - lambda) > 0  ){/* Valid value */
563
      if(count>=sr->numEigs){/* Error found */
2629 carcamgo 564
         SETERRQ(((PetscObject)eps)->comm,1,"Unexpected error in Spectrum Slicing!");
565
      }
2459 carcamgo 566
      sr->eig[count] = lambda;
2596 carcamgo 567
      sr->errest[count] = err;
2708 carcamgo 568
      /* Unlikely explicit purification */
569
      if (sPres->expf && eps->isgeneralized && !iscayley){
2609 carcamgo 570
        ierr = STApply(eps->OP,eps->V[eps->perm[i]],sr->V[count]);CHKERRQ(ierr);
571
        ierr = IPNorm(eps->ip,sr->V[count],&norm);CHKERRQ(ierr);
572
        ierr = VecScale(sr->V[count],1.0/norm);CHKERRQ(ierr);
573
      }else{
574
        ierr = VecCopy(eps->V[eps->perm[i]], sr->V[count]);CHKERRQ(ierr);
575
      }
2459 carcamgo 576
      count++;
2596 carcamgo 577
    }
2459 carcamgo 578
  }
579
  sPres->neigs = count - sr->indexEig;
580
  sr->indexEig = count;
2596 carcamgo 581
  /* Global ordering array updating */
2459 carcamgo 582
  ierr = sortRealEigenvalues(sr->eig,sr->perm,count,PETSC_TRUE,sr->dir);CHKERRQ(ierr);
583
  PetscFunctionReturn(0);
584
}
585
 
586
#undef __FUNCT__
587
#define __FUNCT__ "EPSLookForDeflation"
588
PetscErrorCode EPSLookForDeflation(EPS eps)
589
{
2596 carcamgo 590
  PetscReal       val;
2459 carcamgo 591
  PetscInt        i,count0=0,count1=0;
592
  shift           sPres;
2596 carcamgo 593
  PetscInt        ini,fin,k,idx0,idx1;
2459 carcamgo 594
  SR              sr;
595
 
596
  PetscFunctionBegin;
597
  sr = (SR)(eps->data);
598
  sPres = sr->sPres;
599
 
2464 carcamgo 600
  if(sPres->neighb[0]) ini = (sr->dir)*(sPres->neighb[0]->inertia - sr->inertia0);
2459 carcamgo 601
  else ini = 0;
602
  fin = sr->indexEig;
2596 carcamgo 603
  /* Selection of ends for searching new values */
604
  if(!sPres->neighb[0]) sPres->ext[0] = sr->int0;/* First shift */
2459 carcamgo 605
  else sPres->ext[0] = sPres->neighb[0]->value;
2464 carcamgo 606
  if(!sPres->neighb[1]) {
2459 carcamgo 607
    if(sr->hasEnd) sPres->ext[1] = sr->int1;
608
    else sPres->ext[1] = (sr->dir > 0)?PETSC_MAX_REAL:PETSC_MIN_REAL;
609
  }else sPres->ext[1] = sPres->neighb[1]->value;
2596 carcamgo 610
  /* Selection of values between right and left ends */
2459 carcamgo 611
  for(i=ini;i<fin;i++){
612
    val=PetscRealPart(sr->eig[sr->perm[i]]);
2596 carcamgo 613
    /* Values to the right of left shift */
2459 carcamgo 614
    if( (sr->dir)*(val - sPres->ext[1]) < 0 ){
615
      if((sr->dir)*(val - sPres->value) < 0)count0++;
616
      else count1++;
617
    }else break;
618
  }
2596 carcamgo 619
  /* The number of values on each side are found */
2629 carcamgo 620
  if(sPres->neighb[0]){
2459 carcamgo 621
     sPres->nsch[0] = (sr->dir)*(sPres->inertia - sPres->neighb[0]->inertia)-count0;
2629 carcamgo 622
     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");
623
  }else sPres->nsch[0] = 0;
2459 carcamgo 624
 
2629 carcamgo 625
  if(sPres->neighb[1]){
2459 carcamgo 626
    sPres->nsch[1] = (sr->dir)*(sPres->neighb[1]->inertia - sPres->inertia) - count1;
2629 carcamgo 627
    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");
628
  }else sPres->nsch[1] = (sr->dir)*(sr->inertia1 - sPres->inertia);
2708 carcamgo 629
 
2596 carcamgo 630
  /* Completing vector of indexes for deflation */
631
  idx0 = ini;
632
  idx1 = ini+count0+count1;
2459 carcamgo 633
  k=0;
634
  for(i=idx0;i<idx1;i++)sr->idxDef[k++]=sr->perm[i];
635
  for(i=0;i<k;i++)sr->VDef[i]=sr->V[sr->idxDef[i]];
636
  eps->DS = sr->VDef;
637
  eps->nds = k;
638
  PetscFunctionReturn(0);
639
}
640
 
641
#undef __FUNCT__
642
#define __FUNCT__ "EPSSolve_KrylovSchur_Slice"
643
PetscErrorCode EPSSolve_KrylovSchur_Slice(EPS eps)
644
{
645
  PetscErrorCode ierr;
2708 carcamgo 646
  PetscInt       i,lds;
2459 carcamgo 647
  PetscReal      newS;
648
  KSP            ksp;
649
  PC             pc;
2596 carcamgo 650
  Mat            F;  
651
  PetscReal      *errest_left;
652
  Vec            t;
2459 carcamgo 653
  SR             sr;
2713 jroman 654
  shift          s;
2459 carcamgo 655
 
656
  PetscFunctionBegin;
2629 carcamgo 657
#if defined(PETSC_USE_COMPLEX)
658
  SETERRQ(((PetscObject)eps)->comm,PETSC_ERR_SUP,"Spectrum slicing not supported in complex scalars");
659
#endif
2464 carcamgo 660
  ierr = PetscMalloc(sizeof(struct _n_SR),&sr);CHKERRQ(ierr);
2459 carcamgo 661
  eps->data = sr;
2596 carcamgo 662
  sr->itsKs = 0;
663
  sr->nleap = 0;
664
  sr->nMAXCompl = eps->nev/4;
665
  sr->iterCompl = eps->max_it/4;
2708 carcamgo 666
  sr->sPres = PETSC_NULL;
667
  sr->nS = 0;
668
  lds = PetscMin(eps->mpd,eps->ncv);
2596 carcamgo 669
  /* Checking presence of ends and finding direction */
2459 carcamgo 670
  if( eps->inta > PETSC_MIN_REAL){
671
    sr->int0 = eps->inta;
672
    sr->int1 = eps->intb;
673
    sr->dir = 1;
2596 carcamgo 674
    if(eps->intb >= PETSC_MAX_REAL){ /* Right-open interval */
2459 carcamgo 675
      sr->hasEnd = PETSC_FALSE;
676
      sr->inertia1 = eps->n;
677
    }else sr->hasEnd = PETSC_TRUE;
2596 carcamgo 678
  }else{ /* Left-open interval */
2459 carcamgo 679
    sr->int0 = eps->intb;
680
    sr->int1 = eps->inta;
681
    sr->dir = -1;
682
    sr->hasEnd = PETSC_FALSE;
683
    sr->inertia1 = 0;
684
  }
2596 carcamgo 685
  /* Array of pending shifts */
686
  sr->maxPend = 100;/* Initial size */
2459 carcamgo 687
  ierr = PetscMalloc((sr->maxPend)*sizeof(shift),&sr->pending);CHKERRQ(ierr);
688
  if(sr->hasEnd){
689
    ierr = STGetKSP(eps->OP, &ksp);CHKERRQ(ierr);
690
    ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
691
    ierr = PCFactorGetMatrix(pc,&F);CHKERRQ(ierr);
2596 carcamgo 692
    /* Not looking for values in b (just inertia).*/
2459 carcamgo 693
    ierr = MatGetInertia(F,&sr->inertia1,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
2629 carcamgo 694
    ierr = PCReset(pc);CHKERRQ(ierr); /* avoiding memory leak */
2459 carcamgo 695
  }
696
  sr->nPend = 0;
697
  ierr = EPSCreateShift(eps,sr->int0,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
698
  ierr = EPSExtractShift(eps);
699
  sr->s0 = sr->sPres;
700
  sr->inertia0 = sr->s0->inertia;
701
  sr->numEigs = (sr->dir)*(sr->inertia1 - sr->inertia0);
702
  sr->indexEig = 0;
2596 carcamgo 703
  /* Only with eigenvalues present in the interval ...*/
2464 carcamgo 704
  if(sr->numEigs==0){
705
    eps->reason = EPS_CONVERGED_TOL;
2596 carcamgo 706
    ierr = PetscFree(sr->s0);CHKERRQ(ierr);
707
    ierr = PetscFree(sr->pending);CHKERRQ(ierr);
708
    ierr = PetscFree(sr);CHKERRQ(ierr);
2464 carcamgo 709
    PetscFunctionReturn(0);
710
  }
2596 carcamgo 711
  /* Memory reservation for eig, V and perm */
2708 carcamgo 712
  ierr = PetscMalloc(lds*lds*sizeof(PetscScalar),&sr->S);CHKERRQ(ierr);
713
  ierr = PetscMemzero(sr->S,lds*lds*sizeof(PetscScalar));CHKERRQ(ierr);
2464 carcamgo 714
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscScalar),&sr->eig);CHKERRQ(ierr);
2596 carcamgo 715
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscScalar),&sr->eigi);CHKERRQ(ierr);
2599 carcamgo 716
  ierr = PetscMalloc((sr->numEigs+eps->ncv) *sizeof(PetscReal),&sr->errest);CHKERRQ(ierr);
717
  ierr = PetscMalloc((sr->numEigs+eps->ncv)*sizeof(PetscReal),&errest_left);CHKERRQ(ierr);
2609 carcamgo 718
  ierr = PetscMalloc((sr->numEigs+eps->ncv)*sizeof(PetscScalar),&sr->monit);CHKERRQ(ierr);
2629 carcamgo 719
  ierr = PetscMalloc((eps->ncv)*sizeof(PetscScalar),&sr->back);CHKERRQ(ierr);
2599 carcamgo 720
  for(i=0;i<sr->numEigs;i++){sr->eigi[i]=0;sr->eig[i] = 0;}
721
  for(i=0;i<sr->numEigs+eps->ncv;i++){errest_left[i]=0;sr->errest[i]=0;sr->monit[i]=0;}
2464 carcamgo 722
  ierr = VecCreateMPI(((PetscObject)eps)->comm,eps->nloc,PETSC_DECIDE,&t);CHKERRQ(ierr);
723
  ierr = VecDuplicateVecs(t,sr->numEigs,&sr->V);CHKERRQ(ierr);
724
  ierr = VecDestroy(&t);CHKERRQ(ierr);
2596 carcamgo 725
  /* Vector for maintaining order of eigenvalues */
2464 carcamgo 726
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscInt),&sr->perm);CHKERRQ(ierr);
727
  for(i=0;i< sr->numEigs;i++)sr->perm[i]=i;
2596 carcamgo 728
  /* Vectors for deflation */
729
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscInt),&sr->idxDef);CHKERRQ(ierr);
2464 carcamgo 730
  ierr = PetscMalloc((sr->numEigs)*sizeof(Vec),&sr->VDef);CHKERRQ(ierr);
731
  sr->indexEig = 0;
2708 carcamgo 732
  /* Main loop */
2464 carcamgo 733
  while(sr->sPres){
2596 carcamgo 734
    /* Search for deflation */
2464 carcamgo 735
    ierr = EPSLookForDeflation(eps);CHKERRQ(ierr);
2596 carcamgo 736
    /* KrylovSchur */
2464 carcamgo 737
    ierr = EPSKrylovSchur_Slice(eps);CHKERRQ(ierr);
2596 carcamgo 738
 
2464 carcamgo 739
    ierr = EPSStoreEigenpairs(eps);CHKERRQ(ierr);
2596 carcamgo 740
    /* Select new shift */
2468 eromero 741
    if(!sr->sPres->comp[1]){
2464 carcamgo 742
      ierr = EPSGetNewShiftValue(eps,1,&newS);CHKERRQ(ierr);
743
      ierr = EPSCreateShift(eps,newS,sr->sPres,sr->sPres->neighb[1]);
744
    }
2468 eromero 745
    if(!sr->sPres->comp[0]){
2596 carcamgo 746
      /* Completing earlier interval */
2464 carcamgo 747
      ierr = EPSGetNewShiftValue(eps,0,&newS);CHKERRQ(ierr);
748
      ierr = EPSCreateShift(eps,newS,sr->sPres->neighb[0],sr->sPres);
749
    }
2596 carcamgo 750
    /* Preparing for a new search of values */
2464 carcamgo 751
    ierr = EPSExtractShift(eps);CHKERRQ(ierr);
752
  }
2596 carcamgo 753
 
754
  /* Updating eps values prior to exit */
2629 carcamgo 755
 
2464 carcamgo 756
  ierr = VecDestroyVecs(eps->allocated_ncv,&eps->V);CHKERRQ(ierr);
757
  eps->V = sr->V;
2708 carcamgo 758
  ierr = PetscFree(sr->S);CHKERRQ(ierr);
2464 carcamgo 759
  ierr = PetscFree(eps->eigr);CHKERRQ(ierr);
760
  ierr = PetscFree(eps->eigi);CHKERRQ(ierr);
761
  ierr = PetscFree(eps->errest);CHKERRQ(ierr);
762
  ierr = PetscFree(eps->errest_left);CHKERRQ(ierr);
763
  ierr = PetscFree(eps->perm);CHKERRQ(ierr);
2596 carcamgo 764
  eps->eigr = sr->eig;
765
  eps->eigi = sr->eigi;
766
  eps->errest = sr->errest;
767
  eps->errest_left = errest_left;
2464 carcamgo 768
  eps->perm = sr->perm;
2596 carcamgo 769
  eps->ncv = eps->allocated_ncv = sr->numEigs;
2464 carcamgo 770
  eps->nconv = sr->indexEig;
771
  eps->reason = EPS_CONVERGED_TOL;
2596 carcamgo 772
  eps->its = sr->itsKs;
2464 carcamgo 773
  eps->nds = 0;
774
  eps->DS = PETSC_NULL;
2596 carcamgo 775
  eps->evecsavailable = PETSC_TRUE;
2464 carcamgo 776
  ierr = PetscFree(sr->VDef);CHKERRQ(ierr);
777
  ierr = PetscFree(sr->idxDef);CHKERRQ(ierr);
778
  ierr = PetscFree(sr->pending);CHKERRQ(ierr);
2599 carcamgo 779
  ierr = PetscFree(sr->monit);CHKERRQ(ierr);
2629 carcamgo 780
  ierr = PetscFree(sr->back);CHKERRQ(ierr);
2596 carcamgo 781
  /* Reviewing list of shifts to free memory */
2713 jroman 782
  s = sr->s0;
2464 carcamgo 783
  if(s){
784
    while(s->neighb[1]){
785
      s = s->neighb[1];
786
      ierr = PetscFree(s->neighb[0]);CHKERRQ(ierr);
2459 carcamgo 787
    }
2464 carcamgo 788
    ierr = PetscFree(s);CHKERRQ(ierr);
2459 carcamgo 789
  }
2464 carcamgo 790
  ierr = PetscFree(sr);CHKERRQ(ierr);
2459 carcamgo 791
  PetscFunctionReturn(0);
2599 carcamgo 792
}