Subversion Repositories slepc-dev

Rev

Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2404 jroman 1
/*                      
2
 
3
   SLEPc eigensolver: "krylovschur"
4
 
5
   Method: Krylov-Schur with spectrum slicing for symmetric eigenproblems
6
 
7
   References:
8
 
9
       [1] R.G. Grimes et al., "A shifted block Lanczos algorithm for solving
10
           sparse symmetric generalized eigenproblems", SIAM J. Matrix Analysis
11
           and App., 15(1), pp. 228–272, 1994.
12
 
13
       [2] G.W. Stewart, "A Krylov-Schur Algorithm for Large Eigenproblems",
14
           SIAM J. Matrix Analysis and App., 23(3), pp. 601-614, 2001.
15
 
16
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
17
   SLEPc - Scalable Library for Eigenvalue Problem Computations
2575 eromero 18
   Copyright (c) 2002-2011, Universitat Politecnica de Valencia, Spain
2404 jroman 19
 
20
   This file is part of SLEPc.
2459 carcamgo 21
 
2404 jroman 22
   SLEPc is free software: you can redistribute it and/or modify it under  the
23
   terms of version 3 of the GNU Lesser General Public License as published by
24
   the Free Software Foundation.
25
 
26
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
27
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
28
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
29
   more details.
30
 
31
   You  should have received a copy of the GNU Lesser General  Public  License
32
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
33
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
34
*/
35
 
36
#include <private/epsimpl.h>                /*I "slepceps.h" I*/
37
#include <slepcblaslapack.h>
38
 
39
extern PetscErrorCode EPSProjectedKSSym(EPS,PetscInt,PetscInt,PetscReal*,PetscReal*,PetscScalar*,PetscScalar*,PetscReal*,PetscInt*);
40
 
2464 carcamgo 41
/**/
42
PetscInt   allKs,def,deg,db;
2459 carcamgo 43
 
44
/* Type of data characterizing a shift (place from where an eps is applied) */
45
typedef struct _n_shift *shift;
46
struct _n_shift{
47
  PetscReal     value;
48
  PetscInt      inertia;
2468 eromero 49
  PetscBool     comp[2]; //
2459 carcamgo 50
  shift         neighb[2];//
51
  PetscInt      index;    //
52
  PetscInt      neigs;    //
53
  PetscReal     ext[2];   //
54
  PetscInt      nsch[2];  //
55
  PetscReal     pert;     //
56
  PetscBool     deg;  //not used
57
};
58
 
59
/* Type of data  for storing the state of spectrum slicing*/
2464 carcamgo 60
struct _n_SR{
2470 jroman 61
  PetscReal       int0,int1; // extremes of the interval
2459 carcamgo 62
  PetscInt        dir; // determines the order of values in eig (+1 incr, -1 decr)
63
  PetscBool       hasEnd; // tells whether the interval has an end
64
  PetscInt        inertia0,inertia1;
65
  Vec             *V;
66
  PetscScalar     *eig;
67
  PetscInt        *perm;// permutation for keeping the eigenvalues in order
68
  PetscInt        numEigs; // number of eigenvalues in the interval
69
  PetscInt        indexEig;
70
  shift           sPres; // present shift
71
  shift           *pending;//pending shifts array
72
  PetscInt        nPend;// number of pending shifts
73
  PetscInt        maxPend;// size of "pending" array
74
  Vec             *VDef; // vector for deflation
75
  PetscInt        *idxDef;//for deflation
76
  PetscInt        nMAXCompl;
77
  PetscInt        iterCompl;
78
  PetscInt        itsKs;
79
  PetscInt        nShifts;//number of computed shifts
80
  shift           s0;// initial shift
81
  PetscReal       tolDeg;
82
  PetscInt        nDeg;//number of values coinciding with a shift
83
  PetscInt        defMin; //minimum amount of values for deflation
84
};
2464 carcamgo 85
typedef struct _n_SR  *SR;
86
 
87
/*
88
   Fills the fields of a shift structure
89
 
90
*/
2459 carcamgo 91
#undef __FUNCT__
92
#define __FUNCT__ "EPSCreateShift"
2470 jroman 93
static PetscErrorCode EPSCreateShift(EPS eps,PetscReal val, shift neighb0,shift neighb1)
2404 jroman 94
{
2459 carcamgo 95
  PetscErrorCode   ierr;
96
  shift            s,*pending2;
97
  PetscInt         i;
98
  SR               sr;
99
 
100
  PetscFunctionBegin;
101
  sr = (SR)(eps->data);
102
  ierr = PetscMalloc(sizeof(struct _n_shift),&s);CHKERRQ(ierr);
103
  s->value = val;
104
  s->neighb[0] = neighb0;
2464 carcamgo 105
  if(neighb0) neighb0->neighb[1] = s;
2459 carcamgo 106
  s->neighb[1] = neighb1;
2464 carcamgo 107
  if(neighb1) neighb1->neighb[0] = s;
2468 eromero 108
  s->comp[0] = PETSC_FALSE;
109
  s->comp[1] = PETSC_FALSE;
2459 carcamgo 110
  s->index = -1;
111
  s->neigs = 0;
112
  s->deg = PETSC_FALSE;
113
  s->nsch[0] = s->nsch[1]=0;
114
  // inserts in the stack of pending shifts
115
  // if needed, the array is resized
116
  if(sr->nPend >= sr->maxPend){
2464 carcamgo 117
    if(db>=1){ierr = PetscPrintf(PETSC_COMM_WORLD,"resizing pending shifts array\n");CHKERRQ(ierr);}
2459 carcamgo 118
    sr->maxPend *= 2;
119
    ierr = PetscMalloc((sr->maxPend)*sizeof(shift),&pending2);CHKERRQ(ierr);
120
    for(i=0;i < sr->nPend; i++)pending2[i] = sr->pending[i];
121
    ierr = PetscFree(sr->pending);CHKERRQ(ierr);
122
    sr->pending = pending2;
123
  }
124
  sr->pending[sr->nPend++]=s;
125
  sr->nShifts++;
126
  PetscFunctionReturn(0);
127
}
128
 
