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"
2317 jroman 42
PetscErrorCode SLEPcNotImplemented_Precond(ST st, Vec x, Vec y)
43
{
2214 jroman 44
  SETERRQ(((PetscObject)st)->comm,PETSC_ERR_SUP,"Operation not implemented in STPRECOND.");
1996 eromero 45
}
46
 
47
#undef __FUNCT__  
2021 eromero 48
#define __FUNCT__ "STSetFromOptions_Precond"
49
PetscErrorCode STSetFromOptions_Precond(ST st)
50
{
51
  PetscErrorCode ierr;
52
  PC             pc;
53
  const PCType   pctype;
54
  Mat            P;
2216 jroman 55
  PetscBool      t0, t1;
2021 eromero 56
 
57
  PetscFunctionBegin;
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
  PetscFunctionReturn(0);
75
}
76
 
77
#undef __FUNCT__  
1996 eromero 78
#define __FUNCT__ "STSetUp_Precond"
79
PetscErrorCode STSetUp_Precond(ST st)
80
{
1997 eromero 81
  Mat            P;
1999 eromero 82
  PC             pc;
2216 jroman 83
  PetscBool      t0, setmat, destroyP=PETSC_FALSE, builtP;
1996 eromero 84
  PetscErrorCode ierr;
85
 
86
  PetscFunctionBegin;
2086 eromero 87
  /* if the user did not set the shift, use the target value */
88
  if (!st->sigma_set) st->sigma = st->defsigma;
89
 
2000 eromero 90
  /* If pc is none and any matrix has to be set, exit */
2021 eromero 91
  ierr = STSetFromOptions_Precond(st); CHKERRQ(ierr);
2000 eromero 92
  ierr = KSPGetPC(st->ksp, &pc); CHKERRQ(ierr);
93
  ierr = PetscTypeCompare((PetscObject)pc, PCNONE, &t0); CHKERRQ(ierr);
2020 eromero 94
  ierr = STPrecondGetKSPHasMat(st, &setmat); CHKERRQ(ierr);
2177 jroman 95
  if (t0 && !setmat) PetscFunctionReturn(0);
2000 eromero 96
 
1999 eromero 97
  /* Check if a user matrix is set */
1997 eromero 98
  ierr = STPrecondGetMatForPC(st, &P); CHKERRQ(ierr);
2000 eromero 99
 
100
  /* If not, create A - shift*B */
1997 eromero 101
  if (P) {
2000 eromero 102
    builtP = PETSC_FALSE;
103
    destroyP = PETSC_TRUE;
2182 eromero 104
    ierr = PetscObjectReference((PetscObject)P);CHKERRQ(ierr);
2000 eromero 105
  } else {
106
    builtP = PETSC_TRUE;
107
 
108
    if (st->shift_matrix == ST_MATMODE_SHELL) {
109
      ierr = STMatShellCreate(st,&P);CHKERRQ(ierr);
110
      //TODO: set the apply and apply transpose to st->mat
111
      destroyP = PETSC_TRUE;
2280 jroman 112
    } else if (!(PetscAbsScalar(st->sigma) < PETSC_MAX_REAL) && st->B) {
2000 eromero 113
      P = st->B;
114
      destroyP = PETSC_FALSE;
115
    } else if (st->sigma == 0.0) {
116
      P = st->A;
117
      destroyP = PETSC_FALSE;
2280 jroman 118
    } else if (PetscAbsScalar(st->sigma) < PETSC_MAX_REAL) {
2000 eromero 119
      if (st->shift_matrix == ST_MATMODE_INPLACE) {
120
        P = st->A;
121
        destroyP = PETSC_FALSE;
122
      } else {
123
        ierr = MatDuplicate(st->A, MAT_COPY_VALUES, &P); CHKERRQ(ierr);
124
        destroyP = PETSC_TRUE;
125
      }
126
      if (st->B) {
127
        ierr = MatAXPY(P, -st->sigma, st->B, st->str); CHKERRQ(ierr);
128
      } else {
129
        ierr = MatShift(P, -st->sigma); CHKERRQ(ierr);
130
      }
131
    } else
132
      builtP = PETSC_FALSE;
1999 eromero 133
  }
134
 
2000 eromero 135
  /* If P was not possible to obtain, set pc to PCNONE */
136
  if (!P) {
137
    ierr = PCSetType(pc, PCNONE); CHKERRQ(ierr);
1999 eromero 138
 
2000 eromero 139
    /* If some matrix has to be set to ksp, set ksp to KSPPREONLY */
2177 jroman 140
    if (setmat) {
2000 eromero 141
      ierr = STMatShellCreate(st, &P);CHKERRQ(ierr);
142
      destroyP = PETSC_TRUE;
143
      ierr = KSPSetType(st->ksp, KSPPREONLY); CHKERRQ(ierr);
1999 eromero 144
    }
2000 eromero 145
  }
146
 
2177 jroman 147
  ierr = KSPSetOperators(st->ksp,setmat?P:PETSC_NULL,P,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
2000 eromero 148
 
2177 jroman 149
  if (destroyP) {
2305 jroman 150
    ierr = MatDestroy(&P);CHKERRQ(ierr);
2177 jroman 151
  } else if (st->shift_matrix == ST_MATMODE_INPLACE && builtP) {
2280 jroman 152
    if (st->sigma != 0.0 && PetscAbsScalar(st->sigma) < PETSC_MAX_REAL) {
1999 eromero 153
      if (st->B) {
154
        ierr = MatAXPY(st->A,st->sigma,st->B,st->str);CHKERRQ(ierr);
155
      } else {
156
        ierr = MatShift(st->A,st->sigma);CHKERRQ(ierr);
1996 eromero 157
      }
1999 eromero 158
    }
1996 eromero 159
  }
160
  PetscFunctionReturn(0);
161
}
162
 
163
#undef __FUNCT__  
164
#define __FUNCT__ "STSetShift_Precond"
165
PetscErrorCode STSetShift_Precond(ST st,PetscScalar newshift)
166
{
167
  PetscErrorCode ierr;
168
 
169
  PetscFunctionBegin;
170
  /* Nothing to be done if STSetUp has not been called yet */
171
  if (!st->setupcalled) PetscFunctionReturn(0);
172
  st->sigma = newshift;
173
  if (st->shift_matrix != ST_MATMODE_SHELL) {
174
    ierr =  STSetUp_Precond(st); CHKERRQ(ierr);
175
  }
176
  PetscFunctionReturn(0);
177
}
178
 
179
EXTERN_C_BEGIN
180
#undef __FUNCT__  
181
#define __FUNCT__ "STCreate_Precond"
182
PetscErrorCode STCreate_Precond(ST st)
183
{
184
  PetscErrorCode ierr;
2000 eromero 185
  ST_PRECOND     *data;
1996 eromero 186
 
187
  PetscFunctionBegin;
2000 eromero 188
  ierr = PetscNew(ST_PRECOND, &data); CHKERRQ(ierr);
189
  st->data                 = data;
1996 eromero 190
 
191
  st->ops->apply           = SLEPcNotImplemented_Precond;
192
  st->ops->getbilinearform = STGetBilinearForm_Default;
193
  st->ops->applytrans      = SLEPcNotImplemented_Precond;
194
  st->ops->postsolve       = PETSC_NULL;
195
  st->ops->backtr          = PETSC_NULL;
196
  st->ops->setup           = STSetUp_Precond;
197
  st->ops->setshift        = STSetShift_Precond;
198
  st->ops->view            = STView_Default;
199
  st->ops->destroy         = STDestroy_Precond;
2021 eromero 200
  st->ops->setfromoptions  = STSetFromOptions_Precond;
1996 eromero 201
 
2021 eromero 202
  st->checknullspace       = PETSC_NULL;
1996 eromero 203
 
204
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondGetMatForPC_C","STPrecondGetMatForPC_Precond",STPrecondGetMatForPC_Precond);CHKERRQ(ierr);
205
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondSetMatForPC_C","STPrecondSetMatForPC_Precond",STPrecondSetMatForPC_Precond);CHKERRQ(ierr);
2020 eromero 206
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondGetKSPHasMat_C","STPrecondGetKSPHasMat_Precond",STPrecondGetKSPHasMat_Precond);CHKERRQ(ierr);
207
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondSetKSPHasMat_C","STPrecondSetKSPHasMat_Precond",STPrecondSetKSPHasMat_Precond);CHKERRQ(ierr);
1996 eromero 208
 
2020 eromero 209
  ierr = STPrecondSetKSPHasMat_Precond(st, PETSC_TRUE); CHKERRQ(ierr);
2006 eromero 210
  ierr = KSPSetType(st->ksp, KSPPREONLY); CHKERRQ(ierr);
1996 eromero 211
  PetscFunctionReturn(0);
212
}
213
EXTERN_C_END
214
 
215
#undef __FUNCT__  
216
#define __FUNCT__ "STDestroy_Precond"
217
PetscErrorCode STDestroy_Precond(ST st)
218
{
219
  PetscErrorCode ierr;
220
 
221
  PetscFunctionBegin;
222
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondGetMatForPC_C","",PETSC_NULL);CHKERRQ(ierr);
223
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondSetMatForPC_C","",PETSC_NULL);CHKERRQ(ierr);
2020 eromero 224
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondGetKSPHasMat_C","",PETSC_NULL);CHKERRQ(ierr);
225
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)st,"STPrecondSetKSPHasMat_C","",PETSC_NULL);CHKERRQ(ierr);
2000 eromero 226
  ierr = PetscFree(st->data); CHKERRQ(ierr);
