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