129
/* Provides next shift to be computed */
130
#undef __FUNCT__
131
#define __FUNCT__ "EPSExtractShift"
132
static PetscErrorCode EPSExtractShift(EPS eps){
133
  PetscErrorCode   ierr;
134
  PetscInt         iner;
135
  Mat              F;
136
  PC               pc;
137
  KSP              ksp;
138
  SR               sr;
139
 
140
  PetscFunctionBegin;  
141
  sr = (SR)(eps->data);
142
  if(sr->nPend > 0){
143
    sr->sPres = sr->pending[--sr->nPend];
144
    ierr = STSetShift(eps->OP, sr->sPres->value);CHKERRQ(ierr);
145
    ierr = STGetKSP(eps->OP, &ksp);CHKERRQ(ierr);
146
    ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
147
    ierr = PCFactorGetMatrix(pc,&F);CHKERRQ(ierr);
148
    ierr = MatGetInertia(F,&iner,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
149
    sr->sPres->inertia = iner;
150
    eps->target = sr->sPres->value;
151
    eps->nconv = 0;
152
    eps->reason = EPS_CONVERGED_ITERATING;
153
    eps->its =0;
154
   }else sr->sPres = PETSC_NULL;
155
   PetscFunctionReturn(0);
156
}
157
 
158
/*
2464 carcamgo 159
   Symmetric KrylovSchur adapted to spectrum slicing:
2459 carcamgo 160
   allows searching an specific amount of eigenvalues in the subintervals left and right.
161
   returns whether the search has succeed
162
*/
163
#undef __FUNCT__
164
#define __FUNCT__ "EPSKrylovSchur_Slice"
165
static PetscErrorCode EPSKrylovSchur_Slice(EPS eps)
166
{
2404 jroman 167
  PetscErrorCode ierr;
2459 carcamgo 168
  PetscInt       i,conv,k,l,lds,lt,nv,m,*iwork,p,j;
2404 jroman 169
  Vec            u=eps->work[0];
170
  PetscScalar    *Q;
2464 carcamgo 171
  PetscReal      *a,*b,*work,beta,*Qreal,rtmp;//
2404 jroman 172
  PetscBool      breakdown;
2459 carcamgo 173
  PetscInt       count0,count1;//nconv_prev;
174
  PetscReal      theta,lambda;
175
  shift          sPres;
176
  PetscBool      complIterating;/* shows whether iterations are made for completion */
177
  PetscBool       sch0,sch1;//shows whether values are looked after on each side
2471 jroman 178
  PetscInt        iterCompl=0,n0,n1;
2459 carcamgo 179
  //PetscReal       res;
2404 jroman 180
 
2459 carcamgo 181
  SR             sr;
182
 
2404 jroman 183
  PetscFunctionBegin;
2459 carcamgo 184
  /* spectrum slicing data */
185
  sr = (SR)eps->data;
186
  sPres = sr->sPres;
187
  complIterating =PETSC_FALSE;
188
  sch1 = sch0 = PETSC_TRUE;
2404 jroman 189
  lds = PetscMin(eps->mpd,eps->ncv);
190
  ierr = PetscMalloc(lds*lds*sizeof(PetscReal),&work);CHKERRQ(ierr);
191
  ierr = PetscMalloc(lds*lds*sizeof(PetscScalar),&Q);CHKERRQ(ierr);
192
  ierr = PetscMalloc(2*lds*sizeof(PetscInt),&iwork);CHKERRQ(ierr);
193
  lt = PetscMin(eps->nev+eps->mpd,eps->ncv);
2459 carcamgo 194
  ierr = PetscMalloc(lt*sizeof(PetscReal),&a);CHKERRQ(ierr);
195
  ierr = PetscMalloc(lt*sizeof(PetscReal),&b);CHKERRQ(ierr);
196
  count0=0;count1=0; // found on both sides
197
 
2404 jroman 198
  /* Get the starting Lanczos vector */
199
  ierr = EPSGetStartVector(eps,0,eps->V[0],PETSC_NULL);CHKERRQ(ierr);
200
  l = 0;
201
  /* Restart loop */
202
  while (eps->reason == EPS_CONVERGED_ITERATING) {
203
    eps->its++;
204
 
205
    /* Compute an nv-step Lanczos factorization */
206
    m = PetscMin(eps->nconv+eps->mpd,eps->ncv);
2459 carcamgo 207
 
2404 jroman 208
    ierr = EPSFullLanczos(eps,a+l,b+l,eps->V,eps->nconv+l,&m,u,&breakdown);CHKERRQ(ierr);
209
    nv = m - eps->nconv;
210
    beta = b[nv-1];
211
 
2459 carcamgo 212
    /* Solve projected problem and compute residual norm estimates */
2404 jroman 213
    ierr = EPSProjectedKSSym(eps,nv,l,a,b,eps->eigr+eps->nconv,Q,work,iwork);CHKERRQ(ierr);
214
    /* Check convergence */
215
    ierr = EPSKrylovConvergence(eps,PETSC_TRUE,eps->nconv,nv,PETSC_NULL,nv,Q,eps->V+eps->nconv,nv,beta,1.0,&k,PETSC_NULL);CHKERRQ(ierr);
2459 carcamgo 216
    if(allKs ==1){//option for accepting all converging values
2464 carcamgo 217
      Qreal = (PetscReal*)Q;//
2459 carcamgo 218
      conv=k=j=0;
219
      for(i=0;i<nv;i++)if(eps->errest[eps->nconv+i] < eps->tol)conv++;
220
      for(i=0;i<nv;i++){
221
        if(eps->errest[eps->nconv+i] < eps->tol){
222
          iwork[j++]=i;
223
        }else iwork[conv+k++]=i;
224
      }
2470 jroman 225
      for(i=0;i<nv;i++) a[i]=PetscRealPart(eps->eigr[eps->nconv+i]);
2459 carcamgo 226
      for(i=0;i<nv;i++){
227
        eps->eigr[eps->nconv+i] = a[iwork[i]];
228
      }
229
      for( i=0;i<nv;i++){
230
        p=iwork[i];
231
        if(p!=i){
232
          j=i+1;
233
          while(iwork[j]!=i)j++;
234
          iwork[j]=p;iwork[i]=i;
235
          for(k=0;k<nv;k++){
2464 carcamgo 236
            rtmp=Qreal[k+p*nv];Qreal[k+p*nv]=Qreal[k+i*nv];Qreal[k+i*nv]=rtmp;
237
            //rtmp=Q[k+p*nv];Q[k+p*nv]=Q[k+i*nv];Q[k+i*nv]=rtmp;
2459 carcamgo 238
          }
239
        }
240
      }
241
      k=eps->nconv+conv;
242
    }
243
  /*checking proximity to an eigenvalue*/
2464 carcamgo 244
 
2459 carcamgo 245
  if(deg==1){
246
    for(i=0;i < k; i++){
247
      theta = PetscRealPart(eps->eigr[i]);
2465 jroman 248
      if(PetscAbsReal(theta*sPres->value*eps->tol*10)>1){
2464 carcamgo 249
        if(db>=1){ierr = PetscPrintf(PETSC_COMM_WORLD,"DEGENERATED SHIFT\n");CHKERRQ(ierr);}
2459 carcamgo 250
        sr->nDeg++;
2464 carcamgo 251
        sPres->deg = PETSC_TRUE;
2459 carcamgo 252
      }else break;
253
    }
254
  }
255
  /*
256
  if(deg == 1 && sr->nDeg > 0){
257
    eps->reason = EPS_CONVERGED_TOL;
258
  }else{
259
  */
260
    /* Checking values obtained for completing */
261
    count0=count1=0;
262
    for(i=0;i<k;i++){      
263
      theta = PetscRealPart(eps->eigr[i]);
264
      lambda = sPres->value + 1/theta;
265
      if( ((sr->dir)*theta < 0) && ((sr->dir)*(lambda - sPres->ext[0]) > 0))count0++;
266
      if( ((sr->dir)*theta > 0) && ((sr->dir)*(sPres->ext[1] - lambda) > 0))count1++;
267
    }
2404 jroman 268
 
2459 carcamgo 269
    /* checks completion */
270
    if( (!sch0||count0 >= sPres->nsch[0]) && (!sch1 ||count1 >= sPres->nsch[1]) ) {
271
      eps->reason = EPS_CONVERGED_TOL;
272
    }else {
273
      if(!complIterating && eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
274
      if(complIterating){
275
        if(--iterCompl <= 0) eps->reason = EPS_DIVERGED_ITS;
276
      }else if (k >= eps->nev) {//eps->reason = EPS_CONVERGED_TOL;
277
        n0 = sPres->nsch[0]-count0;
278
        n1 = sPres->nsch[1]-count1;
279
        if( sr->iterCompl>0 && ( (n0>0&& n0<= sr->nMAXCompl)||(n1>0&&n1<=sr->nMAXCompl) )){
280
          complIterating = PETSC_TRUE;
2464 carcamgo 281
          if(db>=1){ierr = PetscPrintf(PETSC_COMM_WORLD,"iterating for completion nMAXComp=%d\n",sr->nMAXCompl);CHKERRQ(ierr);}
2459 carcamgo 282
          if(n0 >sr->nMAXCompl)sch0 = PETSC_FALSE;
283
          if(n1 >sr->nMAXCompl)sch1 = PETSC_FALSE;
284
          iterCompl = sr->iterCompl;
285
        }else eps->reason = EPS_CONVERGED_TOL;
286
      }      
287
    }
288
 
2404 jroman 289
    /* Update l */
290
    if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0;
291
    else l = (eps->nconv+nv-k)/2;
292
 
293
    if (eps->reason == EPS_CONVERGED_ITERATING) {
294
      if (breakdown) {
295
        /* Start a new Lanczos factorization */
2499 jroman 296
        ierr = PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%D norm=%G)\n",eps->its,beta);CHKERRQ(ierr);
2404 jroman 297
        ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
298
        if (breakdown) {
299
          eps->reason = EPS_DIVERGED_BREAKDOWN;
2499 jroman 300
          ierr = PetscInfo(eps,"Unable to generate more start vectors\n");CHKERRQ(ierr);
2404 jroman 301
        }
302
      } else {
303
        /* Prepare the Rayleigh quotient for restart */
304
        for (i=0;i<l;i++) {
305
          a[i] = PetscRealPart(eps->eigr[i+k]);
306
          b[i] = PetscRealPart(Q[nv-1+(i+k-eps->nconv)*nv]*beta);
307
        }
308
      }
309
    }
310
    /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
311
    ierr = SlepcUpdateVectors(nv,eps->V+eps->nconv,0,k+l-eps->nconv,Q,nv,PETSC_FALSE);CHKERRQ(ierr);
312
    /* Normalize u and append it to V */
313
    if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
314
      ierr = VecAXPBY(eps->V[k+l],1.0/beta,0.0,u);CHKERRQ(ierr);
315
    }
316
 
317
    ierr = EPSMonitor(eps,eps->its,k,eps->eigr,eps->eigi,eps->errest,nv+eps->nconv);CHKERRQ(ierr);
2459 carcamgo 318
    //nconv_prev = eps->nconv;//
2404 jroman 319
    eps->nconv = k;
2459 carcamgo 320
  }
321
  /* check for completion */
2468 eromero 322
  sPres->comp[0] = (count0 >= sPres->nsch[0])?PETSC_TRUE:PETSC_FALSE;
323
  sPres->comp[1] = (count1 >= sPres->nsch[1])?PETSC_TRUE:PETSC_FALSE;
2464 carcamgo 324
  if(db>=1){ierr = PetscPrintf(PETSC_COMM_WORLD," found count0=%d(of %d) and count1=%d(of %d)\n",count0,sPres->nsch[0],count1,sPres->nsch[1]);CHKERRQ(ierr);}
2459 carcamgo 325
  sr->itsKs += eps->its;  
326
 
2404 jroman 327
  ierr = PetscFree(Q);CHKERRQ(ierr);
328
  ierr = PetscFree(a);CHKERRQ(ierr);
329
  ierr = PetscFree(b);CHKERRQ(ierr);
330
  ierr = PetscFree(work);CHKERRQ(ierr);
331
  ierr = PetscFree(iwork);CHKERRQ(ierr);
332
  PetscFunctionReturn(0);
333
}
334
 
