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
 
2
static char help[] = "This example solves the eigenvalue problem associated to"
3
  "the Brusselator wave model in chemical reactions.\n\n"
4
  "The command line options are:\n\n"
5
  "  -n <n>, where <n> = block dimension of the 2x2 block matrix.\n"
6
  "  -L <L>, where <L> = bifurcation parameter.\n"
7
  "  -alpha <alpha>, -beta <beta>, -delta1 <delta1>,  -delta2 <delta2>,\n"
8
  "       where <alpha> <beta> <delta1> <delta2> = model parameters.\n\n";
9
 
10
#include "slepceps.h"
11
 
12
/*
13
   This example computes the eigenvalues with largest real part of the
14
   following matrix
15
 
16
        A = [ tau1*T+(beta-1)*I     alpha^2*I
17
                  -beta*I        tau2*T-alpha^2*I ],
18
 
19
   where
20
 
21
        T = tridiag{1,-2,1}
22
        h = 1/(n+1)
23
        tau1 = delta1/(h*L)^2
24
        tau2 = delta2/(h*L)^2
25
 */
26
 
27
 
28
/*
29
   Matrix operations
30
*/
31
extern int MatBrussel_Mult(Mat,Vec,Vec);
32
extern int MatBrussel_Shift(PetscScalar*,Mat);
33
extern int MatBrussel_GetDiagonal(Mat,Vec);
34
 
35
typedef struct {
36
  Mat         T;
37
  Vec         x1, x2, y1, y2;
38
  PetscScalar alpha, beta, tau1, tau2, sigma;
39
} CTX_BRUSSEL;
40
 
41
#undef __FUNCT__
42
#define __FUNCT__ "main"
43
int main( int argc, char **argv )
44
{
45
  Vec         *x;              /* basis vectors */
46
  Mat         A;               /* eigenvalue problem matrix */
47
  EPS         eps;             /* eigenproblem solver context */
48
  EPSType     type;
49
  PetscReal   *error, tol, re, im;
50
  PetscScalar delta1, delta2, L, h, *kr, *ki, value[3];
51
  int         N=30, n, nev, ierr, maxit, i, its, nconv,
52
              col[3], Istart, Iend, FirstBlock=0, LastBlock=0;
53
  CTX_BRUSSEL *ctx;
54
 
55
  SlepcInitialize(&argc,&argv,(char*)0,help);
56
 
57
  ierr = PetscOptionsGetInt(PETSC_NULL,"-n",&N,PETSC_NULL);CHKERRQ(ierr);
58
  ierr = PetscPrintf(PETSC_COMM_WORLD,"\nBrusselator wave model, n=%d\n\n",N);CHKERRQ(ierr);
59
 
60
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
61
        Generate the matrix
62
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
63
 
64
  /*
65
     Create shell matrix context and set default parameters
66
  */
67
  ierr = PetscNew(CTX_BRUSSEL,&ctx);CHKERRQ(ierr);
68
  ctx->alpha = 2.0;
69
  ctx->beta  = 5.45;
70
  delta1     = 0.008;
71
  delta2     = 0.004;
72
  L          = 0.51302;
73
 
74
  /*
75
     Look the command line for user-provided parameters
76
  */
77
  ierr = PetscOptionsGetScalar(PETSC_NULL,"-L",&L,PETSC_NULL);CHKERRQ(ierr);
78
  ierr = PetscOptionsGetScalar(PETSC_NULL,"-alpha",&ctx->alpha,PETSC_NULL);CHKERRQ(ierr);
79
  ierr = PetscOptionsGetScalar(PETSC_NULL,"-beta",&ctx->beta,PETSC_NULL);CHKERRQ(ierr);
80
  ierr = PetscOptionsGetScalar(PETSC_NULL,"-delta1",&delta1,PETSC_NULL);CHKERRQ(ierr);
81
  ierr = PetscOptionsGetScalar(PETSC_NULL,"-delta2",&delta2,PETSC_NULL);CHKERRQ(ierr);
82
 
83
  /*
84
     Create matrix T
85
  */
86
  ierr = MatCreate(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,N,N,&ctx->T);CHKERRQ(ierr);
87
  ierr = MatSetFromOptions(ctx->T);CHKERRQ(ierr);
88
 
89
  ierr = MatGetOwnershipRange(ctx->T,&Istart,&Iend);CHKERRQ(ierr);
90
  if (Istart==0) FirstBlock=PETSC_TRUE;
91
  if (Iend==N) LastBlock=PETSC_TRUE;
92
  value[0]=1.0; value[1]=-2.0; value[2]=1.0;
93
  for( i=(FirstBlock? Istart+1: Istart); i<(LastBlock? Iend-1: Iend); i++ ) {
94
    col[0]=i-1; col[1]=i; col[2]=i+1;
95
    ierr = MatSetValues(ctx->T,1,&i,3,col,value,INSERT_VALUES);CHKERRQ(ierr);
96
  }
97
  if (LastBlock) {
98
    i=N-1; col[0]=N-2; col[1]=N-1;
99
    ierr = MatSetValues(ctx->T,1,&i,2,col,value,INSERT_VALUES);CHKERRQ(ierr);
100
  }
101
  if (FirstBlock) {
102
    i=0; col[0]=0; col[1]=1; value[0]=-2.0; value[1]=1.0;
103
    ierr = MatSetValues(ctx->T,1,&i,2,col,value,INSERT_VALUES);CHKERRQ(ierr);
104
  }
105
 
106
  ierr = MatAssemblyBegin(ctx->T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
107
  ierr = MatAssemblyEnd(ctx->T,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
108
  ierr = MatGetLocalSize(ctx->T,&n,PETSC_NULL);CHKERRQ(ierr);
109
 
110
  /*
111
     Fill the remaining information in the shell matrix context
112
     and create auxiliary vectors
113
  */
114
  h = 1.0 / (double)(N+1);
115
  ctx->tau1 = delta1 / ((h*L)*(h*L));
116
  ctx->tau2 = delta2 / ((h*L)*(h*L));
117
  ctx->sigma = 0.0;
118
  ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,n,PETSC_DECIDE,PETSC_NULL,&ctx->x1);CHKERRQ(ierr);
119
  ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,n,PETSC_DECIDE,PETSC_NULL,&ctx->x2);CHKERRQ(ierr);
120
  ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,n,PETSC_DECIDE,PETSC_NULL,&ctx->y1);CHKERRQ(ierr);
