Subversion Repositories slepc-dev

Rev

Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1376 slepc 1
/*
2
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 3
   SLEPc - Scalable Library for Eigenvalue Problem Computations
4
   Copyright (c) 2002-2009, Universidad Politecnica de Valencia, Spain
1376 slepc 5
 
1672 slepc 6
   This file is part of SLEPc.
7
 
8
   SLEPc is free software: you can redistribute it and/or modify it under  the
9
   terms of version 3 of the GNU Lesser General Public License as published by
10
   the Free Software Foundation.
11
 
12
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
13
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
14
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
15
   more details.
16
 
17
   You  should have received a copy of the GNU Lesser General  Public  License
18
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
1376 slepc 19
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
20
*/
21
 
228 dsic.upv.es!jroman 22
static char help[] = "Illustrates the use of shell spectral transformations. "
161 dsic.upv.es!antodo 23
  "The problem to be solved is the same as ex1.c and"
6 dsic.upv.es!jroman 24
  "corresponds to the Laplacian operator in 1 dimension.\n\n"
1156 slepc 25
  "The command line options are:\n"
6 dsic.upv.es!jroman 26
  "  -n <n>, where <n> = number of grid subdivisions = matrix dimension.\n\n";
27
 
28
#include "slepceps.h"
29
 
30
/* Define context for user-provided spectral transformation */
31
typedef struct {
18 dsic.upv.es!jroman 32
  KSP        ksp;
6 dsic.upv.es!jroman 33
} SampleShellST;
34
 
35
/* Declare routines for user-provided spectral transformation */
983 slepc 36
PetscErrorCode SampleShellSTCreate(SampleShellST**);
37
PetscErrorCode SampleShellSTSetUp(SampleShellST*,ST);
38
PetscErrorCode SampleShellSTApply(void*,Vec,Vec);
39
PetscErrorCode SampleShellSTBackTransform(void*,PetscScalar*,PetscScalar*);
40
PetscErrorCode SampleShellSTDestroy(SampleShellST*);
6 dsic.upv.es!jroman 41
 
42
#undef __FUNCT__
43
#define __FUNCT__ "main"
44
int main( int argc, char **argv )
45
{
983 slepc 46
  Mat            A;               /* operator matrix */
47
  EPS            eps;             /* eigenproblem solver context */
48
  ST             st;              /* spectral transformation context */
49
  SampleShellST  *shell;          /* user-defined spectral transform context */
1507 slepc 50
  const EPSType  type;
983 slepc 51
  PetscReal      error, tol, re, im;
52
  PetscScalar    kr, ki;
53
  PetscErrorCode ierr;
1505 slepc 54
  PetscInt       n=30, i, col[3], Istart, Iend, FirstBlock=0, LastBlock=0, nev, maxit, its, nconv;
983 slepc 55
  PetscScalar    value[3];
56
  PetscTruth     isShell;
6 dsic.upv.es!jroman 57
 
58
  SlepcInitialize(&argc,&argv,(char*)0,help);
59
 
60
  ierr = PetscOptionsGetInt(PETSC_NULL,"-n",&n,PETSC_NULL);CHKERRQ(ierr);
1024 slepc 61
  ierr = PetscPrintf(PETSC_COMM_WORLD,"\n1-D Laplacian Eigenproblem (shell-enabled), n=%d\n\n",n);CHKERRQ(ierr);
6 dsic.upv.es!jroman 62
 
63
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
64
     Compute the operator matrix that defines the eigensystem, Ax=kx
65
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
66
 
828 dsic.upv.es!antodo 67
  ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr);
68
  ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,n,n);CHKERRQ(ierr);
6 dsic.upv.es!jroman 69
  ierr = MatSetFromOptions(A);CHKERRQ(ierr);
70
 
71
  ierr = MatGetOwnershipRange(A,&Istart,&Iend);CHKERRQ(ierr);
72
  if (Istart==0) FirstBlock=PETSC_TRUE;
73
  if (Iend==n) LastBlock=PETSC_TRUE;
74
  value[0]=-1.0; value[1]=2.0; value[2]=-1.0;
75
  for( i=(FirstBlock? Istart+1: Istart); i<(LastBlock? Iend-1: Iend); i++ ) {
76
    col[0]=i-1; col[1]=i; col[2]=i+1;
77
    ierr = MatSetValues(A,1,&i,3,col,value,INSERT_VALUES);CHKERRQ(ierr);
78
  }
79
  if (LastBlock) {
80
    i=n-1; col[0]=n-2; col[1]=n-1;
81
    ierr = MatSetValues(A,1,&i,2,col,value,INSERT_VALUES);CHKERRQ(ierr);
82
  }
