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.
1376 slepc 3
 
4
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 5
   SLEPc - Scalable Library for Eigenvalue Problem Computations
6
   Copyright (c) 2002-2009, Universidad Politecnica de Valencia, Spain
1376 slepc 7
 
1672 slepc 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/>.
1376 slepc 21
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6 dsic.upv.es!jroman 22
*/
1376 slepc 23
 
1521 slepc 24
#include "private/stimpl.h"          /*I "slepcst.h" I*/
6 dsic.upv.es!jroman 25
 
26
#undef __FUNCT__  
27
#define __FUNCT__ "STApply_Sinvert"
476 dsic.upv.es!antodo 28
PetscErrorCode STApply_Sinvert(ST st,Vec x,Vec y)
6 dsic.upv.es!jroman 29
{
476 dsic.upv.es!antodo 30
  PetscErrorCode ierr;
6 dsic.upv.es!jroman 31
 
32
  PetscFunctionBegin;
33
  if (st->B) {
34
    /* generalized eigenproblem: y = (A - sB)^-1 B x */
344 dsic.upv.es!antodo 35
    ierr = MatMult(st->B,x,st->w);CHKERRQ(ierr);
36
    ierr = STAssociatedKSPSolve(st,st->w,y);CHKERRQ(ierr);
6 dsic.upv.es!jroman 37
  }
38
  else {
39
    /* standard eigenproblem: y = (A - sI)^-1 x */
18 dsic.upv.es!jroman 40
    ierr = STAssociatedKSPSolve(st,x,y);CHKERRQ(ierr);
6 dsic.upv.es!jroman 41
  }
42
  PetscFunctionReturn(0);
43
}
44
 
45
#undef __FUNCT__  
780 dsic.upv.es!jroman 46
#define __FUNCT__ "STApplyTranspose_Sinvert"
47
PetscErrorCode STApplyTranspose_Sinvert(ST st,Vec x,Vec y)
48
{
49
  PetscErrorCode ierr;
50
 
51
  PetscFunctionBegin;
52
  if (st->B) {
53
    /* generalized eigenproblem: y = B^T (A - sB)^-T x */
54
    ierr = STAssociatedKSPSolveTranspose(st,x,st->w);CHKERRQ(ierr);
55
    ierr = MatMultTranspose(st->B,st->w,y);CHKERRQ(ierr);
56
  }
57
  else {
58
    /* standard eigenproblem: y = (A - sI)^-T x */
59
    ierr = STAssociatedKSPSolveTranspose(st,x,y);CHKERRQ(ierr);
60
  }
61
  PetscFunctionReturn(0);
62
}
63
 
64
#undef __FUNCT__  
6 dsic.upv.es!jroman 65
#define __FUNCT__ "STBackTransform_Sinvert"
476 dsic.upv.es!antodo 66
PetscErrorCode STBackTransform_Sinvert(ST st,PetscScalar *eigr,PetscScalar *eigi)
6 dsic.upv.es!jroman 67
{
267 dsic.upv.es!antodo 68
#ifndef PETSC_USE_COMPLEX
179 dsic.upv.es!antodo 69
  PetscScalar t;
6 dsic.upv.es!jroman 70
  PetscFunctionBegin;
179 dsic.upv.es!antodo 71
  PetscValidPointer(eigr,2);
72
  PetscValidPointer(eigi,3);
73
  if (*eigi == 0) *eigr = 1.0 / *eigr + st->sigma;
74
  else {
75
    t = *eigr * *eigr + *eigi * *eigi;
76
    *eigr = *eigr / t + st->sigma;
77
    *eigi = - *eigi / t;
78
  }
79
#else
267 dsic.upv.es!antodo 80
  PetscFunctionBegin;
179 dsic.upv.es!antodo 81
  PetscValidPointer(eigr,2);
82
  *eigr = 1.0 / *eigr + st->sigma;
83
#endif
6 dsic.upv.es!jroman 84
  PetscFunctionReturn(0);
85
}
86
 