2459 carcamgo 335
/*
336
  obtains value of subsequent shift
337
*/
338
#undef __FUNCT__
339
#define __FUNCT__ "EPSGetNewShiftValue"
340
static PetscErrorCode EPSGetNewShiftValue(EPS eps,PetscInt side,PetscReal *newS){
341
  PetscReal   lambda,d_prev;//pert,d,d_avg;
342
  PetscInt    i,idxP;
343
  SR          sr;
344
  shift       sPres;
345
 
346
  PetscFunctionBegin;  
347
  sr = (SR)eps->data;
348
  sPres = sr->sPres;
349
/*  
350
  pert = 0;
351
  if(sPres->neigs >0){
352
      idxP=0;//number of computed eigenvalues previous to sPres->value
353
      for(i=sPres->index;i< sPres->index + sPres->neigs;i++){
354
        lambda = PetscRealPart(sr->eig[i]);
355
        if((sr->dir)*(lambda - sPres->value) < 0)idxP++;
356
        else break;
357
      }
358
      //middle point between shift and previous/posterior value
359
      pert = PetscAbs(sr->eig[sPres->index+idxP]- sr->sPres->value)/2;
360
  }
361
*/
2464 carcamgo 362
  if( sPres->neighb[side]){
2459 carcamgo 363
  /* completing a previous interval */
364
    *newS=(sPres->value + sPres->neighb[side]->value)/2;
365
 
366
  }else{ //(only for side=1). creating a new interval.
367
    if(sPres->neigs==0){// no value has been accepted
2464 carcamgo 368
      if(sPres->neighb[0]){
2459 carcamgo 369
        // multiplying by 10 the previous distance
2465 jroman 370
        *newS = sPres->value + 10*(sr->dir)*PetscAbsReal(sPres->value - sPres->neighb[0]->value);
2459 carcamgo 371
      }else {//first shift
372
        if(eps->nconv != 0){
373
           //unaccepted values give information for next shift
374
           idxP=0;//number of values left from shift
375
           for(i=0;i<eps->nconv;i++){
376
             lambda = PetscRealPart(eps->eigr[i]);
377
             if( (sr->dir)*(lambda - sPres->value) <0)idxP++;
378
             else break;
379
           }
380
           //avoiding substraction of eigenvalues (might be the same).
381
           if(idxP>0){
2465 jroman 382
             d_prev = PetscAbsReal(sPres->value - PetscRealPart(eps->eigr[0]))/(idxP+0.3);
2459 carcamgo 383
           }else {
2465 jroman 384
             d_prev = PetscAbsReal(sPres->value - PetscRealPart(eps->eigr[eps->nconv-1]))/(eps->nconv+0.3);
2459 carcamgo 385
           }
386
           *newS = sPres->value + ((sr->dir)*d_prev*eps->nev)/2;
387
        }else{//no values found, no information for next shift
388
          // changing the end of the interval
389
        }
390
      }
391
    }else{// accepted values found
392
      //average distance of values in previous subinterval
393
      shift s = sPres->neighb[0];
2464 carcamgo 394
      while(s && PetscAbs(s->inertia - sPres->inertia)==0){
2459 carcamgo 395
        s = s->neighb[0];//looking for previous shifts with eigenvalues within
396
      }
2464 carcamgo 397
      if(s){
2465 jroman 398
        d_prev = PetscAbsReal( (sPres->value - s->value)/(sPres->inertia - s->inertia));
2470 jroman 399
      }else{//first shift. average distance obtained with values in this shift        
2465 jroman 400
        d_prev = PetscAbsReal( PetscRealPart(sr->eig[sPres->index+sPres->neigs-1]) - sPres->value)/(sPres->neigs+0.3);
2459 carcamgo 401
      }
2470 jroman 402
      // average distance is used for next shift by adding it to value on the right or to shift
2465 jroman 403
      if( (sr->dir)*(PetscRealPart(sr->eig[sPres->index + sPres->neigs -1]) - sPres->value) >0){
404
        *newS = PetscRealPart(sr->eig[sPres->index + sPres->neigs -1])+ ((sr->dir)*d_prev*(eps->nev))/2;  
2459 carcamgo 405
      }else{//last accepted value is on the left of shift. adding to shift.
406
        *newS = sPres->value + ((sr->dir)*d_prev*(eps->nev))/2;
407
      }
408
    //}
409
    }
410
    //end of interval can not be surpassed
411
    if(sr->hasEnd && ((sr->dir)*(*newS - sr->int1) > 0))*newS=sr->int1;
412
  }//of neighb[side]==null
413
  PetscFunctionReturn(0);
414
}
415
 
