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