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 BLOPEX solver
1199 slepc 3
 
1376 slepc 4
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 5
   SLEPc - Scalable Library for Eigenvalue Problem Computations
2575 eromero 6
   Copyright (c) 2002-2011, Universitat 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
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1199 slepc 22
*/
1376 slepc 23
 
2729 jroman 24
#include <slepc-private/stimpl.h>       /*I "slepcst.h" I*/
25
#include <slepc-private/epsimpl.h>      /*I "slepceps.h" I*/
1499 slepc 26
#include "slepc-interface.h"
2423 jroman 27
#include <blopex_lobpcg.h>
28
#include <blopex_interpreter.h>
29
#include <blopex_multivector.h>
30
#include <blopex_temp_multivector.h>
1199 slepc 31
 
1947 jroman 32
PetscErrorCode EPSSolve_BLOPEX(EPS);
33
 
1199 slepc 34
typedef struct {
35
  lobpcg_Tolerance           tol;
36
  lobpcg_BLASLAPACKFunctions blap_fn;
37
  mv_MultiVectorPtr          eigenvectors;
1499 slepc 38
  mv_MultiVectorPtr          Y;
1199 slepc 39
  mv_InterfaceInterpreter    ii;
40
  KSP                        ksp;
2435 jroman 41
  Vec                        w;
1199 slepc 42
} EPS_BLOPEX;
43
 
44
#undef __FUNCT__  
45
#define __FUNCT__ "Precond_FnSingleVector"
46
static void Precond_FnSingleVector(void *data,void *x,void *y)
47
{
2317 jroman 48
  PetscErrorCode ierr;
49
  EPS            eps = (EPS)data;
50
  EPS_BLOPEX     *blopex = (EPS_BLOPEX*)eps->data;
51
  PetscInt       lits;
1199 slepc 52
 
53
  PetscFunctionBegin;
2730 jroman 54
  ierr = KSPSolve(blopex->ksp,(Vec)x,(Vec)y); CHKERRABORT(((PetscObject)eps)->comm,ierr);
55
  ierr = KSPGetIterationNumber(blopex->ksp,&lits); CHKERRABORT(((PetscObject)eps)->comm,ierr);
1499 slepc 56
  eps->OP->lineariterations+= lits;
1199 slepc 57
  PetscFunctionReturnVoid();
58
}
59
 
60
#undef __FUNCT__  
61
#define __FUNCT__ "Precond_FnMultiVector"
62
static void Precond_FnMultiVector(void *data,void *x,void *y)
63
{
2317 jroman 64
  EPS        eps = (EPS)data;
65
  EPS_BLOPEX *blopex = (EPS_BLOPEX*)eps->data;
1199 slepc 66
 
67
  PetscFunctionBegin;
68
  blopex->ii.Eval(Precond_FnSingleVector,data,x,y);
69
  PetscFunctionReturnVoid();
70
}
71
 
72
#undef __FUNCT__  
73
#define __FUNCT__ "OperatorASingleVector"
74
static void OperatorASingleVector(void *data,void *x,void *y)
75
{
2316 jroman 76
  PetscErrorCode ierr;
77
  EPS            eps = (EPS)data;
2435 jroman 78
  EPS_BLOPEX     *blopex = (EPS_BLOPEX*)eps->data;
79
  Mat            A,B;
1499 slepc 80
 
1199 slepc 81
  PetscFunctionBegin;
2730 jroman 82
  ierr = STGetOperators(eps->OP,&A,&B);CHKERRABORT(((PetscObject)eps)->comm,ierr);
83
  ierr = MatMult(A,(Vec)x,(Vec)y);CHKERRABORT(((PetscObject)eps)->comm,ierr);
2435 jroman 84
  if (eps->OP->sigma != 0.0) {
2730 jroman 85
    if (B) { ierr = MatMult(B,(Vec)x,blopex->w);CHKERRABORT(((PetscObject)eps)->comm,ierr); }
86
    else { ierr = VecCopy((Vec)x,blopex->w);CHKERRABORT(((PetscObject)eps)->comm,ierr); }
87
    ierr = VecAXPY((Vec)y,-eps->OP->sigma,blopex->w);CHKERRABORT(((PetscObject)eps)->comm,ierr);
2435 jroman 88
  }
1199 slepc 89
  PetscFunctionReturnVoid();
90
}
91
 
92
#undef __FUNCT__  
93
#define __FUNCT__ "OperatorAMultiVector"
94
static void OperatorAMultiVector(void *data,void *x,void *y)
95
{
2316 jroman 96
  EPS        eps = (EPS)data;
97
  EPS_BLOPEX *blopex = (EPS_BLOPEX*)eps->data;
1199 slepc 98
 
99
  PetscFunctionBegin;
100
  blopex->ii.Eval(OperatorASingleVector,data,x,y);
101
  PetscFunctionReturnVoid();
102
}
103
 