416
/*
417
  function for sorting an array of real values
418
*/
419
#undef __FUNCT__
420
#define __FUNCT__ "sortRealEigenvalues"
421
static PetscErrorCode sortRealEigenvalues(PetscScalar *r,PetscInt *perm,PetscInt nr,PetscBool prev,PetscInt dir)
422
{
423
  PetscReal      re;
424
  PetscInt       i,j,tmp;
425
 
426
  PetscFunctionBegin;
2464 carcamgo 427
  if(!prev) for (i=0; i < nr; i++) { perm[i] = i; }
2459 carcamgo 428
  /* insertion sort */
429
  for (i=1; i < nr; i++) {
430
    re = PetscRealPart(r[perm[i]]);
431
    j = i-1;
432
    while ( j>=0 && dir*(re - PetscRealPart(r[perm[j]])) <= 0 ) {
433
      tmp = perm[j]; perm[j] = perm[j+1]; perm[j+1] = tmp; j--;
434
    }
435
  }
436
  PetscFunctionReturn(0);
437
}
438
 
439
/* Stores the pairs obtained since the last shift in the global arrays */
440
#undef __FUNCT__
441
#define __FUNCT__ "EPSStoreEigenpairs"
442
PetscErrorCode EPSStoreEigenpairs(EPS eps)
443
{
444
  PetscErrorCode ierr;
445
  PetscReal      lambda,error;
446
  PetscInt       i,count;
447
  PetscBool      cond;
448
  SR             sr;
449
  shift          sPres;
450
 
451
  PetscFunctionBegin;
452
  sr = (SR)(eps->data);
453
  sPres = sr->sPres;
454
  sPres->index = sr->indexEig;
455
  count = sr->indexEig;
2464 carcamgo 456
  error=0;
2459 carcamgo 457
  /* backtransform */
458
  for(i=0;i < eps->nconv; i++) eps->eigr[i] =  sPres->value + 1.0/(eps->eigr[i]);
459
  /* sort eigenvalues */
460
  ierr = sortRealEigenvalues(eps->eigr,eps->perm,eps->nconv,PETSC_FALSE,sr->dir);
461
  /* values stored in global array */
462
  // condition for avoiding comparing whith a non-existing end.
2468 eromero 463
  cond = (!sPres->neighb[1] && !sr->hasEnd)?PETSC_TRUE:PETSC_FALSE;
2459 carcamgo 464
  for( i=0; i < eps->nconv ;i++ ){
465
    lambda = PetscRealPart(eps->eigr[eps->perm[i]]);
2464 carcamgo 466
    if(db>1){ierr = EPSComputeRelativeError(eps,eps->perm[i],&error);CHKERRQ(ierr);}
2459 carcamgo 467
    if( ( ((sr->dir)*(lambda - sPres->ext[0]) > 0) && ( cond || ((sr->dir)*(lambda - sPres->ext[1]) < 0)) ) ){
2464 carcamgo 468
      if(count>=sr->numEigs){//Error found
469
        ierr = PetscPrintf(PETSC_COMM_WORLD,"Number of reserved values exceeded  lambda=%.14g\n",lambda);
470
        break;
471
      }  
2459 carcamgo 472
      sr->eig[count] = lambda;
473
      ierr = VecCopy(eps->V[eps->perm[i]], sr->V[count]);CHKERRQ(ierr);
2464 carcamgo 474
      if(db>1){ierr = PetscPrintf(PETSC_COMM_WORLD,"i=%d perm[i]=%d lambda=%.14g error=%g indexEig=%d\n",i,eps->perm[i],lambda,error,count);CHKERRQ(ierr);}
2459 carcamgo 475
      count++;
2464 carcamgo 476
    }else if(db>1){ierr = PetscPrintf(PETSC_COMM_WORLD,"i=%d perm[i]=%d lambda=%.14g NOT VALID\n",i,eps->perm[i],lambda);CHKERRQ(ierr);}
2459 carcamgo 477
  }
478
  sPres->neigs = count - sr->indexEig;
2464 carcamgo 479
  if(db>=1){PetscPrintf(PETSC_COMM_WORLD," stored between %d and %d\n",sr->indexEig,count);CHKERRQ(ierr);}
2459 carcamgo 480
  sr->indexEig = count;
481
 
482
  ierr = sortRealEigenvalues(sr->eig,sr->perm,count,PETSC_TRUE,sr->dir);CHKERRQ(ierr);
483
  PetscFunctionReturn(0);
484
}
485
 
