Subversion Repositories slepc-dev

Rev

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
 
6 dsic.upv.es!jroman 24
#include "src/eps/impls/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
 
1231 slepc 73
  ierr = EPSDefaultGetWork(eps,2);CHKERRQ(ierr);
1596 slepc 74
  ierr = EPSAllocateSolution(eps);CHKERRQ(ierr);
6 dsic.upv.es!jroman 75
 
76
  PetscFunctionReturn(0);
77
}
78
 
79
#undef __FUNCT__  
80
#define __FUNCT__ "EPSSolve_ARPACK"
476 dsic.upv.es!antodo 81
PetscErrorCode EPSSolve_ARPACK(EPS eps)
6 dsic.upv.es!jroman 82
{
1089 slepc 83
  PetscErrorCode ierr;
1229 slepc 84
  EPS_ARPACK     *ar = (EPS_ARPACK *)eps->data;
85
  char           bmat[1], howmny[] = "A";
86
  const char     *which;
87
  PetscInt       nn;
1509 slepc 88
  PetscBLASInt   n, iparam[11], ipntr[14], ido, info,
1645 slepc 89
                 nev, ncv;
1229 slepc 90
  PetscScalar    sigmar, *pV, *resid;
91
  Vec            x, y, w = eps->work[0];
1358 slepc 92
  Mat            A;
1229 slepc 93
  PetscTruth     isSinv, isShift, rvec;
1509 slepc 94
  PetscBLASInt   fcomm;
1229 slepc 95
#if !defined(PETSC_USE_COMPLEX)
96
  PetscScalar    sigmai = 0.0;
97
#endif
6 dsic.upv.es!jroman 98
  PetscFunctionBegin;
1645 slepc 99
 
100
  nev = PetscBLASIntCast(eps->nev);
101
  ncv = PetscBLASIntCast(eps->ncv);
1515 slepc 102
  fcomm = PetscBLASIntCast(MPI_Comm_c2f(((PetscObject)eps)->comm));
1386 slepc 103
  ierr = VecGetLocalSize(eps->vec_initial,&nn); CHKERRQ(ierr);
1645 slepc 104
  n = PetscBLASIntCast(nn);
1422 slepc 105
  ierr = VecCreateMPIWithArray(((PetscObject)eps)->comm,n,PETSC_DECIDE,PETSC_NULL,&x);CHKERRQ(ierr);
106
  ierr = VecCreateMPIWithArray(((PetscObject)eps)->comm,n,PETSC_DECIDE,PETSC_NULL,&y);CHKERRQ(ierr);
6 dsic.upv.es!jroman 107
  ierr = VecGetArray(eps->V[0],&pV);CHKERRQ(ierr);
1386 slepc 108
  ierr = VecCopy(eps->vec_initial,eps->work[1]);CHKERRQ(ierr);
1231 slepc 109
  ierr = VecGetArray(eps->work[1],&resid);CHKERRQ(ierr);
6 dsic.upv.es!jroman 110
 
111
  ido  = 0;            /* first call to reverse communication interface */
112
  info = 1;            /* indicates a initial vector is provided */
113
  iparam[0] = 1;       /* use exact shifts */
1645 slepc 114
  iparam[2] = PetscBLASIntCast(eps->max_it);  /* maximum number of Arnoldi update iterations */
6 dsic.upv.es!jroman 115
  iparam[3] = 1;       /* blocksize */
116
  iparam[4] = 0;       /* number of converged Ritz values */
117
 
118
  /*
119
     Computational modes ([]=not supported):
120
            symmetric    non-symmetric    complex
121
        1     1  'I'        1  'I'         1  'I'
122
        2     3  'I'        3  'I'         3  'I'
123
        3     2  'G'        2  'G'         2  'G'
124
        4     3  'G'        3  'G'         3  'G'
125
        5   [ 4  'G' ]    [ 3  'G' ]
126
        6   [ 5  'G' ]    [ 4  'G' ]
127
   */
1229 slepc 128
  ierr = PetscTypeCompare((PetscObject)eps->OP,STSINV,&isSinv);CHKERRQ(ierr);
129
  ierr = PetscTypeCompare((PetscObject)eps->OP,STSHIFT,&isShift);CHKERRQ(ierr);
130
  ierr = STGetShift(eps->OP,&sigmar);CHKERRQ(ierr);
131
  ierr = STGetOperators(eps->OP,&A,PETSC_NULL);CHKERRQ(ierr);
132
 
133
  if (isSinv) {
134
    /* shift-and-invert mode */
135
    iparam[6] = 3;
1358 slepc 136
    if (eps->ispositive) bmat[0] = 'G';
1229 slepc 137
    else bmat[0] = 'I';
1358 slepc 138
  } else if (isShift && eps->ispositive) {
1229 slepc 139
    /* generalized shift mode with B positive definite */
140
    iparam[6] = 2;
141
    bmat[0] = 'G';
142
  } else {
143
    /* regular mode */
144
    if (eps->ishermitian && eps->isgeneralized)
145
      SETERRQ(PETSC_ERR_SUP,"Spectral transformation not supported by ARPACK hermitian solver");
146
    iparam[6] = 1;
147
    bmat[0] = 'I';
6 dsic.upv.es!jroman 148
  }
149
 
150
#if !defined(PETSC_USE_COMPLEX)
151
    if (eps->ishermitian) {
91 dsic.upv.es!antodo 152
      switch(eps->which) {
153
        case EPS_LARGEST_MAGNITUDE:  which = "LM"; break;
154
        case EPS_SMALLEST_MAGNITUDE: which = "SM"; break;
155
        case EPS_LARGEST_REAL:       which = "LA"; break;
156
        case EPS_SMALLEST_REAL:      which = "SA"; break;
157
        default: SETERRQ(1,"Wrong value of eps->which");
158
      }
176 dsic.upv.es!antodo 159
    } else {
160
#endif
91 dsic.upv.es!antodo 161
      switch(eps->which) {
162
        case EPS_LARGEST_MAGNITUDE:  which = "LM"; break;
163
        case EPS_SMALLEST_MAGNITUDE: which = "SM"; break;
164
        case EPS_LARGEST_REAL:       which = "LR"; break;
165
        case EPS_SMALLEST_REAL:      which = "SR"; break;
166
        case EPS_LARGEST_IMAGINARY:  which = "LI"; break;
167
        case EPS_SMALLEST_IMAGINARY: which = "SI"; break;
168
        default: SETERRQ(1,"Wrong value of eps->which");
169
      }
176 dsic.upv.es!antodo 170
#if !defined(PETSC_USE_COMPLEX)
171
    }
172
#endif
173
 
740 dsic.upv.es!antodo 174
  do {
176 dsic.upv.es!antodo 175
 
176
#if !defined(PETSC_USE_COMPLEX)
177
    if (eps->ishermitian) {
1509 slepc 178
      ARsaupd_( &fcomm, &ido, bmat, &n, which, &nev, &eps->tol,
179
                resid, &ncv, pV, &n, iparam, ipntr, ar->workd,
176 dsic.upv.es!antodo 180
                ar->workl, &ar->lworkl, &info, 1, 2 );
181
    }
182
    else {
1509 slepc 183
      ARnaupd_( &fcomm, &ido, bmat, &n, which, &nev, &eps->tol,
184
                resid, &ncv, pV, &n, iparam, ipntr, ar->workd,
6 dsic.upv.es!jroman 185
                ar->workl, &ar->lworkl, &info, 1, 2 );
186
    }
187
#else
1509 slepc 188
    ARnaupd_( &fcomm, &ido, bmat, &n, which, &nev, &eps->tol,
189
              resid, &ncv, pV, &n, iparam, ipntr, ar->workd,
6 dsic.upv.es!jroman 190
              ar->workl, &ar->lworkl, ar->rwork, &info, 1, 2 );
191
#endif
571 dsic.upv.es!antodo 192
 
1229 slepc 193
    if (ido == -1 || ido == 1 || ido == 2) {
194
      if (ido == 1 && iparam[6] == 3 && bmat[0] == 'G') {
195
        /* special case for shift-and-invert with B semi-positive definite*/
196
        ierr = VecPlaceArray(x,&ar->workd[ipntr[2]-1]); CHKERRQ(ierr);
197
      } else {
198
        ierr = VecPlaceArray(x,&ar->workd[ipntr[0]-1]); CHKERRQ(ierr);
199
      }
740 dsic.upv.es!antodo 200
      ierr = VecPlaceArray(y,&ar->workd[ipntr[1]-1]); CHKERRQ(ierr);
1229 slepc 201
 
202
      if (ido == -1) {
203
        /* Y = OP * X for for the initialization phase to
204
           force the starting vector into the range of OP */
205
        ierr = STApply(eps->OP,x,y); CHKERRQ(ierr);
206
      } else if (ido == 2) {
207
        /* Y = B * X */
1358 slepc 208
        ierr = IPApplyMatrix(eps->ip,x,y); CHKERRQ(ierr);
1229 slepc 209
      } else { /* ido == 1 */
210
        if (iparam[6] == 3 && bmat[0] == 'G') {
211
          /* Y = OP * X for shift-and-invert with B semi-positive definite */
212
          ierr = STAssociatedKSPSolve(eps->OP,x,y);CHKERRQ(ierr);
213
        } else if (iparam[6] == 2) {
214
          /* X=A*X Y=B^-1*X for shift with B positive definite */
215
          ierr = MatMult(A,x,y);CHKERRQ(ierr);
216
          if (sigmar != 0.0) {
1358 slepc 217
            ierr = IPApplyMatrix(eps->ip,x,w);CHKERRQ(ierr);
1229 slepc 218
            ierr = VecAXPY(y,sigmar,w);CHKERRQ(ierr);
219
          }
220
          ierr = VecCopy(y,x); CHKERRQ(ierr);
221
          ierr = STAssociatedKSPSolve(eps->OP,x,y);CHKERRQ(ierr);
222
        } else  {
223
          /* Y = OP * X */
224
          ierr = STApply(eps->OP,x,y); CHKERRQ(ierr);        
740 dsic.upv.es!antodo 225
        }
1538 slepc 226
        ierr = IPOrthogonalize(eps->ip,eps->nds,PETSC_NULL,eps->DS,y,PETSC_NULL,PETSC_NULL,PETSC_NULL,w,PETSC_NULL);CHKERRQ(ierr);
6 dsic.upv.es!jroman 227
      }
1229 slepc 228
 
850 dsic.upv.es!antodo 229
      ierr = VecResetArray(x); CHKERRQ(ierr);
230
      ierr = VecResetArray(y); CHKERRQ(ierr);
742 dsic.upv.es!antodo 231
    } else if (ido != 99) {
740 dsic.upv.es!antodo 232
      SETERRQ1(1,"Internal error in ARPACK reverse comunication interface (ido=%i)\n",ido);
6 dsic.upv.es!jroman 233
    }
740 dsic.upv.es!antodo 234
 
235
  } while (ido != 99);
6 dsic.upv.es!jroman 236
 
237
  eps->nconv = iparam[4];
1223 slepc 238
  eps->its = iparam[2];
6 dsic.upv.es!jroman 239
 
740 dsic.upv.es!antodo 240
  if (info==3) { SETERRQ(1,"No shift could be applied in xxAUPD.\n"
241
                           "Try increasing the size of NCV relative to NEV."); }
242
  else if (info!=0 && info!=1) { SETERRQ1(PETSC_ERR_LIB,"Error reported by ARPACK subroutine xxAUPD (%d)",info);}
6 dsic.upv.es!jroman 243
 
393 dsic.upv.es!antodo 244
  rvec = PETSC_TRUE;
6 dsic.upv.es!jroman 245
 
740 dsic.upv.es!antodo 246
  if (eps->nconv > 0) {
6 dsic.upv.es!jroman 247
#if !defined(PETSC_USE_COMPLEX)
740 dsic.upv.es!antodo 248
    if (eps->ishermitian) {
1223 slepc 249
      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 250
      ARseupd_ ( &fcomm, &rvec, howmny, ar->select, eps->eigr,  
251
                 pV, &n, &sigmar,
1509 slepc 252
                 bmat, &n, which, &nev, &eps->tol,
253
                 resid, &ncv, pV, &n, iparam, ipntr, ar->workd,
740 dsic.upv.es!antodo 254
                 ar->workl, &ar->lworkl, &info, 1, 1, 2 );
255
    }
256
    else {
1223 slepc 257
      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 258
      ARneupd_ ( &fcomm, &rvec, howmny, ar->select, eps->eigr, eps->eigi,
259
                 pV, &n, &sigmar, &sigmai, ar->workev,
1509 slepc 260
                 bmat, &n, which, &nev, &eps->tol,
261
                 resid, &ncv, pV, &n, iparam, ipntr, ar->workd,
740 dsic.upv.es!antodo 262
                 ar->workl, &ar->lworkl, &info, 1, 1, 2 );
263
    }
264
#else
1223 slepc 265
    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 266
    ARneupd_ ( &fcomm, &rvec, howmny, ar->select, eps->eigr,
267
               pV, &n, &sigmar, ar->workev,
1509 slepc 268
               bmat, &n, which, &nev, &eps->tol,
269
               resid, &ncv, pV, &n, iparam, ipntr, ar->workd,
740 dsic.upv.es!antodo 270
               ar->workl, &ar->lworkl, ar->rwork, &info, 1, 1, 2 );
6 dsic.upv.es!jroman 271
#endif
740 dsic.upv.es!antodo 272
    if (info!=0) { SETERRQ1(PETSC_ERR_LIB,"Error reported by ARPACK subroutine xxEUPD (%d)",info); }
273
  }
6 dsic.upv.es!jroman 274
 
275
  ierr = VecRestoreArray( eps->V[0], &pV ); CHKERRQ(ierr);
1231 slepc 276
  ierr = VecRestoreArray( eps->work[1], &resid ); CHKERRQ(ierr);
740 dsic.upv.es!antodo 277
  if( eps->nconv >= eps->nev ) eps->reason = EPS_CONVERGED_TOL;
278
  else eps->reason = EPS_DIVERGED_ITS;
6 dsic.upv.es!jroman 279
 
280
  if (eps->ishermitian) {
281
    ierr = PetscMemcpy(eps->errest,&ar->workl[ipntr[8]-1],eps->nconv);CHKERRQ(ierr);
282
  } else {
283
    ierr = PetscMemcpy(eps->errest,&ar->workl[ipntr[10]-1],eps->nconv);CHKERRQ(ierr);
284
  }
285
 
286
  ierr = VecDestroy(x);CHKERRQ(ierr);
287
  ierr = VecDestroy(y);CHKERRQ(ierr);
288
 
289
  PetscFunctionReturn(0);
290
}
291
 
