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
1376 slepc 1
/*
2
       This file implements a wrapper to the ARPACK package
6 dsic.upv.es!jroman 3
 
1376 slepc 4
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5
      SLEPc - Scalable Library for Eigenvalue Problem Computations
6
      Copyright (c) 2002-2007, Universidad Politecnica de Valencia, Spain
7
 
8
      This file is part of SLEPc. See the README file for conditions of use
9
      and additional information.
10
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6 dsic.upv.es!jroman 11
*/
1376 slepc 12
 
6 dsic.upv.es!jroman 13
#include "src/eps/impls/arpack/arpackp.h"
14
 
15
#undef __FUNCT__  
16
#define __FUNCT__ "EPSSetUp_ARPACK"
476 dsic.upv.es!antodo 17
PetscErrorCode EPSSetUp_ARPACK(EPS eps)
6 dsic.upv.es!jroman 18
{
476 dsic.upv.es!antodo 19
  PetscErrorCode ierr;
1089 slepc 20
  PetscInt       N, n;
21
  int            ncv;
476 dsic.upv.es!antodo 22
  EPS_ARPACK     *ar = (EPS_ARPACK *)eps->data;
6 dsic.upv.es!jroman 23
 
24
  PetscFunctionBegin;
1343 slepc 25
  ierr = VecGetSize(eps->IV[0],&N);CHKERRQ(ierr);
260 dsic.upv.es!antodo 26
  if (eps->ncv) {
27
    if (eps->ncv<eps->nev+2) SETERRQ(1,"The value of ncv must be at least nev+2");
1220 slepc 28
  } else /* set default value of ncv */
260 dsic.upv.es!antodo 29
    eps->ncv = PetscMin(PetscMax(20,2*eps->nev+1),N);
577 dsic.upv.es!antodo 30
  if (!eps->max_it) eps->max_it = PetscMax(300,(int)(2*N/eps->ncv));
260 dsic.upv.es!antodo 31
 
6 dsic.upv.es!jroman 32
  ncv = eps->ncv;
33
#if defined(PETSC_USE_COMPLEX)
1040 slepc 34
  ierr = PetscFree(ar->rwork);CHKERRQ(ierr);
6 dsic.upv.es!jroman 35
  ierr = PetscMalloc(ncv*sizeof(PetscReal),&ar->rwork);CHKERRQ(ierr);
36
  ar->lworkl = 3*ncv*ncv+5*ncv;
1040 slepc 37
  ierr = PetscFree(ar->workev);CHKERRQ(ierr);
6 dsic.upv.es!jroman 38
  ierr = PetscMalloc(3*ncv*sizeof(PetscScalar),&ar->workev);CHKERRQ(ierr);
39
#else
40
  if( eps->ishermitian ) {
41
    ar->lworkl = ncv*(ncv+8);
1220 slepc 42
  } else {
6 dsic.upv.es!jroman 43
    ar->lworkl = 3*ncv*ncv+6*ncv;
1040 slepc 44
    ierr = PetscFree(ar->workev);CHKERRQ(ierr);
6 dsic.upv.es!jroman 45
    ierr = PetscMalloc(3*ncv*sizeof(PetscScalar),&ar->workev);CHKERRQ(ierr);
46
  }
47
#endif
1040 slepc 48
  ierr = PetscFree(ar->workl);CHKERRQ(ierr);
6 dsic.upv.es!jroman 49
  ierr = PetscMalloc(ar->lworkl*sizeof(PetscScalar),&ar->workl);CHKERRQ(ierr);
1040 slepc 50
  ierr = PetscFree(ar->select);CHKERRQ(ierr);
6 dsic.upv.es!jroman 51
  ierr = PetscMalloc(ncv*sizeof(PetscTruth),&ar->select);CHKERRQ(ierr);
1343 slepc 52
  ierr = VecGetLocalSize(eps->IV[0],&n); CHKERRQ(ierr);
1040 slepc 53
  ierr = PetscFree(ar->workd);CHKERRQ(ierr);
6 dsic.upv.es!jroman 54
  ierr = PetscMalloc(3*n*sizeof(PetscScalar),&ar->workd);CHKERRQ(ierr);
55
 
1231 slepc 56
  ierr = EPSDefaultGetWork(eps,2);CHKERRQ(ierr);
260 dsic.upv.es!antodo 57
  ierr = EPSAllocateSolutionContiguous(eps);CHKERRQ(ierr);
6 dsic.upv.es!jroman 58
 
59
  PetscFunctionReturn(0);
60
}
61
 
