Actual source code: sinvert.c

  1: /*
  2:       Implements the shift-and-invert technique for eigenvalue problems.
  3: */
 4:  #include src/st/stimpl.h

  8: PetscErrorCode STApply_Sinvert(ST st,Vec x,Vec y)
  9: {
 10:   PetscErrorCode ierr;

 13:   if (st->B) {
 14:     /* generalized eigenproblem: y = (A - sB)^-1 B x */
 15:     MatMult(st->B,x,st->w);
 16:     STAssociatedKSPSolve(st,st->w,y);
 17:   }
 18:   else {
 19:     /* standard eigenproblem: y = (A - sI)^-1 x */
 20:     STAssociatedKSPSolve(st,x,y);
 21:   }
 22:   return(0);
 23: }

 27: PetscErrorCode STApplyNoB_Sinvert(ST st,Vec x,Vec y)
 28: {
 29:   PetscErrorCode ierr;

 32:   STAssociatedKSPSolve(st,x,y);
 33:   return(0);
 34: }

 38: PetscErrorCode STApplyB_Sinvert(ST st,Vec x,Vec y)
 39: {
 40:   PetscErrorCode ierr;

 43:   if( st->B ) {
 44:     MatMult( st->B, x, y );
 45:   }
 46:   else {
 47:     VecCopy( x, y );
 48:   }
 49:   return(0);
 50: }

 54: PetscErrorCode STBackTransform_Sinvert(ST st,PetscScalar *eigr,PetscScalar *eigi)
 55: {
 56: #ifndef PETSC_USE_COMPLEX
 57:   PetscScalar t;
 61:   if (*eigi == 0) *eigr = 1.0 / *eigr + st->sigma;
 62:   else {
 63:     t = *eigr * *eigr + *eigi * *eigi;
 64:     *eigr = *eigr / t + st->sigma;
 65:     *eigi = - *eigi / t;
 66:   }
 67: #else
 70:   *eigr = 1.0 / *eigr + st->sigma;
 71: #endif
 72:   return(0);
 73: }

 77: PetscErrorCode STPost_Sinvert(ST st)
 78: {
 79:   PetscErrorCode ierr;
 80:   PetscScalar    alpha;

 83:   if (st->shift_matrix == STMATMODE_INPLACE) {
 84:     alpha = st->sigma;
 85:     if( st->B ) { MatAXPY(&alpha,st->B,st->A,st->str); }
 86:     else { MatShift( &alpha, st->A );  }
 87:     st->setupcalled = 0;
 88:   }
 89:   return(0);
 90: }

 94: PetscErrorCode STSetUp_Sinvert(ST st)
 95: {
 96:   PetscErrorCode ierr;
 97:   PetscScalar    alpha;

100: 
101:   if (st->mat) { MatDestroy(st->mat); }

103:   switch (st->shift_matrix) {
104:   case STMATMODE_INPLACE:
105:     st->mat = PETSC_NULL;
106:     if (st->sigma != 0.0) {
107:       alpha = -st->sigma;
108:       if (st->B) {
109:         MatAXPY(&alpha,st->B,st->A,st->str);
110:       } else {
111:         MatShift(&alpha,st->A);
112:       }
113:     }
114:     /* In the following line, the SAME_NONZERO_PATTERN flag has been used to
115:      * improve performance when solving a number of related eigenproblems */
116:     KSPSetOperators(st->ksp,st->A,st->A,SAME_NONZERO_PATTERN);
117:     break;
118:   case STMATMODE_SHELL:
119:     STMatShellCreate(st,&st->mat);
120:     KSPSetOperators(st->ksp,st->mat,st->mat,DIFFERENT_NONZERO_PATTERN);
121:     break;
122:   default:
123:     MatDuplicate(st->A,MAT_COPY_VALUES,&st->mat);
124:     if (st->sigma != 0.0) {
125:       alpha = -st->sigma;
126:       if (st->B) {
127:         MatAXPY(&alpha,st->B,st->mat,st->str);
128:       } else {
129:         MatShift(&alpha,st->mat);
130:       }
131:     }
132:     /* In the following line, the SAME_NONZERO_PATTERN flag has been used to
133:      * improve performance when solving a number of related eigenproblems */
134:     KSPSetOperators(st->ksp,st->mat,st->mat,SAME_NONZERO_PATTERN);
135:   }
136:   KSPSetUp(st->ksp);
137:   return(0);
138: }

142: PetscErrorCode STSetShift_Sinvert(ST st,PetscScalar newshift)
143: {
144:   PetscErrorCode ierr;
145:   PetscScalar    alpha;


149:   /* Nothing to be done if STSetUp has not been called yet */
150:   if (!st->setupcalled) return(0);

152:   switch (st->shift_matrix) {
153:   case STMATMODE_INPLACE:
154:     /* Undo previous operations */
155:     if (st->sigma != 0.0) {
156:       alpha = st->sigma;
157:       if (st->B) { MatAXPY(&alpha,st->B,st->A,st->str); }
158:       else { MatShift(&alpha,st->A); }
159:     }
160:     /* Apply new shift */
161:     if (newshift != 0.0) {
162:       alpha = -newshift;
163:       if (st->B) { MatAXPY(&alpha,st->B,st->A,st->str); }
164:       else { MatShift(&alpha,st->A); }
165:     }
166:     KSPSetOperators(st->ksp,st->A,st->A,SAME_NONZERO_PATTERN);
167:     break;
168:   case STMATMODE_SHELL:
169:     KSPSetOperators(st->ksp,st->mat,st->mat,SAME_NONZERO_PATTERN);
170:     break;
171:   default:
172:     MatCopy(st->A, st->mat,SUBSET_NONZERO_PATTERN);
173:     if (newshift != 0.0) {
174:       alpha = -newshift;
175:       if (st->B) { MatAXPY(&alpha,st->B,st->mat,st->str); }
176:       else { MatShift(&alpha,st->mat); }
177:     }
178:     /* In the following line, the SAME_NONZERO_PATTERN flag has been used to
179:      * improve performance when solving a number of related eigenproblems */
180:     KSPSetOperators(st->ksp,st->mat,st->mat,SAME_NONZERO_PATTERN);
181:   }
182:   st->sigma = newshift;
183:   KSPSetUp(st->ksp);
184:   return(0);
185: }

187: EXTERN_C_BEGIN
190: PetscErrorCode STCreate_Sinvert(ST st)
191: {
193:   st->data                = 0;

195:   st->ops->apply          = STApply_Sinvert;
196:   st->ops->applyB         = STApplyB_Sinvert;
197:   st->ops->applynoB       = STApplyNoB_Sinvert;
198:   st->ops->postsolve      = STPost_Sinvert;
199:   st->ops->backtr         = STBackTransform_Sinvert;
200:   st->ops->setup          = STSetUp_Sinvert;
201:   st->ops->setshift       = STSetShift_Sinvert;
202:   st->ops->view           = STView_Default;
203: 
204:   st->checknullspace      = STCheckNullSpace_Default;

206:   return(0);
207: }
208: EXTERN_C_END