1996 eromero 227
  PetscFunctionReturn(0);
228
}
229
 
230
#undef __FUNCT__  
231
#define __FUNCT__ "STPrecondGetMatForPC"
232
/*@
233
   STPrecondGetMatForPC - Gets the matrix previously set by STPrecondSetMatForPC.
234
   This matrix will be passed as parameter in the KSPSetOperator function as
235
   the matrix to be used in constructing the preconditioner.
236
 
237
   Collective on ST
238
 
239
   Input Parameter:
240
.  st - the spectral transformation context
241
 
242
   Output Parameter:
243
.  mat - the matrix that will be used in constructing the preconditioner or
244
   PETSC_NULL if any previous matrix was set by STPrecondSetMatForPC.
245
 
246
   Level: advanced
247
 
248
.seealso: STPrecondSetMatForPC(), KSPSetOperator()
249
@*/
250
PetscErrorCode STPrecondGetMatForPC(ST st,Mat *mat)
251
{
2221 jroman 252
  PetscErrorCode ierr;
1996 eromero 253
 
254
  PetscFunctionBegin;
2213 jroman 255
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
2221 jroman 256
  ierr = PetscTryMethod(st,"STPrecondGetMatForPC_C",(ST,Mat*),(st,mat));CHKERRQ(ierr);
1996 eromero 257
  PetscFunctionReturn(0);
258
}
259
 