62
#undef __FUNCT__  
63
#define __FUNCT__ "EPSSolve_ARPACK"
476 dsic.upv.es!antodo 64
PetscErrorCode EPSSolve_ARPACK(EPS eps)
6 dsic.upv.es!jroman 65
{
1089 slepc 66
  PetscErrorCode ierr;
1229 slepc 67
  EPS_ARPACK     *ar = (EPS_ARPACK *)eps->data;
68
  char           bmat[1], howmny[] = "A";
69
  const char     *which;
70
  PetscInt       nn;
71
  int            n, iparam[11], ipntr[14], ido, info;
72
  PetscScalar    sigmar, *pV, *resid;
73
  Vec            x, y, w = eps->work[0];
1358 slepc 74
  Mat            A;
1229 slepc 75
  PetscTruth     isSinv, isShift, rvec;
76
  MPI_Fint       fcomm;
77
#if !defined(PETSC_USE_COMPLEX)
78
  PetscScalar    sigmai = 0.0;
79
#endif
6 dsic.upv.es!jroman 80
  PetscFunctionBegin;
81
 
82
  fcomm = MPI_Comm_c2f(eps->comm);
1343 slepc 83
  ierr = VecGetLocalSize(eps->IV[0],&nn); CHKERRQ(ierr);
1089 slepc 84
  n = nn;
6 dsic.upv.es!jroman 85
  ierr = VecCreateMPIWithArray(eps->comm,n,PETSC_DECIDE,PETSC_NULL,&x);CHKERRQ(ierr);
86
  ierr = VecCreateMPIWithArray(eps->comm,n,PETSC_DECIDE,PETSC_NULL,&y);CHKERRQ(ierr);
87
  ierr = VecGetArray(eps->V[0],&pV);CHKERRQ(ierr);
1343 slepc 88
  ierr = VecCopy(eps->IV[0],eps->work[1]);CHKERRQ(ierr);
1231 slepc 89
  ierr = VecGetArray(eps->work[1],&resid);CHKERRQ(ierr);
6 dsic.upv.es!jroman 90
 
91
  ido  = 0;            /* first call to reverse communication interface */
92
  info = 1;            /* indicates a initial vector is provided */
93
  iparam[0] = 1;       /* use exact shifts */
94
  iparam[2] = eps->max_it;  /* maximum number of Arnoldi update iterations */
95
  iparam[3] = 1;       /* blocksize */
96
  iparam[4] = 0;       /* number of converged Ritz values */
97
 
98
  /*
99
     Computational modes ([]=not supported):
100
            symmetric    non-symmetric    complex
101
        1     1  'I'        1  'I'         1  'I'
102
        2     3  'I'        3  'I'         3  'I'
103
        3     2  'G'        2  'G'         2  'G'
104
        4     3  'G'        3  'G'         3  'G'
105
        5   [ 4  'G' ]    [ 3  'G' ]
106
        6   [ 5  'G' ]    [ 4  'G' ]
107
   */
1229 slepc 108
  ierr = PetscTypeCompare((PetscObject)eps->OP,STSINV,&isSinv);CHKERRQ(ierr);
109
  ierr = PetscTypeCompare((PetscObject)eps->OP,STSHIFT,&isShift);CHKERRQ(ierr);
110
  ierr = STGetShift(eps->OP,&sigmar);CHKERRQ(ierr);
111
  ierr = STGetOperators(eps->OP,&A,PETSC_NULL);CHKERRQ(ierr);
112
 
113
  if (isSinv) {
114
    /* shift-and-invert mode */
115
    iparam[6] = 3;
1358 slepc 116
    if (eps->ispositive) bmat[0] = 'G';
1229 slepc 117
    else bmat[0] = 'I';
1358 slepc 118
  } else if (isShift && eps->ispositive) {
1229 slepc 119
    /* generalized shift mode with B positive definite */
120
    iparam[6] = 2;
121
    bmat[0] = 'G';
122
  } else {
123
    /* regular mode */
124
    if (eps->ishermitian && eps->isgeneralized)
125
      SETERRQ(PETSC_ERR_SUP,"Spectral transformation not supported by ARPACK hermitian solver");
126
    iparam[6] = 1;
127
    bmat[0] = 'I';
6 dsic.upv.es!jroman 128
  }
129
 
130
#if !defined(PETSC_USE_COMPLEX)
131
    if (eps->ishermitian) {
91 dsic.upv.es!antodo 132
      switch(eps->which) {
133
        case EPS_LARGEST_MAGNITUDE:  which = "LM"; break;
134
        case EPS_SMALLEST_MAGNITUDE: which = "SM"; break;
135
        case EPS_LARGEST_REAL:       which = "LA"; break;
136
        case EPS_SMALLEST_REAL:      which = "SA"; break;
137
        default: SETERRQ(1,"Wrong value of eps->which");
138
      }
176 dsic.upv.es!antodo 139
    } else {
140
#endif
91 dsic.upv.es!antodo 141
      switch(eps->which) {
142
        case EPS_LARGEST_MAGNITUDE:  which = "LM"; break;
143
        case EPS_SMALLEST_MAGNITUDE: which = "SM"; break;
144
        case EPS_LARGEST_REAL:       which = "LR"; break;
145
        case EPS_SMALLEST_REAL:      which = "SR"; break;
146
        case EPS_LARGEST_IMAGINARY:  which = "LI"; break;
147
        case EPS_SMALLEST_IMAGINARY: which = "SI"; break;
148
        default: SETERRQ(1,"Wrong value of eps->which");
149
      }
176 dsic.upv.es!antodo 150
#if !defined(PETSC_USE_COMPLEX)
151
    }
152
#endif
153
 
740 dsic.upv.es!antodo 154
  do {
176 dsic.upv.es!antodo 155
 
156
#if !defined(PETSC_USE_COMPLEX)
157
    if (eps->ishermitian) {
158
      ARsaupd_( &fcomm, &ido, bmat, &n, which, &eps->nev, &eps->tol,
159
                resid, &eps->ncv, pV, &n, iparam, ipntr, ar->workd,
160
                ar->workl, &ar->lworkl, &info, 1, 2 );
161
    }
162
    else {
6 dsic.upv.es!jroman 163
      ARnaupd_( &fcomm, &ido, bmat, &n, which, &eps->nev, &eps->tol,
164
                resid, &eps->ncv, pV, &n, iparam, ipntr, ar->workd,
165
                ar->workl, &ar->lworkl, &info, 1, 2 );
166
    }
167
#else
168
    ARnaupd_( &fcomm, &ido, bmat, &n, which, &eps->nev, &eps->tol,
169
              resid, &eps->ncv, pV, &n, iparam, ipntr, ar->workd,
170
              ar->workl, &ar->lworkl, ar->rwork, &info, 1, 2 );
171
#endif
571 dsic.upv.es!antodo 172
 
1229 slepc 173
    if (ido == -1 || ido == 1 || ido == 2) {
174
      if (ido == 1 && iparam[6] == 3 && bmat[0] == 'G') {
175
        /* special case for shift-and-invert with B semi-positive definite*/
176
        ierr = VecPlaceArray(x,&ar->workd[ipntr[2]-1]); CHKERRQ(ierr);
177
      } else {
178
        ierr = VecPlaceArray(x,&ar->workd[ipntr[0]-1]); CHKERRQ(ierr);
179
      }
740 dsic.upv.es!antodo 180
      ierr = VecPlaceArray(y,&ar->workd[ipntr[1]-1]); CHKERRQ(ierr);
1229 slepc 181
 
182
      if (ido == -1) {
183
        /* Y = OP * X for for the initialization phase to
184
           force the starting vector into the range of OP */
185
        ierr = STApply(eps->OP,x,y); CHKERRQ(ierr);
186
      } else if (ido == 2) {
187
        /* Y = B * X */
1358 slepc 188
        ierr = IPApplyMatrix(eps->ip,x,y); CHKERRQ(ierr);
1229 slepc 189
      } else { /* ido == 1 */
190
        if (iparam[6] == 3 && bmat[0] == 'G') {
191
          /* Y = OP * X for shift-and-invert with B semi-positive definite */
192
          ierr = STAssociatedKSPSolve(eps->OP,x,y);CHKERRQ(ierr);
193
        } else if (iparam[6] == 2) {
194
          /* X=A*X Y=B^-1*X for shift with B positive definite */
195
          ierr = MatMult(A,x,y);CHKERRQ(ierr);
196
          if (sigmar != 0.0) {
1358 slepc 197
            ierr = IPApplyMatrix(eps->ip,x,w);CHKERRQ(ierr);
1229 slepc 198
            ierr = VecAXPY(y,sigmar,w);CHKERRQ(ierr);
199
          }
200
          ierr = VecCopy(y,x); CHKERRQ(ierr);
201
          ierr = STAssociatedKSPSolve(eps->OP,x,y);CHKERRQ(ierr);
202
        } else  {
203
          /* Y = OP * X */
204
          ierr = STApply(eps->OP,x,y); CHKERRQ(ierr);        
740 dsic.upv.es!antodo 205
        }
1345 slepc 206
        ierr = IPOrthogonalize(eps->ip,eps->nds,PETSC_NULL,eps->DS,y,PETSC_NULL,PETSC_NULL,PETSC_NULL,w);CHKERRQ(ierr);
6 dsic.upv.es!jroman 207
      }
1229 slepc 208
 
850 dsic.upv.es!antodo 209
      ierr = VecResetArray(x); CHKERRQ(ierr);
210
      ierr = VecResetArray(y); CHKERRQ(ierr);
742 dsic.upv.es!antodo 211
    } else if (ido != 99) {
740 dsic.upv.es!antodo 212
      SETERRQ1(1,"Internal error in ARPACK reverse comunication interface (ido=%i)\n",ido);
6 dsic.upv.es!jroman 213
    }
740 dsic.upv.es!antodo 214
 
215
  } while (ido != 99);
6 dsic.upv.es!jroman 216
 
217
  eps->nconv = iparam[4];
1223 slepc 218
  eps->its = iparam[2];
6 dsic.upv.es!jroman 219
 
740 dsic.upv.es!antodo 220
  if (info==3) { SETERRQ(1,"No shift could be applied in xxAUPD.\n"
221
                           "Try increasing the size of NCV relative to NEV."); }
222
  else if (info!=0 && info!=1) { SETERRQ1(PETSC_ERR_LIB,"Error reported by ARPACK subroutine xxAUPD (%d)",info);}
6 dsic.upv.es!jroman 223
 
393 dsic.upv.es!antodo 224
  rvec = PETSC_TRUE;
6 dsic.upv.es!jroman 225
 
740 dsic.upv.es!antodo 226
  if (eps->nconv > 0) {
6 dsic.upv.es!jroman 227
#if !defined(PETSC_USE_COMPLEX)
740 dsic.upv.es!antodo 228
    if (eps->ishermitian) {
1223 slepc 229
      EPSMonitor(eps,iparam[2],iparam[4],&ar->workl[ipntr[5]-1],eps->eigi,&ar->workl[ipntr[6]-1],eps->ncv);
740 dsic.upv.es!antodo 230
      ARseupd_ ( &fcomm, &rvec, howmny, ar->select, eps->eigr,  
231
                 pV, &n, &sigmar,
232
                 bmat, &n, which, &eps->nev, &eps->tol,
233
                 resid, &eps->ncv, pV, &n, iparam, ipntr, ar->workd,
234
                 ar->workl, &ar->lworkl, &info, 1, 1, 2 );
235
    }
236
    else {
1223 slepc 237
      EPSMonitor(eps,iparam[2],iparam[4],&ar->workl[ipntr[5]-1],&ar->workl[ipntr[6]-1],&ar->workl[ipntr[7]-1],eps->ncv);
740 dsic.upv.es!antodo 238
      ARneupd_ ( &fcomm, &rvec, howmny, ar->select, eps->eigr, eps->eigi,
239
                 pV, &n, &sigmar, &sigmai, ar->workev,
240
                 bmat, &n, which, &eps->nev, &eps->tol,
241
                 resid, &eps->ncv, pV, &n, iparam, ipntr, ar->workd,
242
                 ar->workl, &ar->lworkl, &info, 1, 1, 2 );
243
    }
244
#else
1223 slepc 245
    EPSMonitor(eps,eps->its,iparam[4],&ar->workl[ipntr[5]-1],eps->eigi,(PetscReal*)&ar->workl[ipntr[7]-1],eps->ncv);
740 dsic.upv.es!antodo 246
    ARneupd_ ( &fcomm, &rvec, howmny, ar->select, eps->eigr,
247
               pV, &n, &sigmar, ar->workev,
6 dsic.upv.es!jroman 248
               bmat, &n, which, &eps->nev, &eps->tol,
249
               resid, &eps->ncv, pV, &n, iparam, ipntr, ar->workd,
740 dsic.upv.es!antodo 250
               ar->workl, &ar->lworkl, ar->rwork, &info, 1, 1, 2 );
6 dsic.upv.es!jroman 251
#endif
740 dsic.upv.es!antodo 252
    if (info!=0) { SETERRQ1(PETSC_ERR_LIB,"Error reported by ARPACK subroutine xxEUPD (%d)",info); }
253
  }
6 dsic.upv.es!jroman 254
 
255
  ierr = VecRestoreArray( eps->V[0], &pV ); CHKERRQ(ierr);
1231 slepc 256
  ierr = VecRestoreArray( eps->work[1], &resid ); CHKERRQ(ierr);
740 dsic.upv.es!antodo 257
  if( eps->nconv >= eps->nev ) eps->reason = EPS_CONVERGED_TOL;
258
  else eps->reason = EPS_DIVERGED_ITS;
6 dsic.upv.es!jroman 259
 
260
  if (eps->ishermitian) {
261
    ierr = PetscMemcpy(eps->errest,&ar->workl[ipntr[8]-1],eps->nconv);CHKERRQ(ierr);
262
  } else {
263
    ierr = PetscMemcpy(eps->errest,&ar->workl[ipntr[10]-1],eps->nconv);CHKERRQ(ierr);
264
  }
265
 
266
  ierr = VecDestroy(x);CHKERRQ(ierr);
267
  ierr = VecDestroy(y);CHKERRQ(ierr);
268
 
269
  PetscFunctionReturn(0);
270
}
271
 
