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