292
#undef __FUNCT__  
176 dsic.upv.es!antodo 293
#define __FUNCT__ "EPSBackTransform_ARPACK"
476 dsic.upv.es!antodo 294
PetscErrorCode EPSBackTransform_ARPACK(EPS eps)
176 dsic.upv.es!antodo 295
{
476 dsic.upv.es!antodo 296
  PetscErrorCode ierr;
1229 slepc 297
  PetscTruth     isSinv;
176 dsic.upv.es!antodo 298
 
299
  PetscFunctionBegin;
1229 slepc 300
  ierr = PetscTypeCompare((PetscObject)eps->OP,STSINV,&isSinv);CHKERRQ(ierr);
301
  if (!isSinv) {
302
    ierr = EPSBackTransform_Default(eps);CHKERRQ(ierr);
442 dsic.upv.es!antodo 303
  }
176 dsic.upv.es!antodo 304
  PetscFunctionReturn(0);
305
}
306
 
307
#undef __FUNCT__  
6 dsic.upv.es!jroman 308
#define __FUNCT__ "EPSDestroy_ARPACK"
476 dsic.upv.es!antodo 309
PetscErrorCode EPSDestroy_ARPACK(EPS eps)
6 dsic.upv.es!jroman 310
{
476 dsic.upv.es!antodo 311
  PetscErrorCode ierr;
312
  EPS_ARPACK     *ar = (EPS_ARPACK *)eps->data;
6 dsic.upv.es!jroman 313
 
314
  PetscFunctionBegin;
24 dsic.upv.es!jroman 315
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
1040 slepc 316
  ierr = PetscFree(ar->workev);CHKERRQ(ierr);
317
  ierr = PetscFree(ar->workl);CHKERRQ(ierr);
318
  ierr = PetscFree(ar->select);CHKERRQ(ierr);
319
  ierr = PetscFree(ar->workd);CHKERRQ(ierr);
6 dsic.upv.es!jroman 320
#if defined(PETSC_USE_COMPLEX)
1040 slepc 321
  ierr = PetscFree(ar->rwork);CHKERRQ(ierr);
6 dsic.upv.es!jroman 322
#endif
1040 slepc 323
  ierr = PetscFree(eps->data);CHKERRQ(ierr);
260 dsic.upv.es!antodo 324
  ierr = EPSDefaultFreeWork(eps);CHKERRQ(ierr);
1596 slepc 325
  ierr = EPSFreeSolution(eps);CHKERRQ(ierr);
6 dsic.upv.es!jroman 326
  PetscFunctionReturn(0);
327
}
328
 