2012 eromero 260
EXTERN_C_BEGIN
2223 jroman 261
#undef __FUNCT__
262
#define __FUNCT__ "STPrecondGetMatForPC_Precond"
1996 eromero 263
PetscErrorCode STPrecondGetMatForPC_Precond(ST st,Mat *mat)
264
{
1997 eromero 265
  PetscErrorCode ierr;
266
  PC             pc;
2216 jroman 267
  PetscBool      flag;
1997 eromero 268
 
1996 eromero 269
  PetscFunctionBegin;
2213 jroman 270
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
1997 eromero 271
  ierr = KSPGetPC(st->ksp, &pc); CHKERRQ(ierr);
272
  ierr = PCGetOperatorsSet(pc, PETSC_NULL, &flag); CHKERRQ(ierr);
2177 jroman 273
  if (flag) {
1997 eromero 274
    ierr = PCGetOperators(pc, PETSC_NULL, mat, PETSC_NULL); CHKERRQ(ierr);
275
  } else
276
    *mat = PETSC_NULL;
1996 eromero 277
  PetscFunctionReturn(0);
278
}
2012 eromero 279
EXTERN_C_END
1996 eromero 280
 
281
#undef __FUNCT__  
282
#define __FUNCT__ "STPrecondSetMatForPC"
283
/*@
284
   STPrecondSetMatForPC - Sets the matrix that will be passed as parameter in
2000 eromero 285
   the KSPSetOperators function as the matrix to be used in constructing the
1996 eromero 286
   preconditioner. If any matrix is set or mat is PETSC_NULL, A - sigma*B will
287
   be used, being sigma the value set by STSetShift
288
 
289
   Collective on ST
290
 
291
   Input Parameter:
292
+  st - the spectral transformation context
293
-  mat - the matrix that will be used in constructing the preconditioner
294
 
295
   Level: advanced
296
 
2000 eromero 297
.seealso: STPrecondSetMatForPC(), KSPSetOperators()
1996 eromero 298
@*/
299
PetscErrorCode STPrecondSetMatForPC(ST st,Mat mat)
300
{
2221 jroman 301
  PetscErrorCode ierr;
1996 eromero 302
 
303
  PetscFunctionBegin;
2213 jroman 304
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
305
  PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
2221 jroman 306
  ierr = PetscTryMethod(st,"STPrecondSetMatForPC_C",(ST,Mat),(st,mat));CHKERRQ(ierr);
1996 eromero 307
  PetscFunctionReturn(0);
308
}
309
 
