Subversion Repositories slepc-dev

Rev

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