486
#undef __FUNCT__
487
#define __FUNCT__ "EPSLookForDeflation"
488
PetscErrorCode EPSLookForDeflation(EPS eps)
489
{
2464 carcamgo 490
  PetscErrorCode  ierr;
2459 carcamgo 491
  PetscReal       val,lambda,lambda2;
492
  PetscInt        i,count0=0,count1=0;
493
  shift           sPres;
494
  PetscInt        ini,fin,defMin,k,idx0,idx1;
495
  PetscBool       consec;
496
  SR              sr;
497
 
498
  PetscFunctionBegin;
499
  sr = (SR)(eps->data);
500
  sPres = sr->sPres;
501
  defMin = sr->defMin;
502
 
2464 carcamgo 503
  if(sPres->neighb[0]) ini = (sr->dir)*(sPres->neighb[0]->inertia - sr->inertia0);
2459 carcamgo 504
  else ini = 0;
505
  fin = sr->indexEig;
506
  // selection of ends for searching new values
507
  // later modified with version def=0
2464 carcamgo 508
  if(!sPres->neighb[0]) sPres->ext[0] = sr->int0;//first shift
2459 carcamgo 509
  else sPres->ext[0] = sPres->neighb[0]->value;
2464 carcamgo 510
  if(!sPres->neighb[1]) {
2459 carcamgo 511
    if(sr->hasEnd) sPres->ext[1] = sr->int1;
512
    else sPres->ext[1] = (sr->dir > 0)?PETSC_MAX_REAL:PETSC_MIN_REAL;
513
  }else sPres->ext[1] = sPres->neighb[1]->value;
2464 carcamgo 514
  if(db>1){ierr = PetscPrintf(PETSC_COMM_WORLD,"ext0=%g ext1=%g\n",sPres->ext[0],sPres->ext[1]);CHKERRQ(ierr);}
2459 carcamgo 515
  //selection of values between right and left ends
516
  for(i=ini;i<fin;i++){
517
    val=PetscRealPart(sr->eig[sr->perm[i]]);
518
    //values to the right of left shift
519
    if( (sr->dir)*(val - sPres->ext[1]) < 0 ){
520
      if((sr->dir)*(val - sPres->value) < 0)count0++;
521
      else count1++;
522
    }else break;
523
  }
524
  // the number of values on each side are found
2464 carcamgo 525
  if(sPres->neighb[0])
2459 carcamgo 526
     sPres->nsch[0] = (sr->dir)*(sPres->inertia - sPres->neighb[0]->inertia)-count0;
527
  else sPres->nsch[0] = 0;
528
 
2464 carcamgo 529
  if(sPres->neighb[1])
2459 carcamgo 530
    sPres->nsch[1] = (sr->dir)*(sPres->neighb[1]->inertia - sPres->inertia) - count1;
531
  else sPres->nsch[1] = (sr->dir)*(sr->inertia1 - sPres->inertia);
532
 
533
  //completing vector of indexes for deflation
2464 carcamgo 534
  if(def==0 && !sPres->neighb[1]){//new interval && no deflation
535
    if(db>1){ierr = PetscPrintf(PETSC_COMM_WORLD,"def=0 y neig1=null\n");CHKERRQ(ierr);}
536
    k=0;
537
    for(i=fin-1;i>ini;i--){
538
      k++;
539
      lambda = PetscRealPart(sr->eig[sr->perm[i]]);
540
      lambda2 = PetscRealPart(sr->eig[sr->perm[i-1]]);
2465 jroman 541
      if( PetscAbsReal((lambda - lambda2)/lambda) > sr->tolDeg){//relative tolerance
2464 carcamgo 542
        break;
2459 carcamgo 543
      }
2464 carcamgo 544
    }
545
    // if i!=ini values for i and i-1 more than toldeg apart
546
    if(db>1){ierr = PetscPrintf(PETSC_COMM_WORLD,"lookDef i=%d ini=%d\n",i,ini);CHKERRQ(ierr);}
547
    if(i<=ini){
548
      sPres->ext[0] = sPres->value;
549
    }else{//middle point
550
       sPres->ext[0] = (PetscRealPart(sr->eig[sr->perm[i]])+PetscRealPart(sr->eig[sr->perm[i-1]]))/2;        
551
    }
552
    idx0=ini+count0-k;
553
    idx1=ini+count0;
554
    if(db>1){ierr = PetscPrintf(PETSC_COMM_WORLD,"ext0=%g ext1=%g idx0=%d idx1=%d count0=%d k=%d\n",sPres->ext[0],sPres->ext[1],idx0,idx1,count0,k);CHKERRQ(ierr);}
2459 carcamgo 555
  }else{  //completing a subinterval or without deflation
556
    k = PetscMax(0,defMin-count0);
557
    idx0 = PetscMax(0,ini-k);
558
    if(def==0 && sPres->nsch[0]==0){//no deflation towards 0
559
      idx0 = ini + count0;
560
      sPres->ext[0] = sPres->value;
561
    }
562
    k = PetscMax(0,defMin-count1);
563
    idx1 = PetscMin(sr->indexEig,ini+count0+count1+k);
564
    if(def==0 && sPres->nsch[1]==0){//no deflation towards 1
565
      idx1 = ini + count0;
566
      sPres->ext[1] = sPres->value;
567
    }
568
  }
569
  k=0;
570
  for(i=idx0;i<idx1;i++)sr->idxDef[k++]=sr->perm[i];
571
   ///// info
2464 carcamgo 572
  if(db>=1){ierr = PetscPrintf(PETSC_COMM_WORLD," deflated %d in [0] and %d in [1]",count0,count1);CHKERRQ(ierr);}
2459 carcamgo 573
    /////  
574
 
575
  // check for consecutives
576
  consec=PETSC_TRUE;
577
  for(i=1;i<k;i++)if(sr->idxDef[i]!=sr->idxDef[i-1]+1){consec = PETSC_FALSE; break;}
578
  // if not consecutives, copied in array
579
//if(consec){
580
//  V o which
581
//else{
582
  for(i=0;i<k;i++)sr->VDef[i]=sr->V[sr->idxDef[i]];
583
  eps->DS = sr->VDef;
584
//}
585
  eps->nds = k;
586
  //////info
2464 carcamgo 587
  if(db>=1){
588
    if(consec){ ierr = PetscPrintf(PETSC_COMM_WORLD," (%d consecutive values)\n",k);CHKERRQ(ierr);}
589
    else{ ierr = PetscPrintf(PETSC_COMM_WORLD," (%d non consecutive values)\n",k);CHKERRQ(ierr);}
2459 carcamgo 590
  }
591
 
592
  PetscFunctionReturn(0);
593
}
594
 