2012 eromero 310
EXTERN_C_BEGIN
2223 jroman 311
#undef __FUNCT__
312
#define __FUNCT__ "STPrecondSetMatForPC_Precond"
1996 eromero 313
PetscErrorCode STPrecondSetMatForPC_Precond(ST st,Mat mat)
314
{
1997 eromero 315
  PC             pc;
2182 eromero 316
  Mat            A;
2216 jroman 317
  PetscBool      flag;
1996 eromero 318
  PetscErrorCode ierr;
319
 
320
  PetscFunctionBegin;
2213 jroman 321
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
322
  PetscValidHeaderSpecific(mat,MAT_CLASSID,2);
1997 eromero 323
  ierr = KSPGetPC(st->ksp, &pc); CHKERRQ(ierr);
2182 eromero 324
  /* Yes, all these lines are needed to safely set mat as the preconditioner
325
     matrix in pc */
326
  ierr = PCGetOperatorsSet(pc, &flag, PETSC_NULL); CHKERRQ(ierr);
327
  if (flag) {
328
    ierr = PCGetOperators(pc, &A, PETSC_NULL, PETSC_NULL); CHKERRQ(ierr);
329
    ierr = PetscObjectReference((PetscObject)A); CHKERRQ(ierr);
330
  } else
331
    A = PETSC_NULL;
332
  ierr = PetscObjectReference((PetscObject)mat); CHKERRQ(ierr);
333
  ierr = PCSetOperators(pc, A, mat, DIFFERENT_NONZERO_PATTERN); CHKERRQ(ierr);
2305 jroman 334
  ierr = MatDestroy(&A);CHKERRQ(ierr);
335
  ierr = MatDestroy(&mat);CHKERRQ(ierr);
2302 eromero 336
  ierr = STPrecondSetKSPHasMat(st, PETSC_TRUE); CHKERRQ(ierr);
1996 eromero 337
  PetscFunctionReturn(0);
338
}
2012 eromero 339
EXTERN_C_END
1996 eromero 340
 
2000 eromero 341
 