104
#undef __FUNCT__  
1499 slepc 105
#define __FUNCT__ "OperatorBSingleVector"
106
static void OperatorBSingleVector(void *data,void *x,void *y)
107
{
2316 jroman 108
  PetscErrorCode ierr;
109
  EPS            eps = (EPS)data;
110
  Mat            B;
1499 slepc 111
 
112
  PetscFunctionBegin;
2730 jroman 113
  ierr = STGetOperators(eps->OP,PETSC_NULL,&B);CHKERRABORT(((PetscObject)eps)->comm,ierr);
114
  ierr = MatMult(B,(Vec)x,(Vec)y);CHKERRABORT(((PetscObject)eps)->comm,ierr);
1499 slepc 115
  PetscFunctionReturnVoid();
116
}
117
 
118
#undef __FUNCT__  
119
#define __FUNCT__ "OperatorBMultiVector"
120
static void OperatorBMultiVector(void *data,void *x,void *y)
121
{
2316 jroman 122
  EPS        eps = (EPS)data;
123
  EPS_BLOPEX *blopex = (EPS_BLOPEX*)eps->data;
1499 slepc 124
 
125
  PetscFunctionBegin;
126
  blopex->ii.Eval(OperatorBSingleVector,data,x,y);
127
  PetscFunctionReturnVoid();
128
}
129
 
130
#undef __FUNCT__  
1199 slepc 131
#define __FUNCT__ "EPSSetUp_BLOPEX"
132
PetscErrorCode EPSSetUp_BLOPEX(EPS eps)
133
{
2739 jroman 134
#if defined(PETSC_MISSING_LAPACK_POTRF) || defined(PETSC_MISSING_LAPACK_SYGV)
135
  PetscFunctionBegin;
136
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRF/SYGV - Lapack routine is unavailable.");
137
#else
2317 jroman 138
  PetscErrorCode ierr;
2372 jroman 139
  PetscInt       i;
2317 jroman 140
  EPS_BLOPEX     *blopex = (EPS_BLOPEX *)eps->data;
2461 jroman 141
  PetscBool      isPrecond;
1199 slepc 142
 
143
  PetscFunctionBegin;
1499 slepc 144
  if (!eps->ishermitian) {
2214 jroman 145
    SETERRQ(((PetscObject)eps)->comm,PETSC_ERR_SUP,"blopex only works for hermitian problems");
1199 slepc 146
  }
1942 jroman 147
  if (!eps->which) eps->which = EPS_SMALLEST_REAL;
1199 slepc 148
  if (eps->which!=EPS_SMALLEST_REAL) {
2214 jroman 149
    SETERRQ(((PetscObject)eps)->comm,1,"Wrong value of eps->which");
1199 slepc 150
  }
1499 slepc 151
 
2104 eromero 152
  /* Change the default sigma to inf if necessary */
153
  if (eps->which == EPS_LARGEST_MAGNITUDE || eps->which == EPS_LARGEST_REAL ||
154
      eps->which == EPS_LARGEST_IMAGINARY) {
2331 jroman 155
    ierr = STSetDefaultShift(eps->OP,3e300);CHKERRQ(ierr);
2104 eromero 156
  }
157
 
2330 jroman 158
  ierr = STSetUp(eps->OP);CHKERRQ(ierr);
2331 jroman 159
  ierr = PetscTypeCompare((PetscObject)eps->OP,STPRECOND,&isPrecond);CHKERRQ(ierr);
160
  if (!isPrecond) SETERRQ(((PetscObject)eps)->comm,PETSC_ERR_SUP,"blopex only works with STPRECOND");
161
  ierr = STGetKSP(eps->OP,&blopex->ksp);CHKERRQ(ierr);
1199 slepc 162
 
1928 jroman 163
  eps->ncv = eps->nev = PetscMin(eps->nev,eps->n);
2499 jroman 164
  if (eps->mpd) { ierr = PetscInfo(eps,"Warning: parameter mpd ignored\n");CHKERRQ(ierr); }
1928 jroman 165
  if (!eps->max_it) eps->max_it = PetscMax(100,2*eps->n/eps->ncv);
1499 slepc 166
 
167
  ierr = EPSAllocateSolution(eps);CHKERRQ(ierr);
168
  ierr = EPSDefaultGetWork(eps,1);CHKERRQ(ierr);
1199 slepc 169
 
2621 eromero 170
  blopex->tol.absolute = eps->tol==PETSC_DEFAULT?SLEPC_DEFAULT_TOL:eps->tol;
1199 slepc 171
  blopex->tol.relative = 1e-50;
172
 
1499 slepc 173
  SLEPCSetupInterpreter(&blopex->ii);
174
  blopex->eigenvectors = mv_MultiVectorCreateFromSampleVector(&blopex->ii,eps->ncv,eps->V);
2372 jroman 175
  for (i=0;i<eps->ncv;i++) { ierr = PetscObjectReference((PetscObject)eps->V[i]);CHKERRQ(ierr); }
1199 slepc 176
  mv_MultiVectorSetRandom(blopex->eigenvectors,1234);
2435 jroman 177
  ierr = VecDuplicate(eps->V[0],&blopex->w);CHKERRQ(ierr);
1499 slepc 178
 
179
  if (eps->nds > 0) {
2331 jroman 180
    blopex->Y = mv_MultiVectorCreateFromSampleVector(&blopex->ii,eps->nds,eps->DS);
2372 jroman 181
    for (i=0;i<eps->nds;i++) { ierr = PetscObjectReference((PetscObject)eps->DS[i]);CHKERRQ(ierr); }
1499 slepc 182
  } else
183
    blopex->Y = PETSC_NULL;
1974 eromero 184
 
2320 jroman 185
#if defined(PETSC_USE_COMPLEX)
1974 eromero 186
  blopex->blap_fn.zpotrf = PETSC_zpotrf_interface;
187
  blopex->blap_fn.zhegv = PETSC_zsygv_interface;
188
#else
1199 slepc 189
  blopex->blap_fn.dpotrf = PETSC_dpotrf_interface;
190
  blopex->blap_fn.dsygv = PETSC_dsygv_interface;
1974 eromero 191
#endif
1199 slepc 192
 
2499 jroman 193
  if (eps->extraction) { ierr = PetscInfo(eps,"Warning: extraction type ignored\n");CHKERRQ(ierr); }
1426 slepc 194
 
1947 jroman 195
  /* dispatch solve method */
2214 jroman 196
  if (eps->leftvecs) SETERRQ(((PetscObject)eps)->comm,PETSC_ERR_SUP,"Left vectors not supported in this solver");
1947 jroman 197
  eps->ops->solve = EPSSolve_BLOPEX;
1199 slepc 198
  PetscFunctionReturn(0);
2739 jroman 199
#endif
1199 slepc 200
}
201
 