329
EXTERN_C_BEGIN
330
#undef __FUNCT__  
331
#define __FUNCT__ "EPSCreate_ARPACK"
476 dsic.upv.es!antodo 332
PetscErrorCode EPSCreate_ARPACK(EPS eps)
6 dsic.upv.es!jroman 333
{
476 dsic.upv.es!antodo 334
  PetscErrorCode ierr;
335
  EPS_ARPACK     *arpack;
6 dsic.upv.es!jroman 336
 
337
  PetscFunctionBegin;
338
  ierr = PetscNew(EPS_ARPACK,&arpack);CHKERRQ(ierr);
339
  PetscLogObjectMemory(eps,sizeof(EPS_ARPACK));
340
  eps->data                      = (void *) arpack;
341
  eps->ops->solve                = EPSSolve_ARPACK;
503 dsic.upv.es!antodo 342
  eps->ops->setup                = EPSSetUp_ARPACK;
6 dsic.upv.es!jroman 343
  eps->ops->destroy              = EPSDestroy_ARPACK;
176 dsic.upv.es!antodo 344
  eps->ops->backtransform        = EPSBackTransform_ARPACK;
503 dsic.upv.es!antodo 345
  eps->ops->computevectors       = EPSComputeVectors_Default;
6 dsic.upv.es!jroman 346
  PetscFunctionReturn(0);
347
}
348
EXTERN_C_END