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
      Implements the shift-and-invert technique for eigenvalue problems.
3
*/
4
#include "src/st/stimpl.h"          /*I "slepcst.h" I*/
5
#include "sinvert.h"            
6
 
7
typedef struct {
8
  PetscTruth   shift_matrix; /* shift matrix rather than use shell mat */
9
  MatStructure str;          /* whether matrices have the same pattern or not */
10
  Mat          mat;
11
  Vec          w;
12
} ST_SINV;
13
 
14
#undef __FUNCT__  
15
#define __FUNCT__ "STApply_Sinvert"
16
static int STApply_Sinvert(ST st,Vec x,Vec y)
17
{
18
  int       ierr;
19
  ST_SINV   *ctx = (ST_SINV *) st->data;
20
 
21
  PetscFunctionBegin;
22
  if (st->B) {
23
    /* generalized eigenproblem: y = (A - sB)^-1 B x */
24
    ierr = MatMult(st->B,x,ctx->w);CHKERRQ(ierr);
25
    ierr = STAssociatedSLESSolve(st,ctx->w,y);CHKERRQ(ierr);
26
  }
27
  else {
28
    /* standard eigenproblem: y = (A - sI)^-1 x */
29
    ierr = STAssociatedSLESSolve(st,x,y);CHKERRQ(ierr);
30
  }
31
  PetscFunctionReturn(0);
32
}
33
 
34
#undef __FUNCT__  
35
#define __FUNCT__ "STApplyNoB_Sinvert"
36
static int STApplyNoB_Sinvert(ST st,Vec x,Vec y)
37
{
38
  int       ierr;
39
 
40
  PetscFunctionBegin;
41
  ierr = STAssociatedSLESSolve(st,x,y);CHKERRQ(ierr);
42
  PetscFunctionReturn(0);
43
}
44
 
45
#undef __FUNCT__  
46
#define __FUNCT__ "STBackTransform_Sinvert"
47
int STBackTransform_Sinvert(ST st,PetscScalar *eigr,PetscScalar *eigi)
48
{
49
  PetscFunctionBegin;
50
  /* Note that this is not correct in the case of the RQI solver */
51
  if (eigr) *eigr = 1.0 / *eigr + st->sigma;
52
  PetscFunctionReturn(0);
53
}
54
 
55
#undef __FUNCT__  
56
#define __FUNCT__ "STPost_Sinvert"
57
int STPost_Sinvert(ST st)
58
{
59
  ST_SINV      *ctx = (ST_SINV *) st->data;
60
  PetscScalar  alpha;
61
  int          ierr;
62
 
63
  PetscFunctionBegin;
64
  if( ctx->shift_matrix ) {
65
    alpha = st->sigma;
66
    if( st->B ) { ierr = MatAXPY(&alpha,st->B,st->A,ctx->str);CHKERRQ(ierr); }
67
    else { ierr = MatShift( &alpha, st->A ); CHKERRQ(ierr); }
68
    st->setupcalled = 0;
69
  }
70
  PetscFunctionReturn(0);
71
}
72
 