595
#undef __FUNCT__
596
#define __FUNCT__ "EPSSolve_KrylovSchur_Slice"
597
PetscErrorCode EPSSolve_KrylovSchur_Slice(EPS eps)
598
{
599
  PetscErrorCode ierr;
600
  PetscInt       i,j;
601
  PetscInt       imax,jmax;
602
  PetscReal      newS;
603
  KSP            ksp;
604
  PC             pc;
605
  Mat            B,F;  
606
  PetscScalar    *eigi;
607
  Vec            t,w;
608
  SR             sr;
2465 jroman 609
  PetscReal      orthMax;
610
  PetscScalar    inerd;
2459 carcamgo 611
  double         t1,t2;
612
 
613
  PetscFunctionBegin;
614
  eps->trackall = PETSC_TRUE;
2464 carcamgo 615
  allKs = 0;
2459 carcamgo 616
  def = 1;
617
  deg=0;
2464 carcamgo 618
  db = 0;
619
  ierr = PetscOptionsGetInt(PETSC_NULL,"-db",&db,PETSC_NULL);CHKERRQ(ierr);
2459 carcamgo 620
  ierr = PetscOptionsGetInt(PETSC_NULL,"-deg",&deg,PETSC_NULL);CHKERRQ(ierr);
621
  ierr = PetscOptionsGetInt(PETSC_NULL,"-def",&def,PETSC_NULL);CHKERRQ(ierr);
622
  ierr = PetscOptionsGetInt(PETSC_NULL,"-allKs",&allKs,PETSC_NULL);CHKERRQ(ierr);
2464 carcamgo 623
  if(db>=1){ierr = PetscPrintf(PETSC_COMM_WORLD,"Options: allKs=%d, def=%d, deg=%d \n",allKs,def,deg);CHKERRQ(ierr);}
624
  ierr = PetscMalloc(sizeof(struct _n_SR),&sr);CHKERRQ(ierr);
2459 carcamgo 625
  eps->data = sr;
2473 jroman 626
  sr->tolDeg = PetscSqrtReal(eps->tol);//default
2459 carcamgo 627
  ierr = PetscOptionsGetReal(PETSC_NULL,"-toldeg",&sr->tolDeg,PETSC_NULL);CHKERRQ(ierr);
2464 carcamgo 628
  if(db>=1){ierr = PetscPrintf(PETSC_COMM_WORLD,"toldeg=%g\n",sr->tolDeg);CHKERRQ(ierr);}
2459 carcamgo 629
  sr->defMin = 0;
630
  ierr = PetscOptionsGetInt(PETSC_NULL,"-defMin",&sr->defMin,PETSC_NULL);CHKERRQ(ierr);
631
  if(def==0)sr->defMin =0;
632
  //checking presence of ends and finding direction
633
  if( eps->inta > PETSC_MIN_REAL){
634
    sr->int0 = eps->inta;
635
    sr->int1 = eps->intb;
636
    sr->dir = 1;
637
    if(eps->intb >= PETSC_MAX_REAL){ /* right-open interval */
638
      sr->hasEnd = PETSC_FALSE;
639
      sr->inertia1 = eps->n;
640
    }else sr->hasEnd = PETSC_TRUE;
641
  }else{ /* left-open interval */
642
    sr->int0 = eps->intb;
643
    sr->int1 = eps->inta;
644
    sr->dir = -1;
645
    sr->hasEnd = PETSC_FALSE;
646
    sr->inertia1 = 0;
647
  }
2464 carcamgo 648
  if(db>=1){ierr = PetscPrintf(PETSC_COMM_WORLD,"dir=%d int0=%g\n",sr->dir,sr->int0);CHKERRQ(ierr);}
2459 carcamgo 649
  sr->nMAXCompl = 0;
650
  ierr = PetscOptionsGetInt(PETSC_NULL,"-comp",&sr->nMAXCompl,PETSC_NULL);
651
  sr->iterCompl = sr->nMAXCompl+5;//=======
2464 carcamgo 652
  //i = PetscMin(eps->mpd,eps->ncv);//=======
2459 carcamgo 653
  //ierr = PetscMalloc(i*sizeof(PetscReal),&sr->aprox);CHKERRQ(ierr);//======
654
  // array of pending shifts
655
  sr->maxPend = 100;//initial size;
656
  ierr = PetscMalloc((sr->maxPend)*sizeof(shift),&sr->pending);CHKERRQ(ierr);
657
  if(sr->hasEnd){
658
    ierr = STGetKSP(eps->OP, &ksp);CHKERRQ(ierr);
659
    ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr);
660
    ierr = PCFactorGetMatrix(pc,&F);CHKERRQ(ierr);
661
    /* not looking for values in b (just inertia).*/
662
    ierr = MatGetInertia(F,&sr->inertia1,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
663
  }
664
  sr->nShifts = 0;
665
  sr->nPend = 0;
666
  ierr = EPSCreateShift(eps,sr->int0,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
667
  ierr = EPSExtractShift(eps);
668
  sr->s0 = sr->sPres;
669
  sr->inertia0 = sr->s0->inertia;
670
  sr->numEigs = (sr->dir)*(sr->inertia1 - sr->inertia0);
671
  sr->indexEig = 0;
672
  sr->itsKs = 0;
673
  sr->nDeg = 0;
2464 carcamgo 674
  if(db>=1){
675
    ierr = PetscPrintf(PETSC_COMM_WORLD,"dir=%d inertia in 0(=%g) %d and in 1(=%g) %d\n",sr->dir,sr->int0,sr->inertia0,sr->int1,sr->inertia1);CHKERRQ(ierr);
676
    ierr = PetscPrintf(PETSC_COMM_WORLD,"numEigs=%d\n\n",sr->numEigs);
677
  }
2470 jroman 678
  /* only with eigenvalues present in the interval ...*/
2464 carcamgo 679
  if(sr->numEigs==0){
680
    eps->reason = EPS_CONVERGED_TOL;
681
    PetscFunctionReturn(0);
682
  }
2459 carcamgo 683
 
2464 carcamgo 684
  /* memory reservation for eig, V and perm */
685
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscScalar),&sr->eig);CHKERRQ(ierr);
686
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscScalar),&eigi);CHKERRQ(ierr);
687
  for(i=0;i<sr->numEigs;i++)eigi[i]=0;
