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
 
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);
2326 jroman 246
  PetscValidPointer(mat,2);
2221 jroman 247
  ierr = PetscTryMethod(st,"STPrecondGetMatForPC_C",(ST,Mat*),(st,mat));CHKERRQ(ierr);
1996 eromero 248
  PetscFunctionReturn(0);
249
}
250
 
2012 eromero 251
EXTERN_C_BEGIN
2223 jroman 252
#undef __FUNCT__
253
#define __FUNCT__ "STPrecondGetMatForPC_Precond"
1996 eromero 254
PetscErrorCode STPrecondGetMatForPC_Precond(ST st,Mat *mat)
255
{
1997 eromero 256
  PetscErrorCode ierr;
257
  PC             pc;
2216 jroman 258
  PetscBool      flag;
1997 eromero 259
 
1996 eromero 260
  PetscFunctionBegin;
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);
2326 jroman 296
  PetscCheckSameComm(st,1,mat,2);
2221 jroman 297
  ierr = PetscTryMethod(st,"STPrecondSetMatForPC_C",(ST,Mat),(st,mat));CHKERRQ(ierr);
1996 eromero 298
  PetscFunctionReturn(0);
299
}
300
 
2012 eromero 301
EXTERN_C_BEGIN
2223 jroman 302
#undef __FUNCT__
303
#define __FUNCT__ "STPrecondSetMatForPC_Precond"
1996 eromero 304
PetscErrorCode STPrecondSetMatForPC_Precond(ST st,Mat mat)
305
{
1997 eromero 306
  PC             pc;
2182 eromero 307
  Mat            A;
2216 jroman 308
  PetscBool      flag;
1996 eromero 309
  PetscErrorCode ierr;
310
 
311
  PetscFunctionBegin;
1997 eromero 312
  ierr = KSPGetPC(st->ksp, &pc); CHKERRQ(ierr);
2182 eromero 313
  /* Yes, all these lines are needed to safely set mat as the preconditioner
314
     matrix in pc */
315
  ierr = PCGetOperatorsSet(pc, &flag, PETSC_NULL); CHKERRQ(ierr);
316
  if (flag) {
317
    ierr = PCGetOperators(pc, &A, PETSC_NULL, PETSC_NULL); CHKERRQ(ierr);
318
    ierr = PetscObjectReference((PetscObject)A); CHKERRQ(ierr);
319
  } else
320
    A = PETSC_NULL;
321
  ierr = PetscObjectReference((PetscObject)mat); CHKERRQ(ierr);
322
  ierr = PCSetOperators(pc, A, mat, DIFFERENT_NONZERO_PATTERN); CHKERRQ(ierr);
2305 jroman 323
  ierr = MatDestroy(&A);CHKERRQ(ierr);
324
  ierr = MatDestroy(&mat);CHKERRQ(ierr);
2302 eromero 325
  ierr = STPrecondSetKSPHasMat(st, PETSC_TRUE); CHKERRQ(ierr);
1996 eromero 326
  PetscFunctionReturn(0);
327
}
2012 eromero 328
EXTERN_C_END
1996 eromero 329
 
2000 eromero 330
 
331
#undef __FUNCT__  
2020 eromero 332
#define __FUNCT__ "STPrecondSetKSPHasMat"
2000 eromero 333
/*@
2020 eromero 334
   STPrecondSetKSPHasMat - Sets if during the STSetUp the KSP matrix associated
2000 eromero 335
   to the linear system is set with the matrix for building the preconditioner.
336
 
337
   Collective on ST
338
 
339
   Input Parameter:
340
+  st - the spectral transformation context
341
-  setmat - if true, the KSP matrix associated to linear system is set with
342
   the matrix for building the preconditioner
343
 
344
   Level: developer
345
 
2110 jroman 346
.seealso: STPrecondGetKSPHasMat(), TSetShift(), KSPSetOperators()
2000 eromero 347
@*/
2216 jroman 348
PetscErrorCode STPrecondSetKSPHasMat(ST st,PetscBool setmat)
2000 eromero 349
{
2221 jroman 350
  PetscErrorCode ierr;
2000 eromero 351
 
352
  PetscFunctionBegin;
2213 jroman 353
  PetscValidHeaderSpecific(st,ST_CLASSID,1);
2326 jroman 354
  PetscValidLogicalCollectiveBool(st,setmat,2);
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);
2326 jroman 384
  PetscValidPointer(setmat,2);
2221 jroman 385
  ierr = PetscTryMethod(st,"STPrecondGetKSPHasMat_C",(ST,PetscBool*),(st,setmat));CHKERRQ(ierr);
2000 eromero 386
  PetscFunctionReturn(0);
387
}
388
 
2012 eromero 389
EXTERN_C_BEGIN
2223 jroman 390
#undef __FUNCT__
391
#define __FUNCT__ "STPrecondSetKSPHasMat_Precond"
2216 jroman 392
PetscErrorCode STPrecondSetKSPHasMat_Precond(ST st,PetscBool setmat)
2000 eromero 393
{
2317 jroman 394
  ST_PRECOND *data = (ST_PRECOND*)st->data;
2000 eromero 395
 
396
  PetscFunctionBegin;
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;
410
  *setmat = data->setmat;
411
  PetscFunctionReturn(0);
412
}
2012 eromero 413
EXTERN_C_END
2000 eromero 414