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
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3
      SLEPc - Scalable Library for Eigenvalue Problem Computations
4
      Copyright (c) 2002-2007, Universidad Politecnica de Valencia, Spain
6 dsic.upv.es!jroman 5
 
1376 slepc 6
      This file is part of SLEPc. See the README file for conditions of use
7
      and additional information.
8
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9
*/
10
 
228 dsic.upv.es!jroman 11
static char help[] = "Solves the same eigenproblem as in example ex2, but using a shell matrix. "
161 dsic.upv.es!antodo 12
  "The problem is a standard symmetric eigenproblem corresponding to the 2-D Laplacian operator.\n\n"
1156 slepc 13
  "The command line options are:\n"
6 dsic.upv.es!jroman 14
  "  -n <n>, where <n> = number of grid subdivisions in both x and y dimensions.\n\n";
15
 
16
#include "slepceps.h"
17
#include "petscblaslapack.h"
18
 
19
/*
20
   User-defined routines
21
*/
983 slepc 22
PetscErrorCode MatLaplacian2D_Mult( Mat A, Vec x, Vec y );
6 dsic.upv.es!jroman 23
 
24
#undef __FUNCT__
25
#define __FUNCT__ "main"
26
int main( int argc, char **argv )
27
{
1505 slepc 28
  Mat            A;               /* operator matrix */
29
  EPS            eps;             /* eigenproblem solver context */
1507 slepc 30
  const EPSType  type;
1505 slepc 31
  PetscReal      error, tol, re, im;
32
  PetscScalar    kr, ki;
33
  PetscMPIInt    size;
983 slepc 34
  PetscErrorCode ierr;
1505 slepc 35
  PetscInt       N, n=10, nev, maxit, i, its, nconv;
6 dsic.upv.es!jroman 36
 
37
  SlepcInitialize(&argc,&argv,(char*)0,help);
38
  ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
39
  if (size != 1) SETERRQ(1,"This is a uniprocessor example only!");
40
 
41
  ierr = PetscOptionsGetInt(PETSC_NULL,"-n",&n,PETSC_NULL);CHKERRQ(ierr);
42
  N = n*n;
43
  ierr = PetscPrintf(PETSC_COMM_WORLD,"\n2-D Laplacian Eigenproblem (matrix-free version), N=%d (%dx%d grid)\n\n",N,n,n);CHKERRQ(ierr);
44
 
45
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
46
     Compute the operator matrix that defines the eigensystem, Ax=kx
47
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
48
 
49
  ierr = MatCreateShell(PETSC_COMM_WORLD,N,N,N,N,&n,&A);CHKERRQ(ierr);
50
  ierr = MatSetFromOptions(A);CHKERRQ(ierr);
51
  ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)())MatLaplacian2D_Mult);CHKERRQ(ierr);
58 dsic.upv.es!jroman 52
  ierr = MatShellSetOperation(A,MATOP_MULT_TRANSPOSE,(void(*)())MatLaplacian2D_Mult);CHKERRQ(ierr);
6 dsic.upv.es!jroman 53
 
54
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
55
                Create the eigensolver and set various options
56
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
57
 
58
  /*
59
     Create eigensolver context
60
  */
61
  ierr = EPSCreate(PETSC_COMM_WORLD,&eps);CHKERRQ(ierr);
62
 
63
  /*
64
     Set operators. In this case, it is a standard eigenvalue problem
65
  */
66
  ierr = EPSSetOperators(eps,A,PETSC_NULL);CHKERRQ(ierr);
408 dsic.upv.es!antodo 67
  ierr = EPSSetProblemType(eps,EPS_HEP);CHKERRQ(ierr);
6 dsic.upv.es!jroman 68
 
69
  /*
70
     Set solver parameters at runtime
71
  */
72
  ierr = EPSSetFromOptions(eps);CHKERRQ(ierr);
73
 
74
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
75
                      Solve the eigensystem
76
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
77
 