202
#undef __FUNCT__  
203
#define __FUNCT__ "EPSSolve_BLOPEX"
204
PetscErrorCode EPSSolve_BLOPEX(EPS eps)
205
{
2725 jroman 206
  EPS_BLOPEX     *blopex = (EPS_BLOPEX *)eps->data;
207
  int            i,j,info,its,nconv;
208
  double         *residhist=PETSC_NULL;
2587 jroman 209
  PetscErrorCode ierr;
2725 jroman 210
#if defined(PETSC_USE_COMPLEX)
211
  komplex        *lambdahist=PETSC_NULL;
212
#else
213
  double         *lambdahist=PETSC_NULL;
214
#endif
1199 slepc 215
 
216
  PetscFunctionBegin;
2587 jroman 217
  if (eps->numbermonitors>0) {
2725 jroman 218
#if defined(PETSC_USE_COMPLEX)
219
    ierr = PetscMalloc(eps->ncv*(eps->max_it+1)*sizeof(komplex),&lambdahist);CHKERRQ(ierr);
220
#else
2587 jroman 221
    ierr = PetscMalloc(eps->ncv*(eps->max_it+1)*sizeof(double),&lambdahist);CHKERRQ(ierr);
2725 jroman 222
#endif
2587 jroman 223
    ierr = PetscMalloc(eps->ncv*(eps->max_it+1)*sizeof(double),&residhist);CHKERRQ(ierr);
224
  }
225
 
2372 jroman 226
#if defined(PETSC_USE_COMPLEX)
227
  info = lobpcg_solve_complex(blopex->eigenvectors,eps,OperatorAMultiVector,
2316 jroman 228
        eps->isgeneralized?eps:PETSC_NULL,eps->isgeneralized?OperatorBMultiVector:PETSC_NULL,
1499 slepc 229
        eps,Precond_FnMultiVector,blopex->Y,
1524 slepc 230
        blopex->blap_fn,blopex->tol,eps->max_it,0,&its,
2587 jroman 231
        (komplex*)eps->eigr,lambdahist,eps->ncv,eps->errest,residhist,eps->ncv);
2372 jroman 232
#else
233
  info = lobpcg_solve_double(blopex->eigenvectors,eps,OperatorAMultiVector,
234
        eps->isgeneralized?eps:PETSC_NULL,eps->isgeneralized?OperatorBMultiVector:PETSC_NULL,
235
        eps,Precond_FnMultiVector,blopex->Y,
236
        blopex->blap_fn,blopex->tol,eps->max_it,0,&its,
2587 jroman 237
        eps->eigr,lambdahist,eps->ncv,eps->errest,residhist,eps->ncv);
2372 jroman 238
#endif
2214 jroman 239
  if (info>0) SETERRQ1(((PetscObject)eps)->comm,PETSC_ERR_LIB,"Error in blopex (code=%d)",info);
1199 slepc 240
 
2587 jroman 241
  if (eps->numbermonitors>0) {
242
    for (i=0;i<its;i++) {
243
      nconv = 0;
244
      for (j=0;j<eps->ncv;j++) { if (residhist[j+i*eps->ncv]>eps->tol) break; else nconv++; }
2725 jroman 245
      ierr = EPSMonitor(eps,i,nconv,(PetscScalar*)lambdahist+i*eps->ncv,eps->eigi,residhist+i*eps->ncv,eps->ncv);CHKERRQ(ierr);
2587 jroman 246
    }
247
    ierr = PetscFree(lambdahist);CHKERRQ(ierr);
248
    ierr = PetscFree(residhist);CHKERRQ(ierr);
249
  }
250
 
1509 slepc 251
  eps->its = its;
1199 slepc 252
  eps->nconv = eps->ncv;
2435 jroman 253
  if (eps->OP->sigma != 0.0) {
254
    for (i=0;i<eps->nconv;i++) eps->eigr[i]+=eps->OP->sigma;
255
  }
1199 slepc 256
  if (info==-1) eps->reason = EPS_DIVERGED_ITS;
257
  else eps->reason = EPS_CONVERGED_TOL;
258
  PetscFunctionReturn(0);
259
}
260
 