121
  ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,n,PETSC_DECIDE,PETSC_NULL,&ctx->y2);CHKERRQ(ierr);
122
 
123
  /*
124
     Create the shell matrix
125
  */
126
  ierr = MatCreateShell(PETSC_COMM_WORLD,2*n,2*n,2*N,2*N,(void*)ctx,&A);CHKERRQ(ierr);
127
  ierr = MatShellSetOperation(A,MATOP_MULT,(void(*)())MatBrussel_Mult);CHKERRQ(ierr);
128
  ierr = MatShellSetOperation(A,MATOP_SHIFT,(void(*)())MatBrussel_Shift);CHKERRQ(ierr);
129
  ierr = MatShellSetOperation(A,MATOP_GET_DIAGONAL,(void(*)())MatBrussel_GetDiagonal);CHKERRQ(ierr);
130
 
131
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
132
                Create the eigensolver and set various options
133
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
134
 
135
  /*
136
     Create eigensolver context
137
  */
138
  ierr = EPSCreate(PETSC_COMM_WORLD,&eps);CHKERRQ(ierr);
139
 
140
  /*
141
     Set operators. In this case, it is a standard eigenvalue problem
142
  */
143
  ierr = EPSSetOperators(eps,A,PETSC_NULL);CHKERRQ(ierr);
144
 
145
  /*
146
     Force to use ARPACK if it is installed and ask for the rightmost eigenvalues
147
  */
148
#if defined(SLEPC_HAVE_ARPACK)
149
  ierr = EPSSetType(eps,EPSARPACK);CHKERRQ(ierr);
150
  ierr = EPSSetWhichEigenpairs(eps,EPS_LARGEST_REAL);CHKERRQ(ierr);
151
  ierr = EPSSetDimensions(eps,PETSC_DEFAULT,12);CHKERRQ(ierr);
152
#endif
153
 
154
  /*
155
     Set other solver options at runtime
156
  */
157
  ierr = EPSSetFromOptions(eps);CHKERRQ(ierr);
158
 
159
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
160
                      Solve the eigensystem
161
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
162
 
163
  ierr = EPSSolve(eps,&its);CHKERRQ(ierr);
164
  ierr = PetscPrintf(PETSC_COMM_WORLD," Number of iterations of the method: %d\n",its);CHKERRQ(ierr);
165
 