78 dsic.upv.es!antodo 78
  ierr = EPSSolve(eps);CHKERRQ(ierr);
79
  ierr = EPSGetIterationNumber(eps, &its);CHKERRQ(ierr);
6 dsic.upv.es!jroman 80
  ierr = PetscPrintf(PETSC_COMM_WORLD," Number of iterations of the method: %d\n",its);CHKERRQ(ierr);
81
 
82
  /*
83
     Optional: Get some information from the solver and display it
84
  */
85
  ierr = EPSGetType(eps,&type);CHKERRQ(ierr);
86
  ierr = PetscPrintf(PETSC_COMM_WORLD," Solution method: %s\n\n",type);CHKERRQ(ierr);
1575 slepc 87
  ierr = EPSGetDimensions(eps,&nev,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
6 dsic.upv.es!jroman 88
  ierr = PetscPrintf(PETSC_COMM_WORLD," Number of requested eigenvalues: %d\n",nev);CHKERRQ(ierr);
89
  ierr = EPSGetTolerances(eps,&tol,&maxit);CHKERRQ(ierr);
90
  ierr = PetscPrintf(PETSC_COMM_WORLD," Stopping condition: tol=%.4g, maxit=%d\n",tol,maxit);CHKERRQ(ierr);
91
 
92
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
93
                    Display solution and clean up
94
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
95
 
96
  /*
97 dsic.upv.es!antodo 97
     Get number of converged approximate eigenpairs
6 dsic.upv.es!jroman 98
  */
132 dsic.upv.es!antodo 99
  ierr = EPSGetConverged(eps,&nconv);CHKERRQ(ierr);
100
  ierr = PetscPrintf(PETSC_COMM_WORLD," Number of converged eigenpairs: %d\n\n",nconv);
97 dsic.upv.es!antodo 101
         CHKERRQ(ierr);
6 dsic.upv.es!jroman 102
 
132 dsic.upv.es!antodo 103
  if (nconv>0) {
6 dsic.upv.es!jroman 104
    /*
105
       Display eigenvalues and relative errors
106
    */
107
    ierr = PetscPrintf(PETSC_COMM_WORLD,
97 dsic.upv.es!antodo 108
         "           k          ||Ax-kx||/||kx||\n"
109
         "   ----------------- ------------------\n" );CHKERRQ(ierr);
110
 
132 dsic.upv.es!antodo 111
    for( i=0; i<nconv; i++ ) {
97 dsic.upv.es!antodo 112
      /*
113
        Get converged eigenpairs: i-th eigenvalue is stored in kr (real part) and
114
        ki (imaginary part)
115
      */
132 dsic.upv.es!antodo 116
      ierr = EPSGetEigenpair(eps,i,&kr,&ki,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
97 dsic.upv.es!antodo 117
      /*
118
         Compute the relative error associated to each eigenpair
119
      */
120
      ierr = EPSComputeRelativeError(eps,i,&error);CHKERRQ(ierr);
121
 
122
#ifdef PETSC_USE_COMPLEX
132 dsic.upv.es!antodo 123
      re = PetscRealPart(kr);
124
      im = PetscImaginaryPart(kr);
125
#else
126
      re = kr;
127
      im = ki;
97 dsic.upv.es!antodo 128
#endif
132 dsic.upv.es!antodo 129
      if (im!=0.0) {
1162 slepc 130
        ierr = PetscPrintf(PETSC_COMM_WORLD," %9f%+9f j %12g\n",re,im,error);CHKERRQ(ierr);
97 dsic.upv.es!antodo 131
      } else {
1162 slepc 132
        ierr = PetscPrintf(PETSC_COMM_WORLD,"   %12f       %12g\n",re,error);CHKERRQ(ierr);
97 dsic.upv.es!antodo 133
      }
6 dsic.upv.es!jroman 134
    }
135
    ierr = PetscPrintf(PETSC_COMM_WORLD,"\n" );CHKERRQ(ierr);
136
  }
137
 
138
  /*
139
     Free work space
140
  */
141
  ierr = EPSDestroy(eps);CHKERRQ(ierr);
142
  ierr = MatDestroy(A);CHKERRQ(ierr);
143
  ierr = SlepcFinalize();CHKERRQ(ierr);
144
  return 0;
145
}
146
 
147
/*
148
    Compute the matrix vector multiplication y<---T*x where T is a nx by nx
149
    tridiagonal matrix with DD on the diagonal, DL on the subdiagonal, and
150
    DU on the superdiagonal.
151
 */  
152
static void tv( int nx, PetscScalar *x, PetscScalar *y )
153
{
154
  PetscScalar dd, dl, du;
155
  int         j;
156
 
157
  dd  = 4.0;
158
  dl  = -1.0;
159
  du  = -1.0;
160
 
161
  y[0] =  dd*x[0] + du*x[1];
162
  for( j=1; j<nx-1; j++ )
163
    y[j] = dl*x[j-1] + dd*x[j] + du*x[j+1];
164
  y[nx-1] = dl*x[nx-2] + dd*x[nx-1];
165
}
166
 
167
#undef __FUNCT__
168
#define __FUNCT__ "MatLaplacian2D_Mult"
169
/*
170
    Matrix-vector product subroutine for the 2D Laplacian.
171
 
172
    The matrix used is the 2 dimensional discrete Laplacian on unit square with
173
    zero Dirichlet boundary condition.
174
 
175
    Computes y <-- A*x, where A is the block tridiagonal matrix
176
 
177
                 | T -I          |
178
                 |-I  T -I       |
179
             A = |   -I  T       |
180
                 |        ...  -I|
181
                 |           -I T|
182
 
183
    The subroutine TV is called to compute y<--T*x.
184
 */
983 slepc 185
PetscErrorCode MatLaplacian2D_Mult( Mat A, Vec x, Vec y )
6 dsic.upv.es!jroman 186
{
983 slepc 187
  void           *ctx;
188
  PetscErrorCode ierr;
189
  int            nx, lo, j, one=1;
190
  PetscScalar    *px, *py, dmone=-1.0;
6 dsic.upv.es!jroman 191
 
983 slepc 192
  PetscFunctionBegin;
6 dsic.upv.es!jroman 193
  ierr = MatShellGetContext( A, &ctx ); CHKERRQ(ierr);
194
  nx = *(int *)ctx;
195
  ierr = VecGetArray( x, &px ); CHKERRQ(ierr);
196
  ierr = VecGetArray( y, &py ); CHKERRQ(ierr);
197
 
198
  tv( nx, &px[0], &py[0] );
801 dsic.upv.es!antodo 199
  BLASaxpy_( &nx, &dmone, &px[nx], &one, &py[0], &one );
6 dsic.upv.es!jroman 200
 
201
  for( j=2; j<nx; j++ ) {
202
    lo = (j-1)*nx;
203
    tv( nx, &px[lo], &py[lo]);
801 dsic.upv.es!antodo 204
    BLASaxpy_( &nx, &dmone, &px[lo-nx], &one, &py[lo], &one );
205
    BLASaxpy_( &nx, &dmone, &px[lo+nx], &one, &py[lo], &one );
6 dsic.upv.es!jroman 206
  }
207
 
208
  lo = (nx-1)*nx;
209
  tv( nx, &px[lo], &py[lo]);
801 dsic.upv.es!antodo 210
  BLASaxpy_( &nx, &dmone, &px[lo-nx], &one, &py[lo], &one );
6 dsic.upv.es!jroman 211
 
212
  ierr = VecRestoreArray( x, &px ); CHKERRQ(ierr);
213
  ierr = VecRestoreArray( y, &py ); CHKERRQ(ierr);
983 slepc 214
  PetscFunctionReturn(0);
6 dsic.upv.es!jroman 215
}
216