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
1996 eromero 1
/*
2
      Implements the ST class for preconditioned eigenvalue methods.
3
 
4
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5
   SLEPc - Scalable Library for Eigenvalue Problem Computations
2116 eromero 6
   Copyright (c) 2002-2010, Universidad Politecnica de Valencia, Spain
1996 eromero 7
 
8
   This file is part of SLEPc.
9
 
10
   SLEPc is free software: you can redistribute it and/or modify it under  the
11
   terms of version 3 of the GNU Lesser General Public License as published by
12
   the Free Software Foundation.
13
 
14
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
15
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
16
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
17
   more details.
18
 
19
   You  should have received a copy of the GNU Lesser General  Public  License
20
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
21
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22
*/
23
 
2283 jroman 24
#include <private/stimpl.h>          /*I "slepcst.h" I*/
1996 eromero 25
 
26
PetscErrorCode STDestroy_Precond(ST st);
2021 eromero 27
PetscErrorCode STSetFromOptions_Precond(ST st);
2012 eromero 28
EXTERN_C_BEGIN
1996 eromero 29
PetscErrorCode STPrecondSetMatForPC_Precond(ST st,Mat mat);
30
PetscErrorCode STPrecondGetMatForPC_Precond(ST st,Mat *mat);
2216 jroman 31
PetscErrorCode STPrecondSetKSPHasMat_Precond(ST st,PetscBool setmat);
32
PetscErrorCode STPrecondGetKSPHasMat_Precond(ST st,PetscBool *setmat);
2012 eromero 33
EXTERN_C_END
1996 eromero 34
 
2000 eromero 35
typedef struct {
2216 jroman 36
  PetscBool setmat;
2000 eromero 37
} ST_PRECOND;
38
 
39
 
1996 eromero 40
#undef __FUNCT__  
41
#define __FUNCT__ "SLEPcNotImplemented_Precond"
2012 eromero 42
PetscErrorCode SLEPcNotImplemented_Precond(ST st, Vec x, Vec y) {
2214 jroman 43
  SETERRQ(((PetscObject)st)->comm,PETSC_ERR_SUP,"Operation not implemented in STPRECOND.");
1996 eromero 44
}
45
 
46
#undef __FUNCT__  
2021 eromero 47
#define __FUNCT__ "STSetFromOptions_Precond"
48
PetscErrorCode STSetFromOptions_Precond(ST st)
49
{
50
  PetscErrorCode ierr;
51
  PC             pc;
52
  const PCType   pctype;
53
  Mat            P;
2216 jroman 54
  PetscBool      t0, t1;
2021 eromero 55
 
56
  PetscFunctionBegin;
57
 
58
  ierr = KSPGetPC(st->ksp, &pc); CHKERRQ(ierr);
59
  ierr = PetscObjectGetType((PetscObject)pc, &pctype); CHKERRQ(ierr);
60
  ierr = STPrecondGetMatForPC(st, &P); CHKERRQ(ierr);
61
  if (!pctype && st->A) {
62
    if (P || st->shift_matrix == ST_MATMODE_SHELL) {
63
      ierr = PCSetType(pc, PCJACOBI); CHKERRQ(ierr);
64
    } else {
65
      ierr = MatHasOperation(st->A, MATOP_DUPLICATE, &t0); CHKERRQ(ierr);
66
      if (st->B) {
67
        ierr = MatHasOperation(st->A, MATOP_AXPY, &t1); CHKERRQ(ierr);
68
      } else {
2100 eromero 69
        t1 = PETSC_TRUE;
2021 eromero 70
      }
2177 jroman 71
      ierr = PCSetType(pc, (t0 && t1)? PCJACOBI:PCNONE); CHKERRQ(ierr);
2021 eromero 72
    }
73
  }
74
 
75
  PetscFunctionReturn(0);
76
}
77
 
