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