166
  /*
167
     Optional: Get some information from the solver and display it
168
  */
169
  ierr = EPSGetType(eps,&type);CHKERRQ(ierr);
170
  ierr = PetscPrintf(PETSC_COMM_WORLD," Solution method: %s\n\n",type);CHKERRQ(ierr);
171
  ierr = EPSGetDimensions(eps,&nev,PETSC_NULL);CHKERRQ(ierr);
172
  ierr = PetscPrintf(PETSC_COMM_WORLD," Number of requested eigenvalues: %d\n",nev);CHKERRQ(ierr);
173
  ierr = EPSGetTolerances(eps,&tol,&maxit);CHKERRQ(ierr);
174
  ierr = PetscPrintf(PETSC_COMM_WORLD," Stopping condition: tol=%.4g, maxit=%d\n",tol,maxit);CHKERRQ(ierr);
175
 
176
  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
177
                    Display solution and clean up
178
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
179
 
180
  /*
181
     Get number of converged eigenpairs
182
  */
183
  ierr = EPSGetConverged(eps,&nconv);CHKERRQ(ierr);
184
  ierr = PetscPrintf(PETSC_COMM_WORLD," Number of converged approximate eigenpairs: %d\n\n",nconv);CHKERRQ(ierr);
185
 
186
  if (nconv>0) {
187
    /*
188
       Get converged eigenpairs: i-th eigenvalue is stored in kr[i] (real part) and
189
       ki[i] (imaginary part), and the corresponding eigenvector is stored in x[i]
190
    */
191
    ierr = EPSGetSolution(eps,&kr,&ki,&x);CHKERRQ(ierr);
192
 
193
    /*
194
       Compute the relative error associated to each eigenpair
195
    */
196
    ierr = PetscMalloc(nconv*sizeof(PetscReal),&error);CHKERRQ(ierr);
197
    ierr = EPSComputeError(eps,error);CHKERRQ(ierr);
198
 
199
    /*
200
       Display eigenvalues and relative errors
201
    */
202
    ierr = PetscPrintf(PETSC_COMM_WORLD,
203
         "           k              ||Ax-kx||/|k|\n"
204
         "  --------------------- -----------------\n" );CHKERRQ(ierr);
205
    for( i=0; i<nconv; i++ ) {
206
#if defined(PETSC_USE_COMPLEX)
207
      re = PetscRealPart(kr[i]);
208
      im = PetscImaginaryPart(kr[i]);
209
#else
210
      re = kr[i];
211
      im = ki[i];
212
#endif
213
      if( im>0.0 ) ierr = PetscPrintf(PETSC_COMM_WORLD," % 6f + %6f i",re,im);
214
      else if( im<0.0 ) ierr = PetscPrintf(PETSC_COMM_WORLD," % 6f - %6f i",re,-im);
215
      else ierr = PetscPrintf(PETSC_COMM_WORLD,"       % 6f      ",re);
216
      CHKERRQ(ierr);
217
      ierr = PetscPrintf(PETSC_COMM_WORLD," % 12f\n",error[i]);CHKERRQ(ierr);
218
    }
219
    ierr = PetscPrintf(PETSC_COMM_WORLD,"\n" );CHKERRQ(ierr);
220
    ierr = PetscFree(error);CHKERRQ(ierr);
221
  }
222
 
223
  /*
224
     Free work space
225
  */
226
  ierr = EPSDestroy(eps);CHKERRQ(ierr);
227
  ierr = MatDestroy(A);CHKERRQ(ierr);
228
  ierr = MatDestroy(ctx->T);CHKERRQ(ierr);
229
  ierr = VecDestroy(ctx->x1);CHKERRQ(ierr);
230
  ierr = VecDestroy(ctx->x2);CHKERRQ(ierr);
231
  ierr = VecDestroy(ctx->y1);CHKERRQ(ierr);
232
  ierr = VecDestroy(ctx->y2);CHKERRQ(ierr);
233
  ierr = PetscFree(ctx);CHKERRQ(ierr);
234
  ierr = SlepcFinalize();CHKERRQ(ierr);
235
  return 0;
236
}
237
 