272
#undef __FUNCT__  
176 dsic.upv.es!antodo 273
#define __FUNCT__ "EPSBackTransform_ARPACK"
476 dsic.upv.es!antodo 274
PetscErrorCode EPSBackTransform_ARPACK(EPS eps)
176 dsic.upv.es!antodo 275
{
476 dsic.upv.es!antodo 276
  PetscErrorCode ierr;
1229 slepc 277
  PetscTruth     isSinv;
176 dsic.upv.es!antodo 278
 
279
  PetscFunctionBegin;
1229 slepc 280
  ierr = PetscTypeCompare((PetscObject)eps->OP,STSINV,&isSinv);CHKERRQ(ierr);
281
  if (!isSinv) {
282
    ierr = EPSBackTransform_Default(eps);CHKERRQ(ierr);
442 dsic.upv.es!antodo 283
  }
176 dsic.upv.es!antodo 284
  PetscFunctionReturn(0);
285
}
286
 
287
#undef __FUNCT__  
6 dsic.upv.es!jroman 288
#define __FUNCT__ "EPSDestroy_ARPACK"
476 dsic.upv.es!antodo 289
PetscErrorCode EPSDestroy_ARPACK(EPS eps)
6 dsic.upv.es!jroman 290
{
476 dsic.upv.es!antodo 291
  PetscErrorCode ierr;
292
  EPS_ARPACK     *ar = (EPS_ARPACK *)eps->data;
6 dsic.upv.es!jroman 293
 
294
  PetscFunctionBegin;
24 dsic.upv.es!jroman 295
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
1040 slepc 296
  ierr = PetscFree(ar->workev);CHKERRQ(ierr);
297
  ierr = PetscFree(ar->workl);CHKERRQ(ierr);
298
  ierr = PetscFree(ar->select);CHKERRQ(ierr);
299
  ierr = PetscFree(ar->workd);CHKERRQ(ierr);
6 dsic.upv.es!jroman 300
#if defined(PETSC_USE_COMPLEX)
1040 slepc 301
  ierr = PetscFree(ar->rwork);CHKERRQ(ierr);
6 dsic.upv.es!jroman 302
#endif
1040 slepc 303
  ierr = PetscFree(eps->data);CHKERRQ(ierr);
260 dsic.upv.es!antodo 304
  ierr = EPSDefaultFreeWork(eps);CHKERRQ(ierr);
305
  ierr = EPSFreeSolutionContiguous(eps);CHKERRQ(ierr);
6 dsic.upv.es!jroman 306
  PetscFunctionReturn(0);
307
}
308
 