83
  if (FirstBlock) {
84
    i=0; col[0]=0; col[1]=1; value[0]=2.0; value[1]=-1.0;
85
    ierr = MatSetValues(A,1,&i,2,col,value,INSERT_VALUES);CHKERRQ(ierr);
86
  }
87
 
88
  ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
89
  ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
90
 
91
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
92
                Create the eigensolver and set various options
93
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
94
 
95
  /*
96
     Create eigensolver context
97
  */
98
  ierr = EPSCreate(PETSC_COMM_WORLD,&eps);CHKERRQ(ierr);
99
 
100
  /*
101
     Set operators. In this case, it is a standard eigenvalue problem
102
  */
103
  ierr = EPSSetOperators(eps,A,PETSC_NULL);CHKERRQ(ierr);
408 dsic.upv.es!antodo 104
  ierr = EPSSetProblemType(eps,EPS_HEP);CHKERRQ(ierr);
6 dsic.upv.es!jroman 105
 
106
  /*
107
     Set solver parameters at runtime
108
  */
109
  ierr = EPSSetFromOptions(eps);CHKERRQ(ierr);
110
 
111
  /*
112
     Initialize shell spectral transformation if selected by user
113
  */
114
  ierr = EPSGetST(eps,&st);CHKERRQ(ierr);
115
  ierr = PetscTypeCompare((PetscObject)st,STSHELL,&isShell);CHKERRQ(ierr);
116
  if (isShell) {
117
    /* (Optional) Create a context for the user-defined spectral tranform;
118
       this context can be defined to contain any application-specific data. */
119
    ierr = SampleShellSTCreate(&shell);CHKERRQ(ierr);
120
 
121
    /* (Required) Set the user-defined routine for applying the operator */
1024 slepc 122
    ierr = STShellSetApply(st,SampleShellSTApply);CHKERRQ(ierr);
123
    ierr = STShellSetContext(st,shell);CHKERRQ(ierr);
6 dsic.upv.es!jroman 124
 
125
    /* (Optional) Set the user-defined routine for back-transformation */
126
    ierr = STShellSetBackTransform(st,SampleShellSTBackTransform);CHKERRQ(ierr);
127
 
128
    /* (Optional) Set a name for the transformation, used for STView() */
129
    ierr = STShellSetName(st,"MyTransformation");CHKERRQ(ierr);
130
 
131
    /* (Optional) Do any setup required for the new transformation */
132
    ierr = SampleShellSTSetUp(shell,st);CHKERRQ(ierr);
133
  }
134
 
135
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
136
                      Solve the eigensystem
137
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
138
 
78 dsic.upv.es!antodo 139
  ierr = EPSSolve(eps);CHKERRQ(ierr);
140
  ierr = EPSGetIterationNumber(eps, &its);CHKERRQ(ierr);
1024 slepc 141
  ierr = PetscPrintf(PETSC_COMM_WORLD," Number of iterations of the method: %d\n",its);CHKERRQ(ierr);
6 dsic.upv.es!jroman 142
 
143
  /*
144
     Optional: Get some information from the solver and display it
145
  */
146
  ierr = EPSGetType(eps,&type);CHKERRQ(ierr);
147
  ierr = PetscPrintf(PETSC_COMM_WORLD," Solution method: %s\n\n",type);CHKERRQ(ierr);