238
#undef __FUNC__
239
#define __FUNC__ "MatBrussel_Mult"
240
int MatBrussel_Mult(Mat A,Vec x,Vec y)
241
{
242
  int         n, ierr;
243
  PetscScalar alpha, *px, *py;
244
  MPI_Comm    comm;
245
  CTX_BRUSSEL *ctx;
246
 
247
  ierr = MatShellGetContext(A,(void**)&ctx);CHKERRQ(ierr);
248
  ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
249
  ierr = MatGetLocalSize(ctx->T,&n,PETSC_NULL);CHKERRQ(ierr);
250
  ierr = VecGetArray(x,&px);CHKERRQ(ierr);
251
  ierr = VecGetArray(y,&py);CHKERRQ(ierr);
252
  ierr = VecPlaceArray(ctx->x1,px);CHKERRQ(ierr);
253
  ierr = VecPlaceArray(ctx->x2,px+n);CHKERRQ(ierr);
254
  ierr = VecPlaceArray(ctx->y1,py);CHKERRQ(ierr);
255
  ierr = VecPlaceArray(ctx->y2,py+n);CHKERRQ(ierr);
256
 
257
  ierr = MatMult(ctx->T,ctx->x1,ctx->y1);CHKERRQ(ierr);
258
  ierr = VecScale(&ctx->tau1,ctx->y1);CHKERRQ(ierr);
259
  alpha = ctx->beta - 1.0 - ctx->sigma;
260
  ierr = VecAXPY(&alpha,ctx->x1,ctx->y1);CHKERRQ(ierr);
261
  alpha = ctx->alpha * ctx->alpha;
262
  ierr = VecAXPY(&alpha,ctx->x2,ctx->y1);CHKERRQ(ierr);
263
 
264
  ierr = MatMult(ctx->T,ctx->x2,ctx->y2);CHKERRQ(ierr);
265
  ierr = VecScale(&ctx->tau2,ctx->y2);CHKERRQ(ierr);
266
  alpha = -ctx->beta;
267
  ierr = VecAXPY(&alpha,ctx->x1,ctx->y2);CHKERRQ(ierr);
268
  alpha = -ctx->alpha * ctx->alpha - ctx->sigma;
269
  ierr = VecAXPY(&alpha,ctx->x2,ctx->y2);CHKERRQ(ierr);
270
 
271
  ierr = VecRestoreArray(x,&px);CHKERRQ(ierr);
272
  ierr = VecRestoreArray(y,&py);CHKERRQ(ierr);
273
 
274
  return 0;
275
}
276
 
277
#undef __FUNCT__
278
#define __FUNCT__ "MatBrussel_Shift"
279
int MatBrussel_Shift( PetscScalar* a, Mat Y )
280
{
281
  CTX_BRUSSEL *ctx;
282
  int         ierr;
283
 
284
  ierr = MatShellGetContext( Y, (void**)&ctx ); CHKERRQ(ierr);
285
  ctx->sigma += *a;
286
  PetscFunctionReturn(0);
287
}
288
 
289
#undef __FUNC__
290
#define __FUNC__ "MatBrussel_GetDiagonal"
291
int MatBrussel_GetDiagonal(Mat A,Vec diag)
292
{
293
  Vec         d1, d2;
294
  int         n, ierr;
295
  PetscScalar alpha, *pd;
296
  MPI_Comm    comm;
297
  CTX_BRUSSEL *ctx;
298
 
299
  ierr = MatShellGetContext(A,(void**)&ctx);CHKERRQ(ierr);
300
  ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
301
  ierr = MatGetLocalSize(ctx->T,&n,PETSC_NULL);CHKERRQ(ierr);
302
  ierr = VecGetArray(diag,&pd);CHKERRQ(ierr);
303
  ierr = VecCreateMPIWithArray(comm,n,PETSC_DECIDE,pd,&d1);CHKERRQ(ierr);
304
  ierr = VecCreateMPIWithArray(comm,n,PETSC_DECIDE,pd+n,&d2);CHKERRQ(ierr);
305
 
306
  alpha = -2.0*ctx->tau1 + ctx->beta - 1.0 - ctx->sigma;
307
  ierr = VecSet(&alpha,d1);CHKERRQ(ierr);
308
  alpha = -2.0*ctx->tau2 - ctx->alpha*ctx->alpha - ctx->sigma;
309
  ierr = VecSet(&alpha,d2);CHKERRQ(ierr);
310
 
311
  ierr = VecDestroy(d1);CHKERRQ(ierr);
312
  ierr = VecDestroy(d2);CHKERRQ(ierr);
313
  ierr = VecRestoreArray(diag,&pd);CHKERRQ(ierr);
314
 
315
  return 0;
316
}
317
 
318