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