1575 slepc 148
  ierr = EPSGetDimensions(eps,&nev,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1024 slepc 149
  ierr = PetscPrintf(PETSC_COMM_WORLD," Number of requested eigenvalues: %d\n",nev);CHKERRQ(ierr);
6 dsic.upv.es!jroman 150
  ierr = EPSGetTolerances(eps,&tol,&maxit);CHKERRQ(ierr);
1024 slepc 151
  ierr = PetscPrintf(PETSC_COMM_WORLD," Stopping condition: tol=%.4g, maxit=%d\n",tol,maxit);CHKERRQ(ierr);
6 dsic.upv.es!jroman 152
 
153
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
154
                    Display solution and clean up
155
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
156
 
157
  /*
158
     Get number of converged approximate eigenpairs
159
  */
132 dsic.upv.es!antodo 160
  ierr = EPSGetConverged(eps,&nconv);CHKERRQ(ierr);
1024 slepc 161
  ierr = PetscPrintf(PETSC_COMM_WORLD," Number of converged eigenpairs: %d\n\n",nconv);CHKERRQ(ierr);
6 dsic.upv.es!jroman 162
 
132 dsic.upv.es!antodo 163
  if (nconv>0) {
6 dsic.upv.es!jroman 164
    /*
165
       Display eigenvalues and relative errors
166
    */
167
    ierr = PetscPrintf(PETSC_COMM_WORLD,
97 dsic.upv.es!antodo 168
         "           k          ||Ax-kx||/||kx||\n"
169
         "   ----------------- ------------------\n" );CHKERRQ(ierr);
170
 
132 dsic.upv.es!antodo 171
    for( i=0; i<nconv; i++ ) {
97 dsic.upv.es!antodo 172
      /*
173
        Get converged eigenpairs: i-th eigenvalue is stored in kr (real part) and
174
        ki (imaginary part)
175
      */
176
      ierr = EPSGetEigenpair(eps,i,&kr,&ki,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
177
      /*
178
         Compute the relative error associated to each eigenpair
179
      */
180
      ierr = EPSComputeRelativeError(eps,i,&error);CHKERRQ(ierr);
181
 
182
#ifdef PETSC_USE_COMPLEX
132 dsic.upv.es!antodo 183
      re = PetscRealPart(kr);
184
      im = PetscImaginaryPart(kr);
185
#else
186
      re = kr;
187
      im = ki;
97 dsic.upv.es!antodo 188
#endif
132 dsic.upv.es!antodo 189
      if (im!=0.0) {
1162 slepc 190
        ierr = PetscPrintf(PETSC_COMM_WORLD," %9f%+9f j %12g\n",re,im,error);CHKERRQ(ierr);
97 dsic.upv.es!antodo 191
      } else {
1162 slepc 192
        ierr = PetscPrintf(PETSC_COMM_WORLD,"   %12f       %12g\n",re,error);CHKERRQ(ierr);
97 dsic.upv.es!antodo 193
      }
6 dsic.upv.es!jroman 194
    }
195
    ierr = PetscPrintf(PETSC_COMM_WORLD,"\n" );CHKERRQ(ierr);
196
  }
197
 
198
  /*
199
     Free work space
200
  */
201
  if (isShell) {
202
    ierr = SampleShellSTDestroy(shell);CHKERRQ(ierr);
203
  }
204
  ierr = EPSDestroy(eps);CHKERRQ(ierr);
205
  ierr = MatDestroy(A);CHKERRQ(ierr);
206
  ierr = SlepcFinalize();CHKERRQ(ierr);
207
  return 0;
208
}
209
 
210
/***********************************************************************/
1024 slepc 211
/*     Routines for a user-defined shell spectral transformation       */
6 dsic.upv.es!jroman 212
/***********************************************************************/
213
 
214
#undef __FUNCT__  
215
#define __FUNCT__ "SampleShellSTCreate"
216
/*
217
   SampleShellSTCreate - This routine creates a user-defined
218
   spectral transformation context.
219
 
220
   Output Parameter:
221
.  shell - user-defined spectral transformation context
222
*/
983 slepc 223
PetscErrorCode SampleShellSTCreate(SampleShellST **shell)
6 dsic.upv.es!jroman 224
{
983 slepc 225
  SampleShellST  *newctx;
226
  PetscErrorCode ierr;
6 dsic.upv.es!jroman 227
 
983 slepc 228
  PetscFunctionBegin;
6 dsic.upv.es!jroman 229
  ierr   = PetscNew(SampleShellST,&newctx);CHKERRQ(ierr);
18 dsic.upv.es!jroman 230
  ierr   = KSPCreate(PETSC_COMM_WORLD,&newctx->ksp);CHKERRQ(ierr);
231
  ierr   = KSPAppendOptionsPrefix(newctx->ksp,"st_"); CHKERRQ(ierr);
6 dsic.upv.es!jroman 232
  *shell = newctx;
983 slepc 233
  PetscFunctionReturn(0);
6 dsic.upv.es!jroman 234
}
235
/* ------------------------------------------------------------------- */
236
#undef __FUNCT__  
237
#define __FUNCT__ "SampleShellSTSetUp"
238
/*
239
   SampleShellSTSetUp - This routine sets up a user-defined
240
   spectral transformation context.  
241
 
242
   Input Parameters:
243
.  shell - user-defined spectral transformation context
244
.  st    - spectral transformation context containing the operator matrices
245
 
246
   Output Parameter:
247
.  shell - fully set up user-defined transformation context
248
 
249
   Notes:
250
   In this example, the user-defined transformation is simply OP=A^-1.
18 dsic.upv.es!jroman 251
   Therefore, the eigenpairs converge in reversed order. The KSP object
6 dsic.upv.es!jroman 252
   used for the solution of linear systems with A is handled via the
253
   user-defined context SampleShellST.
254
*/
983 slepc 255
PetscErrorCode SampleShellSTSetUp(SampleShellST *shell,ST st)
6 dsic.upv.es!jroman 256
{
983 slepc 257
  Mat            A,B;
258
  PetscErrorCode ierr;
6 dsic.upv.es!jroman 259
 
983 slepc 260
  PetscFunctionBegin;
1024 slepc 261
  ierr = STGetOperators(st,&A,&B);CHKERRQ(ierr);
6 dsic.upv.es!jroman 262
  if (B) { SETERRQ(0,"Warning: This transformation is not intended for generalized problems"); }
18 dsic.upv.es!jroman 263
  ierr = KSPSetOperators(shell->ksp,A,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
264
  ierr = KSPSetFromOptions(shell->ksp);CHKERRQ(ierr);
983 slepc 265
  PetscFunctionReturn(0);
6 dsic.upv.es!jroman 266
}
267
/* ------------------------------------------------------------------- */
268
#undef __FUNCT__  
269
#define __FUNCT__ "SampleShellSTApply"
270
/*
271
   SampleShellSTApply - This routine demonstrates the use of a
272
   user-provided spectral transformation.
273
 
274
   Input Parameters:
1024 slepc 275
.  ctx - optional user-defined context, as set by STShellSetContext()
6 dsic.upv.es!jroman 276
.  x - input vector
277
 
278
   Output Parameter:
279
.  y - output vector
280
 
281
   Notes:
282
   The transformation implemented in this code is just OP=A^-1 and
283
   therefore it is of little use, merely as an example of working with
284
   a STSHELL.
285
*/
983 slepc 286
PetscErrorCode SampleShellSTApply(void *ctx,Vec x,Vec y)
6 dsic.upv.es!jroman 287
{
983 slepc 288
  SampleShellST  *shell = (SampleShellST*)ctx;
289
  PetscErrorCode ierr;
6 dsic.upv.es!jroman 290
 
983 slepc 291
  PetscFunctionBegin;
239 dsic.upv.es!antodo 292
  ierr = KSPSolve(shell->ksp,x,y);CHKERRQ(ierr);
983 slepc 293
  PetscFunctionReturn(0);
6 dsic.upv.es!jroman 294
}
295
/* ------------------------------------------------------------------- */
296
#undef __FUNCT__  
297
#define __FUNCT__ "SampleShellSTBackTransform"
298
/*
299
   SampleShellSTBackTransform - This routine demonstrates the use of a
300
   user-provided spectral transformation.
301
 
302
   Input Parameters:
1024 slepc 303
.  ctx  - optional user-defined context, as set by STShellSetContext()
6 dsic.upv.es!jroman 304
.  eigr - pointer to real part of eigenvalues
305
.  eigi - pointer to imaginary part of eigenvalues
306
 
307
   Output Parameters:
308
.  eigr - modified real part of eigenvalues
309
.  eigi - modified imaginary part of eigenvalues
310
 
311
   Notes:
312
   This code implements the back transformation of eigenvalues in
313
   order to retrieve the eigenvalues of the original problem. In this
314
   example, simply set k_i = 1/k_i.
315
*/
983 slepc 316
PetscErrorCode SampleShellSTBackTransform(void *ctx,PetscScalar *eigr,PetscScalar *eigi)
6 dsic.upv.es!jroman 317
{
983 slepc 318
  PetscFunctionBegin;
6 dsic.upv.es!jroman 319
  *eigr = 1.0 / *eigr;
983 slepc 320
  PetscFunctionReturn(0);
6 dsic.upv.es!jroman 321
}
322
/* ------------------------------------------------------------------- */
323
#undef __FUNCT__  
324
#define __FUNCT__ "SampleShellSTDestroy"
325
/*
326
   SampleShellSTDestroy - This routine destroys a user-defined
327
   spectral transformation context.
328
 
329
   Input Parameter:
330
.  shell - user-defined spectral transformation context
331
*/
983 slepc 332
PetscErrorCode SampleShellSTDestroy(SampleShellST *shell)
6 dsic.upv.es!jroman 333
{
983 slepc 334
  PetscErrorCode ierr;
6 dsic.upv.es!jroman 335
 
983 slepc 336
  PetscFunctionBegin;
18 dsic.upv.es!jroman 337
  ierr = KSPDestroy(shell->ksp);CHKERRQ(ierr);
6 dsic.upv.es!jroman 338
  ierr = PetscFree(shell);CHKERRQ(ierr);
983 slepc 339
  PetscFunctionReturn(0);
6 dsic.upv.es!jroman 340
}
341
 
342