87
#undef __FUNCT__  
1029 slepc 88
#define __FUNCT__ "STPostSolve_Sinvert"
89
PetscErrorCode STPostSolve_Sinvert(ST st)
6 dsic.upv.es!jroman 90
{
476 dsic.upv.es!antodo 91
  PetscErrorCode ierr;
6 dsic.upv.es!jroman 92
 
93
  PetscFunctionBegin;
344 dsic.upv.es!antodo 94
  if (st->shift_matrix == STMATMODE_INPLACE) {
828 dsic.upv.es!antodo 95
    if( st->B ) {
96
      ierr = MatAXPY(st->A,st->sigma,st->B,st->str);CHKERRQ(ierr);
97
    } else {
98
      ierr = MatShift(st->A,st->sigma); CHKERRQ(ierr);
99
    }
6 dsic.upv.es!jroman 100
    st->setupcalled = 0;
101
  }
102
  PetscFunctionReturn(0);
103
}
104
 
105
#undef __FUNCT__  
106
#define __FUNCT__ "STSetUp_Sinvert"
476 dsic.upv.es!antodo 107
PetscErrorCode STSetUp_Sinvert(ST st)
6 dsic.upv.es!jroman 108
{
476 dsic.upv.es!antodo 109
  PetscErrorCode ierr;
6 dsic.upv.es!jroman 110
 
111
  PetscFunctionBegin;
360 dsic.upv.es!antodo 112
  if (st->mat) { ierr = MatDestroy(st->mat);CHKERRQ(ierr); }
6 dsic.upv.es!jroman 113
 
344 dsic.upv.es!antodo 114
  switch (st->shift_matrix) {
115
  case STMATMODE_INPLACE:
360 dsic.upv.es!antodo 116
    st->mat = PETSC_NULL;
331 dsic.upv.es!antodo 117
    if (st->sigma != 0.0) {
326 dsic.upv.es!antodo 118
      if (st->B) {
828 dsic.upv.es!antodo 119
        ierr = MatAXPY(st->A,-st->sigma,st->B,st->str);CHKERRQ(ierr);
326 dsic.upv.es!antodo 120
      } else {
828 dsic.upv.es!antodo 121
        ierr = MatShift(st->A,-st->sigma);CHKERRQ(ierr);
326 dsic.upv.es!antodo 122
      }
123
    }
1241 slepc 124
    ierr = KSPSetOperators(st->ksp,st->A,st->A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
163 dsic.upv.es!antodo 125
    break;
344 dsic.upv.es!antodo 126
  case STMATMODE_SHELL:
127
    ierr = STMatShellCreate(st,&st->mat);CHKERRQ(ierr);
128
    ierr = KSPSetOperators(st->ksp,st->mat,st->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
163 dsic.upv.es!antodo 129
    break;
130
  default:
331 dsic.upv.es!antodo 131
    if (st->sigma != 0.0) {
1418 slepc 132
      ierr = MatDuplicate(st->A,MAT_COPY_VALUES,&st->mat);CHKERRQ(ierr);
326 dsic.upv.es!antodo 133
      if (st->B) {
828 dsic.upv.es!antodo 134
        ierr = MatAXPY(st->mat,-st->sigma,st->B,st->str);CHKERRQ(ierr);
326 dsic.upv.es!antodo 135
      } else {
828 dsic.upv.es!antodo 136
        ierr = MatShift(st->mat,-st->sigma);CHKERRQ(ierr);
326 dsic.upv.es!antodo 137
      }
1241 slepc 138
      ierr = KSPSetOperators(st->ksp,st->mat,st->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
139
    } else {
140
      st->mat = PETSC_NULL;
141
      ierr = KSPSetOperators(st->ksp,st->A,st->A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
326 dsic.upv.es!antodo 142
    }
6 dsic.upv.es!jroman 143
  }
1241 slepc 144
 
18 dsic.upv.es!jroman 145
  ierr = KSPSetUp(st->ksp);CHKERRQ(ierr);
6 dsic.upv.es!jroman 146
  PetscFunctionReturn(0);
147
}
148
 
149
#undef __FUNCT__  
150
#define __FUNCT__ "STSetShift_Sinvert"
476 dsic.upv.es!antodo 151
PetscErrorCode STSetShift_Sinvert(ST st,PetscScalar newshift)
6 dsic.upv.es!jroman 152
{
476 dsic.upv.es!antodo 153
  PetscErrorCode ierr;
1241 slepc 154
  MatStructure   flg;
6 dsic.upv.es!jroman 155
 
156
  PetscFunctionBegin;
157
 
158
  /* Nothing to be done if STSetUp has not been called yet */
159
  if (!st->setupcalled) PetscFunctionReturn(0);
1241 slepc 160
 
161
  /* Check if the new KSP matrix has the same zero structure */
162
  if (st->B && st->str == DIFFERENT_NONZERO_PATTERN && (st->sigma == 0.0 || newshift == 0.0)) {
163
    flg = DIFFERENT_NONZERO_PATTERN;
164
  } else {
165
    flg = SAME_NONZERO_PATTERN;
166
  }
6 dsic.upv.es!jroman 167
 
344 dsic.upv.es!antodo 168
  switch (st->shift_matrix) {
169
  case STMATMODE_INPLACE:
6 dsic.upv.es!jroman 170
    /* Undo previous operations */
331 dsic.upv.es!antodo 171
    if (st->sigma != 0.0) {
828 dsic.upv.es!antodo 172
      if (st->B) {
173
        ierr = MatAXPY(st->A,st->sigma,st->B,st->str);CHKERRQ(ierr);
174
      } else {
175
        ierr = MatShift(st->A,st->sigma);CHKERRQ(ierr);
176
      }
331 dsic.upv.es!antodo 177
    }
6 dsic.upv.es!jroman 178
    /* Apply new shift */
331 dsic.upv.es!antodo 179
    if (newshift != 0.0) {
828 dsic.upv.es!antodo 180
      if (st->B) {
181
        ierr = MatAXPY(st->A,-newshift,st->B,st->str);CHKERRQ(ierr);
182
      } else {
183
        ierr = MatShift(st->A,-newshift);CHKERRQ(ierr);
184
      }
331 dsic.upv.es!antodo 185
    }
1241 slepc 186
    ierr = KSPSetOperators(st->ksp,st->A,st->A,flg);CHKERRQ(ierr);
163 dsic.upv.es!antodo 187
    break;
344 dsic.upv.es!antodo 188
  case STMATMODE_SHELL:
1241 slepc 189
    ierr = KSPSetOperators(st->ksp,st->mat,st->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);    
163 dsic.upv.es!antodo 190
    break;
191
  default:
1241 slepc 192
    if (st->mat) {
193
      ierr = MatCopy(st->A,st->mat,SUBSET_NONZERO_PATTERN); CHKERRQ(ierr);
194
    } else {
195
      ierr = MatDuplicate(st->A,MAT_COPY_VALUES,&st->mat);CHKERRQ(ierr);
196
    }
331 dsic.upv.es!antodo 197
    if (newshift != 0.0) {  
828 dsic.upv.es!antodo 198
      if (st->B) {
199
        ierr = MatAXPY(st->mat,-newshift,st->B,st->str);CHKERRQ(ierr);
200
      } else {
201
        ierr = MatShift(st->mat,-newshift);CHKERRQ(ierr);
202
      }
331 dsic.upv.es!antodo 203
    }
1241 slepc 204
    ierr = KSPSetOperators(st->ksp,st->mat,st->mat,flg);CHKERRQ(ierr);    
6 dsic.upv.es!jroman 205
  }
344 dsic.upv.es!antodo 206
  st->sigma = newshift;
18 dsic.upv.es!jroman 207
  ierr = KSPSetUp(st->ksp);CHKERRQ(ierr);
6 dsic.upv.es!jroman 208
  PetscFunctionReturn(0);
209
}
210
 
211
EXTERN_C_BEGIN
212
#undef __FUNCT__  
213
#define __FUNCT__ "STCreate_Sinvert"
476 dsic.upv.es!antodo 214
PetscErrorCode STCreate_Sinvert(ST st)
6 dsic.upv.es!jroman 215
{
216
  PetscFunctionBegin;
1358 slepc 217
  st->data                 = 0;
6 dsic.upv.es!jroman 218
 
1358 slepc 219
  st->ops->apply           = STApply_Sinvert;
220
  st->ops->getbilinearform = STGetBilinearForm_Default;
221
  st->ops->applytrans      = STApplyTranspose_Sinvert;
222
  st->ops->postsolve       = STPostSolve_Sinvert;
223
  st->ops->backtr          = STBackTransform_Sinvert;
224
  st->ops->setup           = STSetUp_Sinvert;
225
  st->ops->setshift        = STSetShift_Sinvert;
226
  st->ops->view            = STView_Default;
310 dsic.upv.es!antodo 227
 
228
  st->checknullspace      = STCheckNullSpace_Default;
6 dsic.upv.es!jroman 229
 
230
  PetscFunctionReturn(0);
231
}
232
EXTERN_C_END
233