688
  ierr = VecCreateMPI(((PetscObject)eps)->comm,eps->nloc,PETSC_DECIDE,&t);CHKERRQ(ierr);
689
  ierr = VecDuplicateVecs(t,sr->numEigs,&sr->V);CHKERRQ(ierr);
690
  ierr = VecDestroy(&t);CHKERRQ(ierr);
691
  // vector for maintaining order of eigenvalues
692
  ierr = PetscMalloc((sr->numEigs)*sizeof(PetscInt),&sr->perm);CHKERRQ(ierr);
693
  for(i=0;i< sr->numEigs;i++)sr->perm[i]=i;
694
  // vectors for deflation
695
  ierr = PetscMalloc((sr->numEigs+sr->defMin)*sizeof(PetscInt),&sr->idxDef);CHKERRQ(ierr);
696
  ierr = PetscMalloc((sr->numEigs)*sizeof(Vec),&sr->VDef);CHKERRQ(ierr);
697
  sr->indexEig = 0;
2459 carcamgo 698
 
2464 carcamgo 699
  t1 = MPI_Wtime();
700
  while(sr->sPres){
2459 carcamgo 701
 
2464 carcamgo 702
    //////////info
703
    if(db>=1){
704
      if(sr->sPres->neighb[1]){ierr = PetscPrintf(PETSC_COMM_WORLD,"Completing ");CHKERRQ(ierr);}
705
      else {ierr = PetscPrintf(PETSC_COMM_WORLD,"New ");CHKERRQ(ierr);}
706
      ierr = PetscPrintf(PETSC_COMM_WORLD,"shift: %.14g (s0=",sr->sPres->value);CHKERRQ(ierr);
707
      if (sr->sPres->neighb[0]){ierr = PetscPrintf(PETSC_COMM_WORLD,"%g",sr->sPres->neighb[0]->value);CHKERRQ(ierr);}
708
      ierr = PetscPrintf(PETSC_COMM_WORLD," s1=");CHKERRQ(ierr);
709
      if (sr->sPres->neighb[1]){ierr = PetscPrintf(PETSC_COMM_WORLD,"%g",sr->sPres->neighb[1]->value);CHKERRQ(ierr);}
710
      ierr = PetscPrintf(PETSC_COMM_WORLD,")\n");CHKERRQ(ierr);
2459 carcamgo 711
    }
2464 carcamgo 712
    ///////////
713
 
714
    /* search for deflation */
715
    ierr = EPSLookForDeflation(eps);CHKERRQ(ierr);
716
    /* krylovSchur */
717
    ierr = EPSKrylovSchur_Slice(eps);CHKERRQ(ierr);
718
    ierr = EPSStoreEigenpairs(eps);CHKERRQ(ierr);
719
    /* select new shift */
2468 eromero 720
    if(!sr->sPres->comp[1]){
2464 carcamgo 721
      ierr = EPSGetNewShiftValue(eps,1,&newS);CHKERRQ(ierr);
722
      ierr = EPSCreateShift(eps,newS,sr->sPres,sr->sPres->neighb[1]);
723
    }
2468 eromero 724
    if(!sr->sPres->comp[0]){
2464 carcamgo 725
      // completing earlier interval
726
      ierr = EPSGetNewShiftValue(eps,0,&newS);CHKERRQ(ierr);
727
      ierr = EPSCreateShift(eps,newS,sr->sPres->neighb[0],sr->sPres);
728
    }
729
    /* preparing for a new search of values */
730
    ierr = EPSExtractShift(eps);CHKERRQ(ierr);
731
  }
