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