342
#undef __FUNCT__  
2020 eromero 343
#define __FUNCT__ "STPrecondSetKSPHasMat"
2000 eromero 344
/*@
2020 eromero 345
   STPrecondSetKSPHasMat - Sets if during the STSetUp the KSP matrix associated
2000 eromero 346
   to the linear system is set with the matrix for building the preconditioner.
347
 
348
   Collective on ST
349
 
350
   Input Parameter:
351
+  st - the spectral transformation context
352
-  setmat - if true, the KSP matrix associated to linear system is set with
353
   the matrix for building the preconditioner
354
 
355
   Level: developer
356
 
2110 jroman 357
.seealso: STPrecondGetKSPHasMat(), TSetShift(), KSPSetOperators()
2000 eromero 358
@*/
2216 jroman 359
PetscErrorCode STPrecondSetKSPHasMat(ST st,PetscBool setmat)
2000 eromero 360
{
2221 jroman 361
  PetscErrorCode ierr;
2000 eromero 362
 
363
  PetscFunctionBegin;
2213 jroman 364
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
2221 jroman 365
  ierr = PetscTryMethod(st,"STPrecondSetKSPHasMat_C",(ST,PetscBool),(st,setmat));CHKERRQ(ierr);
2000 eromero 366
  PetscFunctionReturn(0);
367
}
368
 
369
#undef __FUNCT__  
2020 eromero 370
#define __FUNCT__ "STPrecondGetKSPHasMat"
2000 eromero 371
/*@
2020 eromero 372
   STPrecondGetKSPHasMat - Gets if during the STSetUp the KSP matrix associated
2000 eromero 373
   to the linear system is set with the matrix for building the preconditioner.
374
 
375
   Collective on ST
376
 
377
   Input Parameter:
378
.  st - the spectral transformation context
379
 
380
   Output Parameter:
381
.  setmat - if true, the KSP matrix associated to linear system is set with
382
   the matrix for building the preconditioner
383
 
384
   Level: developer
385
 
2020 eromero 386
.seealso: STPrecondSetKSPHasMat(), STSetShift(), KSPSetOperators()
2000 eromero 387
@*/
2216 jroman 388
PetscErrorCode STPrecondGetKSPHasMat(ST st,PetscBool *setmat)
2000 eromero 389
{
2221 jroman 390
  PetscErrorCode ierr;
2000 eromero 391
 
392
  PetscFunctionBegin;
2213 jroman 393
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
2221 jroman 394
  ierr = PetscTryMethod(st,"STPrecondGetKSPHasMat_C",(ST,PetscBool*),(st,setmat));CHKERRQ(ierr);
2000 eromero 395
  PetscFunctionReturn(0);
396
}
397
 
2012 eromero 398
EXTERN_C_BEGIN
2223 jroman 399
#undef __FUNCT__
400
#define __FUNCT__ "STPrecondSetKSPHasMat_Precond"
2216 jroman 401
PetscErrorCode STPrecondSetKSPHasMat_Precond(ST st,PetscBool setmat)
2000 eromero 402
{
2317 jroman 403
  ST_PRECOND *data = (ST_PRECOND*)st->data;
2000 eromero 404
 
405
  PetscFunctionBegin;
2213 jroman 406
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
2000 eromero 407
  data->setmat = setmat;
408
  PetscFunctionReturn(0);
409
}
2012 eromero 410
EXTERN_C_END
2000 eromero 411
 
2012 eromero 412
EXTERN_C_BEGIN
2223 jroman 413
#undef __FUNCT__
414
#define __FUNCT__ "STPrecondGetKSPHasMat_Precond"
2216 jroman 415
PetscErrorCode STPrecondGetKSPHasMat_Precond(ST st,PetscBool *setmat)
2000 eromero 416
{
2317 jroman 417
  ST_PRECOND *data = (ST_PRECOND*)st->data;
2000 eromero 418
 
419
  PetscFunctionBegin;
2213 jroman 420
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
2000 eromero 421
  *setmat = data->setmat;
422
  PetscFunctionReturn(0);
423
}
2012 eromero 424
EXTERN_C_END
2000 eromero 425