309
EXTERN_C_BEGIN
310
#undef __FUNCT__  
311
#define __FUNCT__ "EPSCreate_ARPACK"
476 dsic.upv.es!antodo 312
PetscErrorCode EPSCreate_ARPACK(EPS eps)
6 dsic.upv.es!jroman 313
{
476 dsic.upv.es!antodo 314
  PetscErrorCode ierr;
315
  EPS_ARPACK     *arpack;
6 dsic.upv.es!jroman 316
 
317
  PetscFunctionBegin;
318
  ierr = PetscNew(EPS_ARPACK,&arpack);CHKERRQ(ierr);
319
  PetscLogObjectMemory(eps,sizeof(EPS_ARPACK));
320
  eps->data                      = (void *) arpack;
321
  eps->ops->solve                = EPSSolve_ARPACK;
503 dsic.upv.es!antodo 322
  eps->ops->setup                = EPSSetUp_ARPACK;
6 dsic.upv.es!jroman 323
  eps->ops->destroy              = EPSDestroy_ARPACK;
176 dsic.upv.es!antodo 324
  eps->ops->backtransform        = EPSBackTransform_ARPACK;
503 dsic.upv.es!antodo 325
  eps->ops->computevectors       = EPSComputeVectors_Default;
6 dsic.upv.es!jroman 326
  PetscFunctionReturn(0);
327
}
328
EXTERN_C_END