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"
1779 antodo 66
PetscErrorCode STBackTransform_Sinvert(ST st,PetscInt n,PetscScalar *eigr,PetscScalar *eigi)
6 dsic.upv.es!jroman 67
{
1778 antodo 68
  PetscInt j;
267 dsic.upv.es!antodo 69
#ifndef PETSC_USE_COMPLEX
179 dsic.upv.es!antodo 70
  PetscScalar t;
6 dsic.upv.es!jroman 71
  PetscFunctionBegin;
179 dsic.upv.es!antodo 72
  PetscValidPointer(eigr,2);
73
  PetscValidPointer(eigi,3);
1778 antodo 74
  for (j=0;j<n;j++) {
75
    if (eigi[j] == 0) eigr[j] = 1.0 / eigr[j] + st->sigma;
76
    else {
77
      t = eigr[j] * eigr[j] + eigi[j] * eigi[j];
78
      eigr[j] = eigr[j] / t + st->sigma;
79
      eigi[j] = - eigi[j] / t;
80
    }
179 dsic.upv.es!antodo 81
  }
82
#else
267 dsic.upv.es!antodo 83
  PetscFunctionBegin;
179 dsic.upv.es!antodo 84
  PetscValidPointer(eigr,2);
1778 antodo 85
  for (j=0;j<n;j++) {
86
    eigr[j] = 1.0 / eigr[j] + st->sigma;
87
  }
179 dsic.upv.es!antodo 88
#endif
6 dsic.upv.es!jroman 89
  PetscFunctionReturn(0);
90
}
91
 
92
#undef __FUNCT__  
1029 slepc 93
#define __FUNCT__ "STPostSolve_Sinvert"
94
PetscErrorCode STPostSolve_Sinvert(ST st)
6 dsic.upv.es!jroman 95
{
476 dsic.upv.es!antodo 96
  PetscErrorCode ierr;
6 dsic.upv.es!jroman 97
 
98
  PetscFunctionBegin;
1940 jroman 99
  if (st->shift_matrix == ST_MATMODE_INPLACE) {
828 dsic.upv.es!antodo 100
    if( st->B ) {
101
      ierr = MatAXPY(st->A,st->sigma,st->B,st->str);CHKERRQ(ierr);
102
    } else {
103
      ierr = MatShift(st->A,st->sigma); CHKERRQ(ierr);
104
    }
6 dsic.upv.es!jroman 105
    st->setupcalled = 0;
106
  }
107
  PetscFunctionReturn(0);
108
}
109
 