261
#undef __FUNCT__  
2348 jroman 262
#define __FUNCT__ "EPSReset_BLOPEX"
263
PetscErrorCode EPSReset_BLOPEX(EPS eps)
264
{
265
  PetscErrorCode ierr;
266
  EPS_BLOPEX     *blopex = (EPS_BLOPEX *)eps->data;
267
 
268
  PetscFunctionBegin;
269
  mv_MultiVectorDestroy(blopex->eigenvectors);
270
  mv_MultiVectorDestroy(blopex->Y);
2435 jroman 271
  ierr = VecDestroy(&blopex->w);CHKERRQ(ierr);
2348 jroman 272
  ierr = EPSReset_Default(eps);CHKERRQ(ierr);
273
  PetscFunctionReturn(0);
274
}
275
 
276
#undef __FUNCT__  
1199 slepc 277
#define __FUNCT__ "EPSDestroy_BLOPEX"
278
PetscErrorCode EPSDestroy_BLOPEX(EPS eps)
279
{
280
  PetscErrorCode ierr;
281
 
282
  PetscFunctionBegin;
283
  LOBPCG_DestroyRandomContext();
284
  ierr = PetscFree(eps->data);CHKERRQ(ierr);
285
  PetscFunctionReturn(0);
286
}
287
 
2448 eromero 288
#undef __FUNCT__  
289
#define __FUNCT__ "EPSSetFromOptions_BLOPEX"
290
PetscErrorCode EPSSetFromOptions_BLOPEX(EPS eps)
291
{
292
  PetscErrorCode  ierr;
293
 
294
  PetscFunctionBegin;
295
  ierr = PetscOptionsHead("EPS BLOPEX Options");CHKERRQ(ierr);
296
  LOBPCG_SetFromOptionsRandomContext();
297
  ierr = PetscOptionsTail();CHKERRQ(ierr);
298
  PetscFunctionReturn(0);
299
}
300
 
1199 slepc 301
EXTERN_C_BEGIN
302
#undef __FUNCT__  
303
#define __FUNCT__ "EPSCreate_BLOPEX"
304
PetscErrorCode EPSCreate_BLOPEX(EPS eps)
305
{
306
  PetscErrorCode ierr;
307
 
308
  PetscFunctionBegin;
2372 jroman 309
  ierr = PetscNewLog(eps,EPS_BLOPEX,&eps->data);CHKERRQ(ierr);
1199 slepc 310
  eps->ops->setup                = EPSSetUp_BLOPEX;
2448 eromero 311
  eps->ops->setfromoptions       = EPSSetFromOptions_BLOPEX;
1199 slepc 312
  eps->ops->destroy              = EPSDestroy_BLOPEX;
2348 jroman 313
  eps->ops->reset                = EPSReset_BLOPEX;
1199 slepc 314
  eps->ops->backtransform        = EPSBackTransform_Default;
315
  eps->ops->computevectors       = EPSComputeVectors_Default;
2348 jroman 316
  ierr = STSetType(eps->OP,STPRECOND);CHKERRQ(ierr);
317
  ierr = STPrecondSetKSPHasMat(eps->OP,PETSC_TRUE);CHKERRQ(ierr);
2695 jroman 318
  LOBPCG_InitRandomContext(((PetscObject)eps)->comm,eps->rand);
1199 slepc 319
  PetscFunctionReturn(0);
320
}
321
EXTERN_C_END