732
  t2 = MPI_Wtime();
733
  /* checking orthogonality */
734
  if(db>=1){
2459 carcamgo 735
    ierr = STGetOperators(eps->OP,PETSC_NULL,&B);CHKERRQ(ierr);
736
    orthMax=0;
737
    imax=jmax=-1;
738
    ierr = VecDuplicate(sr->V[0],&w);CHKERRQ(ierr);
739
    for(i=0;i < sr->indexEig; i++){
2464 carcamgo 740
      ierr = MatMult(B,sr->V[i],w);CHKERRQ(ierr);
2459 carcamgo 741
      for(j=0;j < sr->indexEig;j++){
2465 jroman 742
        if(i != j) {
743
          ierr = VecDot(w,sr->V[j],&inerd);CHKERRQ(ierr);
744
          if(PetscRealPart(inerd)>orthMax){orthMax = PetscRealPart(inerd); imax = i; jmax = j;}
745
        }
2459 carcamgo 746
      }
747
    }
748
    ierr = VecDestroy(&w);CHKERRQ(ierr);    
2464 carcamgo 749
    ierr = PetscPrintf(PETSC_COMM_WORLD,"\nStored indexEig=%d (of %d)\n (orthog max %g in i=%d j=%d)\n\n",sr->indexEig,sr->numEigs,orthMax,imax,jmax);CHKERRQ(ierr);
750
    ierr = PetscPrintf(PETSC_COMM_WORLD," time %g\n",t2-t1);CHKERRQ(ierr);
751
    ierr = PetscPrintf(PETSC_COMM_WORLD," number of shifts: %d\n",sr->nShifts);CHKERRQ(ierr);
752
  }
753
  /* updating eps values prior to exit */
754
  //ierr = EPSFreeSolution(eps);
755
  ierr = VecDestroyVecs(eps->allocated_ncv,&eps->V);CHKERRQ(ierr);
756
  eps->V = sr->V;
757
  ierr = PetscFree(eps->eigr);CHKERRQ(ierr);
758
  ierr = PetscFree(eps->eigi);CHKERRQ(ierr);
759
  eps->eigr = sr->eig;
760
  eps->eigi = eigi;
761
  eps->its = sr->itsKs;
762
  eps->ncv = eps->allocated_ncv = sr->numEigs;
763
  ierr = PetscFree(eps->errest);CHKERRQ(ierr);
764
  ierr = PetscFree(eps->errest_left);CHKERRQ(ierr);
765
  ierr = PetscMalloc(eps->ncv*sizeof(PetscReal),&eps->errest);CHKERRQ(ierr);
766
  ierr = PetscMalloc(eps->ncv*sizeof(PetscReal),&eps->errest_left);CHKERRQ(ierr);
767
  ierr = PetscFree(eps->perm);CHKERRQ(ierr);
768
  eps->perm = sr->perm;
769
  eps->nconv = sr->indexEig;
770
  eps->reason = EPS_CONVERGED_TOL;
771
  eps->nds = 0;
772
  eps->DS = PETSC_NULL;
773
  ierr = PetscFree(sr->VDef);CHKERRQ(ierr);
774
  ierr = PetscFree(sr->idxDef);CHKERRQ(ierr);
775
  ierr = PetscFree(sr->pending);CHKERRQ(ierr);
776
  // reviewing list of shifts to free memmory
777
  shift s = sr->s0;
778
  if(s){
779
    while(s->neighb[1]){
780
      s = s->neighb[1];
781
      ierr = PetscFree(s->neighb[0]);CHKERRQ(ierr);
2459 carcamgo 782
    }
2464 carcamgo 783
    ierr = PetscFree(s);CHKERRQ(ierr);
2459 carcamgo 784
  }
2464 carcamgo 785
  ierr = PetscFree(sr);CHKERRQ(ierr);
2459 carcamgo 786
  PetscFunctionReturn(0);
787
}
788