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: {
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 STApplyTranspose_Sinvert(ST st,Vec x,Vec y)
28: {
32: if (st->B) {
33: /* generalized eigenproblem: y = B^T (A - sB)^-T x */
34: STAssociatedKSPSolveTranspose(st,x,st->w);
35: MatMultTranspose(st->B,st->w,y);
36: }
37: else {
38: /* standard eigenproblem: y = (A - sI)^-T x */
39: STAssociatedKSPSolveTranspose(st,x,y);
40: }
41: return(0);
42: }
46: PetscErrorCode STApplyNoB_Sinvert(ST st,Vec x,Vec y)
47: {
51: STAssociatedKSPSolve(st,x,y);
52: return(0);
53: }
57: PetscErrorCode STApplyB_Sinvert(ST st,Vec x,Vec y)
58: {
62: if( st->B ) {
63: MatMult( st->B, x, y );
64: }
65: else {
66: VecCopy( x, y );
67: }
68: return(0);
69: }
73: PetscErrorCode STBackTransform_Sinvert(ST st,PetscScalar *eigr,PetscScalar *eigi)
74: {
75: #ifndef PETSC_USE_COMPLEX
76: PetscScalar t;
80: if (*eigi == 0) *eigr = 1.0 / *eigr + st->sigma;
81: else {
82: t = *eigr * *eigr + *eigi * *eigi;
83: *eigr = *eigr / t + st->sigma;
84: *eigi = - *eigi / t;
85: }
86: #else
89: *eigr = 1.0 / *eigr + st->sigma;
90: #endif
91: return(0);
92: }
96: PetscErrorCode STPostSolve_Sinvert(ST st)
97: {
101: if (st->shift_matrix == STMATMODE_INPLACE) {
102: if( st->B ) {
103: MatAXPY(st->A,st->sigma,st->B,st->str);
104: } else {
105: MatShift(st->A,st->sigma);
106: }
107: st->setupcalled = 0;
108: }
109: return(0);
110: }
114: PetscErrorCode STSetUp_Sinvert(ST st)
115: {
119:
120: if (st->mat) { MatDestroy(st->mat); }
122: switch (st->shift_matrix) {
123: case STMATMODE_INPLACE:
124: st->mat = PETSC_NULL;
125: if (st->sigma != 0.0) {
126: if (st->B) {
127: MatAXPY(st->A,-st->sigma,st->B,st->str);
128: } else {
129: MatShift(st->A,-st->sigma);
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->A,st->A,SAME_NONZERO_PATTERN);
135: break;
136: case STMATMODE_SHELL:
137: STMatShellCreate(st,&st->mat);
138: KSPSetOperators(st->ksp,st->mat,st->mat,DIFFERENT_NONZERO_PATTERN);
139: break;
140: default:
141: MatDuplicate(st->A,MAT_COPY_VALUES,&st->mat);
142: if (st->sigma != 0.0) {
143: if (st->B) {
144: MatAXPY(st->mat,-st->sigma,st->B,st->str);
145: } else {
146: MatShift(st->mat,-st->sigma);
147: }
148: }
149: /* In the following line, the SAME_NONZERO_PATTERN flag has been used to
150: * improve performance when solving a number of related eigenproblems */
151: KSPSetOperators(st->ksp,st->mat,st->mat,SAME_NONZERO_PATTERN);
152: }
153: KSPSetUp(st->ksp);
154: return(0);
155: }
159: PetscErrorCode STSetShift_Sinvert(ST st,PetscScalar newshift)
160: {
165: /* Nothing to be done if STSetUp has not been called yet */
166: if (!st->setupcalled) return(0);
168: switch (st->shift_matrix) {
169: case STMATMODE_INPLACE:
170: /* Undo previous operations */
171: if (st->sigma != 0.0) {
172: if (st->B) {
173: MatAXPY(st->A,st->sigma,st->B,st->str);
174: } else {
175: MatShift(st->A,st->sigma);
176: }
177: }
178: /* Apply new shift */
179: if (newshift != 0.0) {
180: if (st->B) {
181: MatAXPY(st->A,-newshift,st->B,st->str);
182: } else {
183: MatShift(st->A,-newshift);
184: }
185: }
186: KSPSetOperators(st->ksp,st->A,st->A,SAME_NONZERO_PATTERN);
187: break;
188: case STMATMODE_SHELL:
189: KSPSetOperators(st->ksp,st->mat,st->mat,SAME_NONZERO_PATTERN);
190: break;
191: default:
192: MatCopy(st->A, st->mat,SUBSET_NONZERO_PATTERN);
193: if (newshift != 0.0) {
194: if (st->B) {
195: MatAXPY(st->mat,-newshift,st->B,st->str);
196: } else {
197: MatShift(st->mat,-newshift);
198: }
199: }
200: /* In the following line, the SAME_NONZERO_PATTERN flag has been used to
201: * improve performance when solving a number of related eigenproblems */
202: KSPSetOperators(st->ksp,st->mat,st->mat,SAME_NONZERO_PATTERN);
203: }
204: st->sigma = newshift;
205: KSPSetUp(st->ksp);
206: return(0);
207: }
212: PetscErrorCode STCreate_Sinvert(ST st)
213: {
215: st->data = 0;
217: st->ops->apply = STApply_Sinvert;
218: st->ops->applyB = STApplyB_Sinvert;
219: st->ops->applynoB = STApplyNoB_Sinvert;
220: st->ops->applytrans = STApplyTranspose_Sinvert;
221: st->ops->postsolve = STPostSolve_Sinvert;
222: st->ops->backtr = STBackTransform_Sinvert;
223: st->ops->setup = STSetUp_Sinvert;
224: st->ops->setshift = STSetShift_Sinvert;
225: st->ops->view = STView_Default;
226:
227: st->checknullspace = STCheckNullSpace_Default;
229: return(0);
230: }