78
#undef __FUNCT__  
1996 eromero 79
#define __FUNCT__ "STSetUp_Precond"
80
PetscErrorCode STSetUp_Precond(ST st)
81
{
1997 eromero 82
  Mat            P;
1999 eromero 83
  PC             pc;
2216 jroman 84
  PetscBool      t0, setmat, destroyP=PETSC_FALSE, builtP;
1996 eromero 85
  PetscErrorCode ierr;
86
 
87
  PetscFunctionBegin;
1997 eromero 88
 
2086 eromero 89
  /* if the user did not set the shift, use the target value */
90
  if (!st->sigma_set) st->sigma = st->defsigma;
91
 
2000 eromero 92
  /* If pc is none and any matrix has to be set, exit */
2021 eromero 93
  ierr = STSetFromOptions_Precond(st); CHKERRQ(ierr);
2000 eromero 94
  ierr = KSPGetPC(st->ksp, &pc); CHKERRQ(ierr);
95
  ierr = PetscTypeCompare((PetscObject)pc, PCNONE, &t0); CHKERRQ(ierr);
2020 eromero 96
  ierr = STPrecondGetKSPHasMat(st, &setmat); CHKERRQ(ierr);
2177 jroman 97
  if (t0 && !setmat) PetscFunctionReturn(0);
2000 eromero 98
 
1999 eromero 99
  /* Check if a user matrix is set */
1997 eromero 100
  ierr = STPrecondGetMatForPC(st, &P); CHKERRQ(ierr);
2000 eromero 101
 
102
  /* If not, create A - shift*B */
1997 eromero 103
  if (P) {
2000 eromero 104
    builtP = PETSC_FALSE;
105
    destroyP = PETSC_TRUE;
2182 eromero 106
    ierr = PetscObjectReference((PetscObject)P);CHKERRQ(ierr);
2000 eromero 107
  } else {
108
    builtP = PETSC_TRUE;
109
 
110
    if (st->shift_matrix == ST_MATMODE_SHELL) {
111
      ierr = STMatShellCreate(st,&P);CHKERRQ(ierr);
112
      //TODO: set the apply and apply transpose to st->mat
113
      destroyP = PETSC_TRUE;
2280 jroman 114
    } else if (!(PetscAbsScalar(st->sigma) < PETSC_MAX_REAL) && st->B) {
2000 eromero 115
      P = st->B;
116
      destroyP = PETSC_FALSE;
117
    } else if (st->sigma == 0.0) {
118
      P = st->A;
119
      destroyP = PETSC_FALSE;
2280 jroman 120
    } else if (PetscAbsScalar(st->sigma) < PETSC_MAX_REAL) {
2000 eromero 121
      if (st->shift_matrix == ST_MATMODE_INPLACE) {
122
        P = st->A;
123
        destroyP = PETSC_FALSE;
124
      } else {
125
        ierr = MatDuplicate(st->A, MAT_COPY_VALUES, &P); CHKERRQ(ierr);
126
        destroyP = PETSC_TRUE;
127
      }
128
      if (st->B) {
129
        ierr = MatAXPY(P, -st->sigma, st->B, st->str); CHKERRQ(ierr);
130
      } else {
131
        ierr = MatShift(P, -st->sigma); CHKERRQ(ierr);
132
      }
133
    } else
134
      builtP = PETSC_FALSE;
1999 eromero 135
  }
136
 
2000 eromero 137
  /* If P was not possible to obtain, set pc to PCNONE */
138
  if (!P) {
139
    ierr = PCSetType(pc, PCNONE); CHKERRQ(ierr);
1999 eromero 140
 
2000 eromero 141
    /* If some matrix has to be set to ksp, set ksp to KSPPREONLY */
2177 jroman 142
    if (setmat) {
2000 eromero 143
      ierr = STMatShellCreate(st, &P);CHKERRQ(ierr);
144
      destroyP = PETSC_TRUE;
145
      ierr = KSPSetType(st->ksp, KSPPREONLY); CHKERRQ(ierr);
1999 eromero 146
    }
2000 eromero 147
  }
148
 
2177 jroman 149
  ierr = KSPSetOperators(st->ksp,setmat?P:PETSC_NULL,P,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
2000 eromero 150
 
2177 jroman 151
  if (destroyP) {
2000 eromero 152
    ierr = MatDestroy(P); CHKERRQ(ierr);
2177 jroman 153
  } else if (st->shift_matrix == ST_MATMODE_INPLACE && builtP) {
2280 jroman 154
    if (st->sigma != 0.0 && PetscAbsScalar(st->sigma) < PETSC_MAX_REAL) {
1999 eromero 155
      if (st->B) {
156
        ierr = MatAXPY(st->A,st->sigma,st->B,st->str);CHKERRQ(ierr);
157
      } else {
158
        ierr = MatShift(st->A,st->sigma);CHKERRQ(ierr);
1996 eromero 159
      }
1999 eromero 160
    }
1996 eromero 161
  }
162
 
163
  PetscFunctionReturn(0);
164
}
165
 
166
#undef __FUNCT__  
167
#define __FUNCT__ "STSetShift_Precond"
168
PetscErrorCode STSetShift_Precond(ST st,PetscScalar newshift)
169
{
170
  PetscErrorCode ierr;
171
 
172
  PetscFunctionBegin;
173
 
174
  /* Nothing to be done if STSetUp has not been called yet */
175
  if (!st->setupcalled) PetscFunctionReturn(0);
176
 
177
  st->sigma = newshift;
178
  if (st->shift_matrix != ST_MATMODE_SHELL) {
179
    ierr =  STSetUp_Precond(st); CHKERRQ(ierr);
180
  }
181
 
182
  PetscFunctionReturn(0);
183
}
184
 
185
EXTERN_C_BEGIN
186
#undef __FUNCT__  
187
#define __FUNCT__ "STCreate_Precond"
188
PetscErrorCode STCreate_Precond(ST st)
189
{
190
  PetscErrorCode ierr;
2000 eromero 191
  ST_PRECOND     *data;
1996 eromero 192
 
193
  PetscFunctionBegin;
194
 
2000 eromero 195
  ierr = PetscNew(ST_PRECOND, &data); CHKERRQ(ierr);
196
  st->data                 = data;
1996 eromero 197
 
198
  st->ops->apply           = SLEPcNotImplemented_Precond;
199
  st->ops->getbilinearform = STGetBilinearForm_Default;
200
  st->ops->applytrans      = SLEPcNotImplemented_Precond;
201
  st->ops->postsolve       = PETSC_NULL;
202
  st->ops->backtr          = PETSC_NULL;
203
  st->ops->setup           = STSetUp_Precond;
204
  st->ops->setshift        = STSetShift_Precond;
205
  st->ops->view            = STView_Default;
206
  st->ops->destroy         = STDestroy_Precond;
2021 eromero 207
  st->ops->setfromoptions  = STSetFromOptions_Precond;
1996 eromero 208
 
2021 eromero 209
  st->checknullspace       = PETSC_NULL;
1996 eromero 210
 
211
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondGetMatForPC_C","STPrecondGetMatForPC_Precond",STPrecondGetMatForPC_Precond);CHKERRQ(ierr);
212
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondSetMatForPC_C","STPrecondSetMatForPC_Precond",STPrecondSetMatForPC_Precond);CHKERRQ(ierr);
2020 eromero 213
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondGetKSPHasMat_C","STPrecondGetKSPHasMat_Precond",STPrecondGetKSPHasMat_Precond);CHKERRQ(ierr);
214
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondSetKSPHasMat_C","STPrecondSetKSPHasMat_Precond",STPrecondSetKSPHasMat_Precond);CHKERRQ(ierr);
1996 eromero 215
 
2020 eromero 216
  ierr = STPrecondSetKSPHasMat_Precond(st, PETSC_TRUE); CHKERRQ(ierr);
2006 eromero 217
  ierr = KSPSetType(st->ksp, KSPPREONLY); CHKERRQ(ierr);
2014 eromero 218
 
1996 eromero 219
  PetscFunctionReturn(0);
220
}
221
EXTERN_C_END
222
 
223
#undef __FUNCT__  
224
#define __FUNCT__ "STDestroy_Precond"
225
PetscErrorCode STDestroy_Precond(ST st)
226
{
227
  PetscErrorCode ierr;
228
 
229
  PetscFunctionBegin;
230
 
231
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondGetMatForPC_C","",PETSC_NULL);CHKERRQ(ierr);
232
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondSetMatForPC_C","",PETSC_NULL);CHKERRQ(ierr);
2020 eromero 233
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondGetKSPHasMat_C","",PETSC_NULL);CHKERRQ(ierr);
234
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondSetKSPHasMat_C","",PETSC_NULL);CHKERRQ(ierr);
1996 eromero 235
 
2000 eromero 236
  ierr = PetscFree(st->data); CHKERRQ(ierr);
237
 
1996 eromero 238
  PetscFunctionReturn(0);
239
}
240
 
241
#undef __FUNCT__  
242
#define __FUNCT__ "STPrecondGetMatForPC"
243
/*@
244
   STPrecondGetMatForPC - Gets the matrix previously set by STPrecondSetMatForPC.
245
   This matrix will be passed as parameter in the KSPSetOperator function as
246
   the matrix to be used in constructing the preconditioner.
247
 
248
   Collective on ST
249
 
250
   Input Parameter:
251
.  st - the spectral transformation context
252
 
253
   Output Parameter:
254
.  mat - the matrix that will be used in constructing the preconditioner or
255
   PETSC_NULL if any previous matrix was set by STPrecondSetMatForPC.
256
 
257
   Level: advanced
258
 
259
.seealso: STPrecondSetMatForPC(), KSPSetOperator()
260
@*/
261
PetscErrorCode STPrecondGetMatForPC(ST st,Mat *mat)
262
{
2221 jroman 263
  PetscErrorCode ierr;
1996 eromero 264
 
265
  PetscFunctionBegin;
2213 jroman 266
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
2221 jroman 267
  ierr = PetscTryMethod(st,"STPrecondGetMatForPC_C",(ST,Mat*),(st,mat));CHKERRQ(ierr);
1996 eromero 268
  PetscFunctionReturn(0);
269
}
270
 
2012 eromero 271
EXTERN_C_BEGIN
2223 jroman 272
#undef __FUNCT__
273
#define __FUNCT__ "STPrecondGetMatForPC_Precond"
1996 eromero 274
PetscErrorCode STPrecondGetMatForPC_Precond(ST st,Mat *mat)
275
{
1997 eromero 276
  PetscErrorCode ierr;
277
  PC             pc;
2216 jroman 278
  PetscBool      flag;
1997 eromero 279
 
1996 eromero 280
  PetscFunctionBegin;
2213 jroman 281
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
1996 eromero 282
 
1997 eromero 283
  ierr = KSPGetPC(st->ksp, &pc); CHKERRQ(ierr);
284
  ierr = PCGetOperatorsSet(pc, PETSC_NULL, &flag); CHKERRQ(ierr);
2177 jroman 285
  if (flag) {
1997 eromero 286
    ierr = PCGetOperators(pc, PETSC_NULL, mat, PETSC_NULL); CHKERRQ(ierr);
287
  } else
288
    *mat = PETSC_NULL;
1996 eromero 289
 
290
  PetscFunctionReturn(0);
291
}
2012 eromero 292
EXTERN_C_END
1996 eromero 293
 
294
#undef __FUNCT__  
295
#define __FUNCT__ "STPrecondSetMatForPC"
296
/*@
297
   STPrecondSetMatForPC - Sets the matrix that will be passed as parameter in
2000 eromero 298
   the KSPSetOperators function as the matrix to be used in constructing the
1996 eromero 299
   preconditioner. If any matrix is set or mat is PETSC_NULL, A - sigma*B will
300
   be used, being sigma the value set by STSetShift
301
 
302
   Collective on ST
303
 
304
   Input Parameter:
305
+  st - the spectral transformation context
306
-  mat - the matrix that will be used in constructing the preconditioner
307
 
308
   Level: advanced
309
 
2000 eromero 310
.seealso: STPrecondSetMatForPC(), KSPSetOperators()
1996 eromero 311
@*/
312
PetscErrorCode STPrecondSetMatForPC(ST st,Mat mat)
313
{
2221 jroman 314
  PetscErrorCode ierr;
1996 eromero 315
 
316
  PetscFunctionBegin;
2213 jroman 317
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
318
  PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
2221 jroman 319
  ierr = PetscTryMethod(st,"STPrecondSetMatForPC_C",(ST,Mat),(st,mat));CHKERRQ(ierr);
1996 eromero 320
  PetscFunctionReturn(0);
321
}
322
 
2012 eromero 323
EXTERN_C_BEGIN
2223 jroman 324
#undef __FUNCT__
325
#define __FUNCT__ "STPrecondSetMatForPC_Precond"
1996 eromero 326
PetscErrorCode STPrecondSetMatForPC_Precond(ST st,Mat mat)
327
{
1997 eromero 328
  PC             pc;
2182 eromero 329
  Mat            A;
2216 jroman 330
  PetscBool      flag;
1996 eromero 331
  PetscErrorCode ierr;
332
 
333
  PetscFunctionBegin;
2213 jroman 334
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
335
  PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
1996 eromero 336
 
1997 eromero 337
  ierr = KSPGetPC(st->ksp, &pc); CHKERRQ(ierr);
2182 eromero 338
  /* Yes, all these lines are needed to safely set mat as the preconditioner
339
     matrix in pc */
340
  ierr = PCGetOperatorsSet(pc, &flag, PETSC_NULL); CHKERRQ(ierr);
341
  if (flag) {
342
    ierr = PCGetOperators(pc, &A, PETSC_NULL, PETSC_NULL); CHKERRQ(ierr);
343
    ierr = PetscObjectReference((PetscObject)A); CHKERRQ(ierr);
344
  } else
345
    A = PETSC_NULL;
346
  ierr = PetscObjectReference((PetscObject)mat); CHKERRQ(ierr);
347
  ierr = PCSetOperators(pc, A, mat, DIFFERENT_NONZERO_PATTERN); CHKERRQ(ierr);
348
  if (A) { ierr = MatDestroy(A); CHKERRQ(ierr); }
349
  ierr = MatDestroy(mat); CHKERRQ(ierr);
1996 eromero 350
 
351
  PetscFunctionReturn(0);
352
}
2012 eromero 353
EXTERN_C_END
1996 eromero 354
 
2000 eromero 355
 
356
#undef __FUNCT__  
2020 eromero 357
#define __FUNCT__ "STPrecondSetKSPHasMat"
2000 eromero 358
/*@
2020 eromero 359
   STPrecondSetKSPHasMat - Sets if during the STSetUp the KSP matrix associated
2000 eromero 360
   to the linear system is set with the matrix for building the preconditioner.
361
 
362
   Collective on ST
363
 
364
   Input Parameter:
365
+  st - the spectral transformation context
366
-  setmat - if true, the KSP matrix associated to linear system is set with
367
   the matrix for building the preconditioner
368
 
369
   Level: developer
370
 
2110 jroman 371
.seealso: STPrecondGetKSPHasMat(), TSetShift(), KSPSetOperators()
2000 eromero 372
@*/
2216 jroman 373
PetscErrorCode STPrecondSetKSPHasMat(ST st,PetscBool setmat)
2000 eromero 374
{
2221 jroman 375
  PetscErrorCode ierr;
2000 eromero 376
 
377
  PetscFunctionBegin;
2213 jroman 378
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
2221 jroman 379
  ierr = PetscTryMethod(st,"STPrecondSetKSPHasMat_C",(ST,PetscBool),(st,setmat));CHKERRQ(ierr);
2000 eromero 380
  PetscFunctionReturn(0);
381
}
382
 
383
#undef __FUNCT__  
2020 eromero 384
#define __FUNCT__ "STPrecondGetKSPHasMat"
2000 eromero 385
/*@
2020 eromero 386
   STPrecondGetKSPHasMat - Gets if during the STSetUp the KSP matrix associated
2000 eromero 387
   to the linear system is set with the matrix for building the preconditioner.
388
 
389
   Collective on ST
390
 
391
   Input Parameter:
392
.  st - the spectral transformation context
393
 
394
   Output Parameter:
395
.  setmat - if true, the KSP matrix associated to linear system is set with
396
   the matrix for building the preconditioner
397
 
398
   Level: developer
399
 
2020 eromero 400
.seealso: STPrecondSetKSPHasMat(), STSetShift(), KSPSetOperators()
2000 eromero 401
@*/
2216 jroman 402
PetscErrorCode STPrecondGetKSPHasMat(ST st,PetscBool *setmat)
2000 eromero 403
{
2221 jroman 404
  PetscErrorCode ierr;
2000 eromero 405
 
406
  PetscFunctionBegin;
2213 jroman 407
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
2221 jroman 408
  ierr = PetscTryMethod(st,"STPrecondGetKSPHasMat_C",(ST,PetscBool*),(st,setmat));CHKERRQ(ierr);
2000 eromero 409
  PetscFunctionReturn(0);
410
}
411
 
2012 eromero 412
EXTERN_C_BEGIN
2223 jroman 413
#undef __FUNCT__
414
#define __FUNCT__ "STPrecondSetKSPHasMat_Precond"
2216 jroman 415
PetscErrorCode STPrecondSetKSPHasMat_Precond(ST st,PetscBool setmat)
2000 eromero 416
{
417
  ST_PRECOND     *data = (ST_PRECOND*)st->data;
418
 
419
  PetscFunctionBegin;
420
 
2213 jroman 421
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
2000 eromero 422
 
423
  data->setmat = setmat;
424
 
425
  PetscFunctionReturn(0);
426
}
2012 eromero 427
EXTERN_C_END
2000 eromero 428
 
2012 eromero 429
EXTERN_C_BEGIN
2223 jroman 430
#undef __FUNCT__
431
#define __FUNCT__ "STPrecondGetKSPHasMat_Precond"
2216 jroman 432
PetscErrorCode STPrecondGetKSPHasMat_Precond(ST st,PetscBool *setmat)
2000 eromero 433
{
434
  ST_PRECOND     *data = (ST_PRECOND*)st->data;
435
 
436
  PetscFunctionBegin;
437
 
2213 jroman 438
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
2000 eromero 439
 
440
  *setmat = data->setmat;
441
 
442
  PetscFunctionReturn(0);
443
}
2012 eromero 444
EXTERN_C_END
2000 eromero 445