73
#undef __FUNCT__  
74
#define __FUNCT__ "STSetUp_Sinvert"
75
static int STSetUp_Sinvert(ST st)
76
{
77
  int          ierr;
78
  ST_SINV      *ctx = (ST_SINV *) st->data;
79
  PetscScalar  alpha;
80
 
81
  PetscFunctionBegin;
82
 
83
  if (ctx->shift_matrix) {
84
    alpha = -st->sigma;
85
    if (st->B) { ierr = MatAXPY(&alpha,st->B,st->A,ctx->str);CHKERRQ(ierr); }
86
    else { ierr = MatShift(&alpha,st->A);CHKERRQ(ierr); }
87
    ierr = SLESSetOperators(st->sles,st->A,st->A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
88
  }
89
  else {
90
    ierr = MatCreateMatSinvert(st,&ctx->mat);CHKERRQ(ierr);
91
    ierr = SLESSetOperators(st->sles,ctx->mat,ctx->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
92
  }
93
  if (st->B && !ctx->w) { ierr = VecDuplicate(st->vec,&ctx->w);CHKERRQ(ierr); }
94
  ierr = SLESSetUp(st->sles,st->vec,st->vec);CHKERRQ(ierr);
95
  PetscFunctionReturn(0);
96
}
97
 
98
#undef __FUNCT__  
99
#define __FUNCT__ "STSetShift_Sinvert"
100
static int STSetShift_Sinvert(ST st,PetscScalar newshift)
101
{
102
  int          ierr;
103
  ST_SINV      *stctx = (ST_SINV *) st->data;
104
  PetscScalar  alpha;
105
  CTX_SINV     *ctx;
106
 
107
  PetscFunctionBegin;
108
 
109
  /* Nothing to be done if STSetUp has not been called yet */
110
  if (!st->setupcalled) PetscFunctionReturn(0);
111
 
112
  if (stctx->shift_matrix) {
113
    /* Undo previous operations */
114
    alpha = st->sigma;
115
    if (st->B) { ierr = MatAXPY(&alpha,st->B,st->A,stctx->str);CHKERRQ(ierr); }
116
    else { ierr = MatShift(&alpha,st->A);CHKERRQ(ierr); }
117
    /* Apply new shift */
118
    alpha = -newshift;
119
    if (st->B) { ierr = MatAXPY(&alpha,st->B,st->A,stctx->str);CHKERRQ(ierr); }
120
    else { ierr = MatShift(&alpha,st->A);CHKERRQ(ierr); }
121
    ierr = SLESSetOperators(st->sles,st->A,st->A,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
122
  }
123
  else {
124
    ierr = MatShellGetContext(stctx->mat,(void**)&ctx);CHKERRQ(ierr);
125
    ctx->sigma = newshift;
126
    ierr = SLESSetOperators(st->sles,stctx->mat,stctx->mat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
127
  }
128
  ierr = SLESSetUp(st->sles,st->vec,st->vec);CHKERRQ(ierr);
129
  PetscFunctionReturn(0);
130
}
131
 
132
#undef __FUNCT__  
133
#define __FUNCT__ "STDestroy_Sinvert"
134
static int STDestroy_Sinvert(ST st)
135
{
136
  ST_SINV  *ctx = (ST_SINV *) st->data;
137
  int      ierr;
138
 
139
  PetscFunctionBegin;
140
  if (!ctx->shift_matrix) { ierr = MatDestroy(ctx->mat);CHKERRQ(ierr); }
141
  if (st->B) { ierr = VecDestroy(ctx->w);CHKERRQ(ierr); }
142
  ierr = PetscFree(ctx);CHKERRQ(ierr);
143
  PetscFunctionReturn(0);
144
}
145
 
146
#undef __FUNCT__  
147
#define __FUNCT__ "STView_Sinvert"
148
static int STView_Sinvert(ST st,PetscViewer viewer)
149
{
150
  ST_SINV    *ctx = (ST_SINV *) st->data;
151
  int        ierr;
152
  PetscTruth isascii;
153
  char       *str;
154
 
155
  PetscFunctionBegin;
156
  ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
157
  if (!isascii) {
158
    SETERRQ1(1,"Viewer type %s not supported for STSINV",((PetscObject)viewer)->type_name);
159
  }
160
  if (ctx->shift_matrix) {
161
    ierr = PetscViewerASCIIPrintf(viewer,"Shifting the matrix and unshifting at exit\n");CHKERRQ(ierr);
162
    if (st->B) {
163
      switch (ctx->str) {
164
        case SAME_NONZERO_PATTERN:      str = "same nonzero pattern";break;
165
        case DIFFERENT_NONZERO_PATTERN: str = "different nonzero pattern";break;
166
        case SUBSET_NONZERO_PATTERN:    str = "subset nonzero pattern";break;
167
      }
168
      ierr = PetscViewerASCIIPrintf(viewer,"Matrices A and B have %s\n",str);CHKERRQ(ierr);
169
    }
170
  }
171
  PetscFunctionReturn(0);
172
}
173
 
174
#undef __FUNCT__  
175
#define __FUNCT__ "STSetFromOptions_Sinvert"
176
static int STSetFromOptions_Sinvert(ST st)
177
{
178
  int        ierr;
179
  PetscTruth flg;
180
  PC         pc;
181
 
182
  PetscFunctionBegin;
183
  ierr = PetscOptionsHead("ST Shift-and-invert Options");CHKERRQ(ierr);
184
    ierr = PetscOptionsName("-st_sinvert_shift_mat","Shift matrix explicitly","STSinvertSetShiftMat",&flg);CHKERRQ(ierr);
185
    if (flg) {
186
      ierr = STSinvertSetShiftMat(st);CHKERRQ(ierr);
187
    }
188
    else {
189
      /* if shift_mat is set then the default preconditioner is ILU,
190
         otherwise set Jacobi as the default */
191
      ierr = SLESGetPC(st->sles,&pc); CHKERRQ(ierr);
192
      ierr = PCSetType(pc,PCJACOBI);CHKERRQ(ierr);
193
    }
194
    ierr = PetscOptionsLogicalGroupBegin("-st_sinvert_same_pattern","same nonzero pattern","STSinvertSetMatStructure",&flg);CHKERRQ(ierr);
195
    if (flg) {ierr = STSinvertSetMatStructure(st,SAME_NONZERO_PATTERN);CHKERRQ(ierr);}
196
    ierr = PetscOptionsLogicalGroup("-st_sinvert_different_pattern","different nonzero pattern","STSinvertSetMatStructure",&flg);CHKERRQ(ierr);
197
    if (flg) {ierr = STSinvertSetMatStructure(st,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);}
198
    ierr = PetscOptionsLogicalGroupEnd("-st_sinvert_subset_pattern","subset nonzero pattern","STSinvertSetMatStructure",&flg);CHKERRQ(ierr);
199
    if (flg) {ierr = STSinvertSetMatStructure(st,SUBSET_NONZERO_PATTERN);CHKERRQ(ierr);}
200
  ierr = PetscOptionsTail();CHKERRQ(ierr);
201
  PetscFunctionReturn(0);
202
}
203
 
204
/* -------------------------------------------------------------------------*/
205
 
206
EXTERN_C_BEGIN
207
#undef __FUNCT__  
208
#define __FUNCT__ "STSinvertSetShiftMat_Sinvert"
209
int STSinvertSetShiftMat_Sinvert(ST st)
210
{
211
  ST_SINV    *ctx = (ST_SINV *) st->data;
212
 
213
  PetscFunctionBegin;
214
  ctx->shift_matrix = PETSC_TRUE;
215
  PetscFunctionReturn(0);
216
}
217
EXTERN_C_END
218
 
219
#undef __FUNCT__  
220
#define __FUNCT__ "STSinvertSetShiftMat"
221
/*@
222
   STSinvertSetShiftMat - Sets a flag to indicate that the matrix is
223
   being shifted at STSetUp() and unshifted at the end of the computations.
224
 
225
   Collective on ST
226
 
227
   Input Parameters:
228
.  st - the spectral transformation context
229
 
230
   Options Database Key:
231
.  -st_sinvert_shift_mat - Activates STSinvertSetShiftMat()
232
 
233
   Note:
234
   By default, the matrix is not shifted explicitly. Instead, the solver
235
   works with an implicit shell matrix that represents the shifted matrix,
236
   in which case only the Jacobi preconditioning is available for the linear
237
   solves performed in each iteration of the eigensolver.
238
 
239
   Level: intermediate
240
 
241
.seealso: STSetOperators()
242
@*/
243
int STSinvertSetShiftMat(ST st)
244
{
245
  int ierr, (*f)(ST);
246
 
247
  PetscFunctionBegin;
248
  PetscValidHeaderSpecific(st,ST_COOKIE);
249
  ierr = PetscObjectQueryFunction((PetscObject)st,"STSinvertSetShiftMat_C",(void (**)(void))&f);CHKERRQ(ierr);
250
  if (f) {
251
    ierr = (*f)(st);CHKERRQ(ierr);
252
  }
253
  PetscFunctionReturn(0);
254
}
255
 
256
EXTERN_C_BEGIN
257
#undef __FUNCT__  
258
#define __FUNCT__ "STSinvertSetMatStructure_Sinvert"
259
int STSinvertSetMatStructure_Sinvert(ST st,MatStructure str)
260
{
261
  ST_SINV    *ctx = (ST_SINV *) st->data;
262
 
263
  PetscFunctionBegin;
264
  ctx->str = str;
265
  PetscFunctionReturn(0);
266
}
267
EXTERN_C_END
268
 
269
#undef __FUNCT__  
270
#define __FUNCT__ "STSinvertSetMatStructure"
271
/*@
272
   STSinvertSetMatStructure - Sets an internal MatStructure attribute to
273
   indicate which is the relation of the sparsity pattern of the two matrices
274
   A and B constituting the generalized eigenvalue problem. This function
275
   has no effect in the case of standard eigenproblems.
276
 
277
   Collective on ST
278
 
279
   Input Parameters:
280
+  st  - the spectral transformation context
281
-  str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN or
282
         SUBSET_NONZERO_PATTERN
283
 
284
   Options Database Key:
285
+  -st_sinvert_same_pattern - Indicates A and B have the same nonzero pattern
286
.  -st_sinvert_different_pattern - Indicates A and B have different nonzero pattern
287
-  -st_sinvert_subset_pattern - Indicates B's nonzero pattern is a subset of B's
288
 
289
   Note:
290
   By default, the sparsity patterns are assumed to be different. If the
291
   patterns are equal or a subset then it is recommended to set this attribute
292
   for efficiency reasons (in particular, for internal MatAXPY operations).
293
 
294
   Level: advanced
295
 
296
.seealso: STSetOperators()
297
@*/
298
int STSinvertSetMatStructure(ST st,MatStructure str)
299
{
300
  int ierr, (*f)(ST,MatStructure);
301
 
302
  PetscFunctionBegin;
303
  PetscValidHeaderSpecific(st,ST_COOKIE);
304
  ierr = PetscObjectQueryFunction((PetscObject)st,"STSinvertSetMatStructure_C",(void (**)(void))&f);CHKERRQ(ierr);
305
  if (f) {
306
    ierr = (*f)(st,str);CHKERRQ(ierr);
307
  }
308
  PetscFunctionReturn(0);
309
}
310
 
311
/* ---------------------------------------------------------------------------*/
312
 
313
EXTERN_C_BEGIN
314
#undef __FUNCT__  
315
#define __FUNCT__ "STCreate_Sinvert"
316
int STCreate_Sinvert(ST st)
317
{
318
  int       ierr;
319
  char      *prefix;
320
  ST_SINV   *ctx;
321
 
322
  PetscFunctionBegin;
323
  ierr = PetscNew(ST_SINV,&ctx); CHKERRQ(ierr);
324
  PetscMemzero(ctx,sizeof(ST_SINV));
325
  PetscLogObjectMemory(st,sizeof(ST_SINV));
326
  st->numberofshifts      = 1;
327
  st->data                = (void *) ctx;
328
 
329
  st->ops->apply          = STApply_Sinvert;
330
  st->ops->applynoB       = STApplyNoB_Sinvert;
331
  st->ops->postsolve      = STPost_Sinvert;
332
  st->ops->backtr         = STBackTransform_Sinvert;
333
  st->ops->setup          = STSetUp_Sinvert;
334
  st->ops->setshift       = STSetShift_Sinvert;
335
  st->ops->destroy        = STDestroy_Sinvert;
336
  st->ops->setfromoptions = STSetFromOptions_Sinvert;
337
  st->ops->view           = STView_Sinvert;
338
 
339
  ierr = SLESCreate(st->comm,&st->sles);CHKERRQ(ierr);
340
  ierr = STGetOptionsPrefix(st,&prefix);CHKERRQ(ierr);
341
  ierr = SLESSetOptionsPrefix(st->sles,prefix);CHKERRQ(ierr);
342
  ierr = SLESAppendOptionsPrefix(st->sles,"st_");CHKERRQ(ierr);
343
  ctx->shift_matrix = PETSC_FALSE;
344
  ctx->str          = DIFFERENT_NONZERO_PATTERN;
345
 
346
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STSinvertSetShiftMat_C","STSinvertSetShiftMat_Sinvert",
347
                    STSinvertSetShiftMat_Sinvert);CHKERRQ(ierr);
348
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STSinvertSetMatStructure_C","STSinvertSetMatStructure_Sinvert",
349
                    STSinvertSetMatStructure_Sinvert);CHKERRQ(ierr);
350
 
351
  PetscFunctionReturn(0);
352
}
353
EXTERN_C_END
354