110
#undef __FUNCT__  
111
#define __FUNCT__ "STSetUp_Sinvert"
476 dsic.upv.es!antodo 112
PetscErrorCode STSetUp_Sinvert(ST st)
6 dsic.upv.es!jroman 113
{
476 dsic.upv.es!antodo 114
  PetscErrorCode ierr;
6 dsic.upv.es!jroman 115
 
116
  PetscFunctionBegin;
360 dsic.upv.es!antodo 117
  if (st->mat) { ierr = MatDestroy(st->mat);CHKERRQ(ierr); }
6 dsic.upv.es!jroman 118
 
344 dsic.upv.es!antodo 119
  switch (st->shift_matrix) {
1940 jroman 120
  case ST_MATMODE_INPLACE:
360 dsic.upv.es!antodo 121
    st->mat = PETSC_NULL;
331 dsic.upv.es!antodo 122
    if (st->sigma != 0.0) {
326 dsic.upv.es!antodo 123
      if (st->B) {
828 dsic.upv.es!antodo 124
        ierr = MatAXPY(st->A,-st->sigma,st->B,st->str);CHKERRQ(ierr);
326 dsic.upv.es!antodo 125
      } else {
828 dsic.upv.es!antodo 126
        ierr = MatShift(st->A,-st->sigma);CHKERRQ(ierr);
326 dsic.upv.es!antodo 127
      }
128
    }
1241 slepc 129
    ierr = KSPSetOperators(st->ksp,st->A,st->A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
163 dsic.upv.es!antodo 130
    break;
1940 jroman 131
  case ST_MATMODE_SHELL:
344 dsic.upv.es!antodo 132
    ierr = STMatShellCreate(st,&st->mat);CHKERRQ(ierr);
133
    ierr = KSPSetOperators(st->ksp,st->mat,st->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
163 dsic.upv.es!antodo 134
    break;
135
  default:
331 dsic.upv.es!antodo 136
    if (st->sigma != 0.0) {
1418 slepc 137
      ierr = MatDuplicate(st->A,MAT_COPY_VALUES,&st->mat);CHKERRQ(ierr);
326 dsic.upv.es!antodo 138
      if (st->B) {
828 dsic.upv.es!antodo 139
        ierr = MatAXPY(st->mat,-st->sigma,st->B,st->str);CHKERRQ(ierr);
326 dsic.upv.es!antodo 140
      } else {
828 dsic.upv.es!antodo 141
        ierr = MatShift(st->mat,-st->sigma);CHKERRQ(ierr);
326 dsic.upv.es!antodo 142
      }
1241 slepc 143
      ierr = KSPSetOperators(st->ksp,st->mat,st->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
144
    } else {
145
      st->mat = PETSC_NULL;
146
      ierr = KSPSetOperators(st->ksp,st->A,st->A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
326 dsic.upv.es!antodo 147
    }
6 dsic.upv.es!jroman 148
  }
1241 slepc 149
 
18 dsic.upv.es!jroman 150
  ierr = KSPSetUp(st->ksp);CHKERRQ(ierr);
6 dsic.upv.es!jroman 151
  PetscFunctionReturn(0);
152
}
153
 
154
#undef __FUNCT__  
155
#define __FUNCT__ "STSetShift_Sinvert"
476 dsic.upv.es!antodo 156
PetscErrorCode STSetShift_Sinvert(ST st,PetscScalar newshift)
6 dsic.upv.es!jroman 157
{
476 dsic.upv.es!antodo 158
  PetscErrorCode ierr;
1241 slepc 159
  MatStructure   flg;
6 dsic.upv.es!jroman 160
 
161
  PetscFunctionBegin;
162
 
163
  /* Nothing to be done if STSetUp has not been called yet */
164
  if (!st->setupcalled) PetscFunctionReturn(0);
1241 slepc 165
 
166
  /* Check if the new KSP matrix has the same zero structure */
167
  if (st->B && st->str == DIFFERENT_NONZERO_PATTERN && (st->sigma == 0.0 || newshift == 0.0)) {
168
    flg = DIFFERENT_NONZERO_PATTERN;
169
  } else {
170
    flg = SAME_NONZERO_PATTERN;
171
  }
6 dsic.upv.es!jroman 172
 
344 dsic.upv.es!antodo 173
  switch (st->shift_matrix) {
1940 jroman 174
  case ST_MATMODE_INPLACE:
6 dsic.upv.es!jroman 175
    /* Undo previous operations */
331 dsic.upv.es!antodo 176
    if (st->sigma != 0.0) {
828 dsic.upv.es!antodo 177
      if (st->B) {
178
        ierr = MatAXPY(st->A,st->sigma,st->B,st->str);CHKERRQ(ierr);
179
      } else {
180
        ierr = MatShift(st->A,st->sigma);CHKERRQ(ierr);
181
      }
331 dsic.upv.es!antodo 182
    }
6 dsic.upv.es!jroman 183
    /* Apply new shift */
331 dsic.upv.es!antodo 184
    if (newshift != 0.0) {
828 dsic.upv.es!antodo 185
      if (st->B) {
186
        ierr = MatAXPY(st->A,-newshift,st->B,st->str);CHKERRQ(ierr);
187
      } else {
188
        ierr = MatShift(st->A,-newshift);CHKERRQ(ierr);
189
      }
331 dsic.upv.es!antodo 190
    }
1241 slepc 191
    ierr = KSPSetOperators(st->ksp,st->A,st->A,flg);CHKERRQ(ierr);
163 dsic.upv.es!antodo 192
    break;
1940 jroman 193
  case ST_MATMODE_SHELL:
1241 slepc 194
    ierr = KSPSetOperators(st->ksp,st->mat,st->mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);    
163 dsic.upv.es!antodo 195
    break;
196
  default:
1241 slepc 197
    if (st->mat) {
198
      ierr = MatCopy(st->A,st->mat,SUBSET_NONZERO_PATTERN); CHKERRQ(ierr);
199
    } else {
200
      ierr = MatDuplicate(st->A,MAT_COPY_VALUES,&st->mat);CHKERRQ(ierr);
201
    }
331 dsic.upv.es!antodo 202
    if (newshift != 0.0) {  
828 dsic.upv.es!antodo 203
      if (st->B) {
204
        ierr = MatAXPY(st->mat,-newshift,st->B,st->str);CHKERRQ(ierr);
205
      } else {
206
        ierr = MatShift(st->mat,-newshift);CHKERRQ(ierr);
207
      }
331 dsic.upv.es!antodo 208
    }
1241 slepc 209
    ierr = KSPSetOperators(st->ksp,st->mat,st->mat,flg);CHKERRQ(ierr);    
6 dsic.upv.es!jroman 210
  }
344 dsic.upv.es!antodo 211
  st->sigma = newshift;
18 dsic.upv.es!jroman 212
  ierr = KSPSetUp(st->ksp);CHKERRQ(ierr);
6 dsic.upv.es!jroman 213
  PetscFunctionReturn(0);
214
}
215
 
216
EXTERN_C_BEGIN
217
#undef __FUNCT__  
218
#define __FUNCT__ "STCreate_Sinvert"
476 dsic.upv.es!antodo 219
PetscErrorCode STCreate_Sinvert(ST st)
6 dsic.upv.es!jroman 220
{
221
  PetscFunctionBegin;
1358 slepc 222
  st->data                 = 0;
6 dsic.upv.es!jroman 223
 
1358 slepc 224
  st->ops->apply           = STApply_Sinvert;
225
  st->ops->getbilinearform = STGetBilinearForm_Default;
226
  st->ops->applytrans      = STApplyTranspose_Sinvert;
227
  st->ops->postsolve       = STPostSolve_Sinvert;
228
  st->ops->backtr          = STBackTransform_Sinvert;
229
  st->ops->setup           = STSetUp_Sinvert;
230
  st->ops->setshift        = STSetShift_Sinvert;
231
  st->ops->view            = STView_Default;
310 dsic.upv.es!antodo 232
 
233
  st->checknullspace      = STCheckNullSpace_Default;
6 dsic.upv.es!jroman 234
 
235
  PetscFunctionReturn(0);
236
}
237
EXTERN_C_END
238