| 1619 |
slepc |
1 |
/*
|
|
|
2 |
SLEPc eigensolver: "davidson"
|
|
|
3 |
|
|
|
4 |
Some utils
|
|
|
5 |
|
| 2110 |
jroman |
6 |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
7 |
SLEPc - Scalable Library for Eigenvalue Problem Computations
|
| 2116 |
eromero |
8 |
Copyright (c) 2002-2010, Universidad Politecnica de Valencia, Spain
|
| 2110 |
jroman |
9 |
|
|
|
10 |
This file is part of SLEPc.
|
|
|
11 |
|
|
|
12 |
SLEPc is free software: you can redistribute it and/or modify it under the
|
|
|
13 |
terms of version 3 of the GNU Lesser General Public License as published by
|
|
|
14 |
the Free Software Foundation.
|
|
|
15 |
|
|
|
16 |
SLEPc is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
17 |
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
18 |
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
|
|
19 |
more details.
|
|
|
20 |
|
|
|
21 |
You should have received a copy of the GNU Lesser General Public License
|
|
|
22 |
along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
|
|
|
23 |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
| 1619 |
slepc |
24 |
*/
|
|
|
25 |
|
| 1985 |
eromero |
26 |
#include "davidson.h"
|
| 1619 |
slepc |
27 |
|
| 1764 |
eromero |
28 |
PetscErrorCode dvd_static_precond_PC_0(dvdDashboard *d, PetscInt i, Vec x,
|
|
|
29 |
Vec Px);
|
| 1736 |
eromero |
30 |
PetscErrorCode dvd_jacobi_precond_0(dvdDashboard *d, PetscInt i, Vec x, Vec Px);
|
| 1883 |
eromero |
31 |
PetscErrorCode dvd_precond_none(dvdDashboard *d, PetscInt i, Vec x, Vec Px);
|
| 2021 |
eromero |
32 |
PetscErrorCode dvd_improvex_precond_d(dvdDashboard *d);
|
| 1619 |
slepc |
33 |
|
|
|
34 |
typedef struct {
|
|
|
35 |
PC pc;
|
|
|
36 |
} dvdPCWrapper;
|
|
|
37 |
/*
|
|
|
38 |
Create a static preconditioner from a PC
|
|
|
39 |
*/
|
| 2019 |
eromero |
40 |
#undef __FUNCT__
|
|
|
41 |
#define __FUNCT__ "dvd_static_precond_PC"
|
| 1764 |
eromero |
42 |
PetscErrorCode dvd_static_precond_PC(dvdDashboard *d, dvdBlackboard *b, PC pc)
|
| 1619 |
slepc |
43 |
{
|
|
|
44 |
PetscErrorCode ierr;
|
|
|
45 |
dvdPCWrapper *dvdpc;
|
| 2004 |
eromero |
46 |
Mat P;
|
| 1997 |
eromero |
47 |
MatStructure str;
|
| 1619 |
slepc |
48 |
|
|
|
49 |
PetscFunctionBegin;
|
|
|
50 |
|
| 1764 |
eromero |
51 |
/* Setup the step */
|
|
|
52 |
if (b->state >= DVD_STATE_CONF) {
|
| 1883 |
eromero |
53 |
/* If the preconditioner is valid */
|
|
|
54 |
if (pc) {
|
| 1992 |
eromero |
55 |
ierr = PetscMalloc(sizeof(dvdPCWrapper), &dvdpc); CHKERRQ(ierr);
|
|
|
56 |
dvdpc->pc = pc;
|
| 2013 |
eromero |
57 |
ierr = PetscObjectReference((PetscObject)pc); CHKERRQ(ierr);
|
| 1992 |
eromero |
58 |
d->improvex_precond_data = dvdpc;
|
|
|
59 |
d->improvex_precond = dvd_static_precond_PC_0;
|
|
|
60 |
|
| 1997 |
eromero |
61 |
/* PC saves the matrix associated with the linear system, and it has to
|
|
|
62 |
be initialize to a valid matrix */
|
| 2004 |
eromero |
63 |
ierr = PCGetOperators(pc, PETSC_NULL, &P, &str); CHKERRQ(ierr);
|
| 2178 |
eromero |
64 |
ierr = PetscObjectReference((PetscObject)P); CHKERRQ(ierr);
|
| 2004 |
eromero |
65 |
ierr = PCSetOperators(pc, P, P, str); CHKERRQ(ierr);
|
| 2182 |
eromero |
66 |
ierr = MatDestroy(P); CHKERRQ(ierr);
|
| 1883 |
eromero |
67 |
ierr = PCSetUp(pc); CHKERRQ(ierr);
|
| 1867 |
eromero |
68 |
|
| 1992 |
eromero |
69 |
DVD_FL_ADD(d->destroyList, dvd_improvex_precond_d);
|
|
|
70 |
|
| 1883 |
eromero |
71 |
/* Else, use no preconditioner */
|
|
|
72 |
} else
|
|
|
73 |
d->improvex_precond = dvd_precond_none;
|
| 1764 |
eromero |
74 |
}
|
| 1619 |
slepc |
75 |
|
|
|
76 |
PetscFunctionReturn(0);
|
|
|
77 |
}
|
|
|
78 |
|
| 1992 |
eromero |
79 |
#undef __FUNCT__
|
|
|
80 |
#define __FUNCT__ "dvd_improvex_precond_d"
|
| 2021 |
eromero |
81 |
PetscErrorCode dvd_improvex_precond_d(dvdDashboard *d)
|
| 1992 |
eromero |
82 |
{
|
|
|
83 |
PetscErrorCode ierr;
|
| 2013 |
eromero |
84 |
dvdPCWrapper *dvdpc = (dvdPCWrapper*)d->improvex_precond_data;
|
| 1619 |
slepc |
85 |
|
| 1992 |
eromero |
86 |
PetscFunctionBegin;
|
|
|
87 |
|
|
|
88 |
/* Free local data */
|
| 2013 |
eromero |
89 |
if (dvdpc->pc) { ierr = PCDestroy(dvdpc->pc); CHKERRQ(ierr); }
|
| 1992 |
eromero |
90 |
ierr = PetscFree(d->improvex_precond_data); CHKERRQ(ierr);
|
|
|
91 |
d->improvex_precond_data = PETSC_NULL;
|
|
|
92 |
|
|
|
93 |
PetscFunctionReturn(0);
|
|
|
94 |
}
|
|
|
95 |
|
|
|
96 |
|
| 1764 |
eromero |
97 |
PetscErrorCode dvd_static_precond_PC_0(dvdDashboard *d, PetscInt i, Vec x,
|
|
|
98 |
Vec Px)
|
| 1619 |
slepc |
99 |
{
|
|
|
100 |
PetscErrorCode ierr;
|
| 1764 |
eromero |
101 |
dvdPCWrapper *dvdpc = (dvdPCWrapper*)d->improvex_precond_data;
|
| 1619 |
slepc |
102 |
|
|
|
103 |
PetscFunctionBegin;
|
|
|
104 |
|
|
|
105 |
ierr = PCApply(dvdpc->pc, x, Px); CHKERRQ(ierr);
|
|
|
106 |
|
|
|
107 |
PetscFunctionReturn(0);
|
|
|
108 |
}
|
|
|
109 |
|
|
|
110 |
typedef struct {
|
| 1736 |
eromero |
111 |
Vec diagA, diagB;
|
| 1619 |
slepc |
112 |
} dvdJacobiPrecond;
|
|
|
113 |
/*
|
| 1883 |
eromero |
114 |
Create the Jacobi preconditioner for Generalized Eigenproblems
|
| 1619 |
slepc |
115 |
*/
|
| 1736 |
eromero |
116 |
PetscErrorCode dvd_jacobi_precond(dvdDashboard *d, dvdBlackboard *b)
|
| 1619 |
slepc |
117 |
{
|
|
|
118 |
PetscErrorCode ierr;
|
|
|
119 |
dvdJacobiPrecond
|
|
|
120 |
*dvdjp;
|
| 1883 |
eromero |
121 |
PetscTruth t;
|
| 1619 |
slepc |
122 |
|
|
|
123 |
PetscFunctionBegin;
|
|
|
124 |
|
| 1883 |
eromero |
125 |
/* Check if the problem matrices support GetDiagonal */
|
|
|
126 |
ierr = MatHasOperation(d->A, MATOP_GET_DIAGONAL, &t); CHKERRQ(ierr);
|
| 2177 |
jroman |
127 |
if (t && d->B) {
|
| 1883 |
eromero |
128 |
ierr = MatHasOperation(d->B, MATOP_GET_DIAGONAL, &t); CHKERRQ(ierr);
|
|
|
129 |
}
|
|
|
130 |
|
| 1736 |
eromero |
131 |
/* Setting configuration constrains */
|
| 2177 |
jroman |
132 |
b->own_vecs+= t?( (d->B == 0)?1:2 ) : 0;
|
| 1619 |
slepc |
133 |
|
| 1736 |
eromero |
134 |
/* Setup the step */
|
|
|
135 |
if (b->state >= DVD_STATE_CONF) {
|
| 2177 |
jroman |
136 |
if (t) {
|
| 1883 |
eromero |
137 |
ierr = PetscMalloc(sizeof(dvdJacobiPrecond), &dvdjp); CHKERRQ(ierr);
|
|
|
138 |
dvdjp->diagA = *b->free_vecs; b->free_vecs++;
|
|
|
139 |
ierr = MatGetDiagonal(d->A,dvdjp->diagA); CHKERRQ(ierr);
|
|
|
140 |
if (d->B) {
|
|
|
141 |
dvdjp->diagB = *b->free_vecs; b->free_vecs++;
|
|
|
142 |
ierr = MatGetDiagonal(d->B, dvdjp->diagB); CHKERRQ(ierr);
|
|
|
143 |
} else
|
|
|
144 |
dvdjp->diagB = 0;
|
|
|
145 |
d->improvex_precond_data = dvdjp;
|
|
|
146 |
d->improvex_precond = dvd_jacobi_precond_0;
|
|
|
147 |
|
| 1992 |
eromero |
148 |
DVD_FL_ADD(d->destroyList, dvd_improvex_precond_d);
|
|
|
149 |
|
| 1883 |
eromero |
150 |
/* Else, use no preconditioner */
|
| 1736 |
eromero |
151 |
} else
|
| 1883 |
eromero |
152 |
d->improvex_precond = dvd_precond_none;
|
|
|
153 |
}
|
| 1736 |
eromero |
154 |
|
| 1619 |
slepc |
155 |
PetscFunctionReturn(0);
|
|
|
156 |
}
|
|
|
157 |
|
| 1736 |
eromero |
158 |
PetscErrorCode dvd_jacobi_precond_0(dvdDashboard *d, PetscInt i, Vec x, Vec Px)
|
| 1619 |
slepc |
159 |
{
|
|
|
160 |
PetscErrorCode ierr;
|
|
|
161 |
dvdJacobiPrecond
|
| 1736 |
eromero |
162 |
*dvdjp = (dvdJacobiPrecond*)d->improvex_precond_data;
|
| 1619 |
slepc |
163 |
|
|
|
164 |
PetscFunctionBegin;
|
|
|
165 |
|
|
|
166 |
/* Compute inv(D - eig)*x */
|
| 1736 |
eromero |
167 |
if (dvdjp->diagB == 0) {
|
|
|
168 |
/* Px <- diagA - l */
|
|
|
169 |
ierr = VecCopy(dvdjp->diagA, Px); CHKERRQ(ierr);
|
|
|
170 |
ierr = VecShift(Px, -d->eigr[i]); CHKERRQ(ierr);
|
|
|
171 |
} else {
|
|
|
172 |
/* Px <- diagA - l*diagB */
|
|
|
173 |
ierr = VecWAXPY(Px, -d->eigr[i], dvdjp->diagB, dvdjp->diagA);
|
|
|
174 |
CHKERRQ(ierr);
|
|
|
175 |
}
|
| 1619 |
slepc |
176 |
|
|
|
177 |
/* Px(i) <- x/Px(i) */
|
|
|
178 |
ierr = VecPointwiseDivide(Px, x, Px); CHKERRQ(ierr);
|
|
|
179 |
|
|
|
180 |
PetscFunctionReturn(0);
|
|
|
181 |
}
|
|
|
182 |
|
| 1883 |
eromero |
183 |
/*
|
|
|
184 |
Create a trivial preconditioner
|
|
|
185 |
*/
|
|
|
186 |
PetscErrorCode dvd_precond_none(dvdDashboard *d, PetscInt i, Vec x, Vec Px)
|
|
|
187 |
{
|
|
|
188 |
PetscErrorCode ierr;
|
| 1743 |
eromero |
189 |
|
| 1883 |
eromero |
190 |
PetscFunctionBegin;
|
|
|
191 |
|
|
|
192 |
ierr = VecCopy(x, Px); CHKERRQ(ierr);
|
|
|
193 |
|
|
|
194 |
PetscFunctionReturn(0);
|
|
|
195 |
}
|
|
|
196 |
|
|
|
197 |
|
| 1743 |
eromero |
198 |
/*
|
|
|
199 |
Use of PETSc profiler functions
|
|
|
200 |
*/
|
|
|
201 |
|
|
|
202 |
/* Define stages */
|
|
|
203 |
#define DVD_STAGE_INITV 0
|
|
|
204 |
#define DVD_STAGE_NEWITER 1
|
|
|
205 |
#define DVD_STAGE_CALCPAIRS 2
|
|
|
206 |
#define DVD_STAGE_IMPROVEX 3
|
|
|
207 |
#define DVD_STAGE_UPDATEV 4
|
|
|
208 |
#define DVD_STAGE_ORTHV 5
|
|
|
209 |
|
| 2021 |
eromero |
210 |
PetscErrorCode dvd_profiler_d(dvdDashboard *d);
|
| 1992 |
eromero |
211 |
|
| 1743 |
eromero |
212 |
typedef struct {
|
| 2021 |
eromero |
213 |
PetscErrorCode (*old_initV)(struct _dvdDashboard*);
|
|
|
214 |
PetscErrorCode (*old_calcPairs)(struct _dvdDashboard*);
|
|
|
215 |
PetscErrorCode (*old_improveX)(struct _dvdDashboard*, Vec *D,
|
|
|
216 |
PetscInt max_size_D, PetscInt r_s,
|
|
|
217 |
PetscInt r_e, PetscInt *size_D);
|
|
|
218 |
PetscErrorCode (*old_updateV)(struct _dvdDashboard*);
|
|
|
219 |
PetscErrorCode (*old_orthV)(struct _dvdDashboard*);
|
| 1743 |
eromero |
220 |
} DvdProfiler;
|
|
|
221 |
|
| 1978 |
eromero |
222 |
PetscLogStage stages[6] = {0,0,0,0,0,0};
|
|
|
223 |
|
| 1743 |
eromero |
224 |
/*** Other things ****/
|
|
|
225 |
|
| 1745 |
eromero |
226 |
#undef __FUNCT__
|
|
|
227 |
#define __FUNCT__ "dvd_prof_init"
|
| 1992 |
eromero |
228 |
PetscErrorCode dvd_prof_init() {
|
| 1743 |
eromero |
229 |
PetscErrorCode ierr;
|
|
|
230 |
|
| 1745 |
eromero |
231 |
PetscFunctionBegin;
|
|
|
232 |
|
| 1978 |
eromero |
233 |
if (!stages[0]) {
|
|
|
234 |
ierr = PetscLogStageRegister("Dvd_step_initV", &stages[DVD_STAGE_INITV]);
|
|
|
235 |
CHKERRQ(ierr);
|
|
|
236 |
ierr = PetscLogStageRegister("Dvd_step_calcPairs",
|
|
|
237 |
&stages[DVD_STAGE_CALCPAIRS]); CHKERRQ(ierr);
|
|
|
238 |
ierr = PetscLogStageRegister("Dvd_step_improveX",
|
|
|
239 |
&stages[DVD_STAGE_IMPROVEX]); CHKERRQ(ierr);
|
|
|
240 |
ierr = PetscLogStageRegister("Dvd_step_updateV",
|
|
|
241 |
&stages[DVD_STAGE_UPDATEV]); CHKERRQ(ierr);
|
|
|
242 |
ierr = PetscLogStageRegister("Dvd_step_orthV",
|
|
|
243 |
&stages[DVD_STAGE_ORTHV]); CHKERRQ(ierr);
|
|
|
244 |
}
|
|
|
245 |
|
| 1743 |
eromero |
246 |
PetscFunctionReturn(0);
|
|
|
247 |
}
|
|
|
248 |
|
| 2021 |
eromero |
249 |
PetscErrorCode dvd_initV_prof(dvdDashboard* d) {
|
| 1992 |
eromero |
250 |
DvdProfiler *p = (DvdProfiler*)d->prof_data;
|
| 2021 |
eromero |
251 |
PetscErrorCode ierr;
|
| 1743 |
eromero |
252 |
|
|
|
253 |
PetscFunctionBegin;
|
|
|
254 |
|
| 1978 |
eromero |
255 |
PetscLogStagePush(stages[DVD_STAGE_INITV]);
|
| 2021 |
eromero |
256 |
ierr = p->old_initV(d); CHKERRQ(ierr);
|
| 1743 |
eromero |
257 |
PetscLogStagePop();
|
|
|
258 |
|
| 2021 |
eromero |
259 |
PetscFunctionReturn(0);
|
| 1743 |
eromero |
260 |
}
|
|
|
261 |
|
| 2021 |
eromero |
262 |
PetscErrorCode dvd_calcPairs_prof(dvdDashboard* d) {
|
| 1992 |
eromero |
263 |
DvdProfiler *p = (DvdProfiler*)d->prof_data;
|
| 2021 |
eromero |
264 |
PetscErrorCode ierr;
|
| 1743 |
eromero |
265 |
|
|
|
266 |
PetscFunctionBegin;
|
|
|
267 |
|
| 1978 |
eromero |
268 |
PetscLogStagePush(stages[DVD_STAGE_CALCPAIRS]);
|
| 2021 |
eromero |
269 |
ierr = p->old_calcPairs(d); CHKERRQ(ierr);
|
| 1743 |
eromero |
270 |
PetscLogStagePop();
|
|
|
271 |
|
| 2021 |
eromero |
272 |
PetscFunctionReturn(0);
|
| 1743 |
eromero |
273 |
}
|
|
|
274 |
|
| 2021 |
eromero |
275 |
PetscErrorCode dvd_improveX_prof(dvdDashboard* d, Vec *D, PetscInt max_size_D,
|
| 1743 |
eromero |
276 |
PetscInt r_s, PetscInt r_e, PetscInt *size_D) {
|
| 1992 |
eromero |
277 |
DvdProfiler *p = (DvdProfiler*)d->prof_data;
|
| 2021 |
eromero |
278 |
PetscErrorCode ierr;
|
| 1743 |
eromero |
279 |
|
|
|
280 |
PetscFunctionBegin;
|
|
|
281 |
|
| 1978 |
eromero |
282 |
PetscLogStagePush(stages[DVD_STAGE_IMPROVEX]);
|
| 2021 |
eromero |
283 |
ierr = p->old_improveX(d, D, max_size_D, r_s, r_e, size_D); CHKERRQ(ierr);
|
| 1743 |
eromero |
284 |
PetscLogStagePop();
|
|
|
285 |
|
| 2021 |
eromero |
286 |
PetscFunctionReturn(0);
|
| 1743 |
eromero |
287 |
}
|
|
|
288 |
|
| 2021 |
eromero |
289 |
PetscErrorCode dvd_updateV_prof(dvdDashboard *d) {
|
| 1992 |
eromero |
290 |
DvdProfiler *p = (DvdProfiler*)d->prof_data;
|
| 2021 |
eromero |
291 |
PetscErrorCode ierr;
|
| 1743 |
eromero |
292 |
|
|
|
293 |
PetscFunctionBegin;
|
|
|
294 |
|
| 1978 |
eromero |
295 |
PetscLogStagePush(stages[DVD_STAGE_UPDATEV]);
|
| 2021 |
eromero |
296 |
ierr = p->old_updateV(d); CHKERRQ(ierr);
|
| 1743 |
eromero |
297 |
PetscLogStagePop();
|
|
|
298 |
|
| 2021 |
eromero |
299 |
PetscFunctionReturn(0);
|
| 1743 |
eromero |
300 |
}
|
|
|
301 |
|
| 2021 |
eromero |
302 |
PetscErrorCode dvd_orthV_prof(dvdDashboard *d) {
|
| 1992 |
eromero |
303 |
DvdProfiler *p = (DvdProfiler*)d->prof_data;
|
| 2021 |
eromero |
304 |
PetscErrorCode ierr;
|
| 1743 |
eromero |
305 |
|
|
|
306 |
PetscFunctionBegin;
|
|
|
307 |
|
| 1978 |
eromero |
308 |
PetscLogStagePush(stages[DVD_STAGE_ORTHV]);
|
| 2021 |
eromero |
309 |
ierr = p->old_orthV(d); CHKERRQ(ierr);
|
| 1743 |
eromero |
310 |
PetscLogStagePop();
|
|
|
311 |
|
| 2021 |
eromero |
312 |
PetscFunctionReturn(0);
|
| 1743 |
eromero |
313 |
}
|
|
|
314 |
|
| 1992 |
eromero |
315 |
#undef __FUNCT__
|
|
|
316 |
#define __FUNCT__ "dvd_profiler"
|
|
|
317 |
PetscErrorCode dvd_profiler(dvdDashboard *d, dvdBlackboard *b)
|
|
|
318 |
{
|
|
|
319 |
PetscErrorCode ierr;
|
|
|
320 |
DvdProfiler *p;
|
| 1743 |
eromero |
321 |
|
|
|
322 |
PetscFunctionBegin;
|
|
|
323 |
|
| 1992 |
eromero |
324 |
/* Setup the step */
|
|
|
325 |
if (b->state >= DVD_STATE_CONF) {
|
|
|
326 |
if (d->prof_data) {
|
|
|
327 |
ierr = PetscFree(d->prof_data); CHKERRQ(ierr);
|
|
|
328 |
}
|
|
|
329 |
ierr = PetscMalloc(sizeof(DvdProfiler), &p); CHKERRQ(ierr);
|
|
|
330 |
d->prof_data = p;
|
|
|
331 |
p->old_initV = d->initV; d->initV = dvd_initV_prof;
|
|
|
332 |
p->old_calcPairs = d->calcPairs; d->calcPairs = dvd_calcPairs_prof;
|
|
|
333 |
p->old_improveX = d->improveX; d->improveX = dvd_improveX_prof;
|
|
|
334 |
p->old_updateV = d->updateV; d->updateV = dvd_updateV_prof;
|
|
|
335 |
|
|
|
336 |
DVD_FL_ADD(d->destroyList, dvd_profiler_d);
|
|
|
337 |
}
|
|
|
338 |
|
|
|
339 |
PetscFunctionReturn(0);
|
| 1743 |
eromero |
340 |
}
|
|
|
341 |
|
| 1992 |
eromero |
342 |
#undef __FUNCT__
|
|
|
343 |
#define __FUNCT__ "dvd_profiler_d"
|
| 2021 |
eromero |
344 |
PetscErrorCode dvd_profiler_d(dvdDashboard *d)
|
| 1992 |
eromero |
345 |
{
|
|
|
346 |
PetscErrorCode ierr;
|
|
|
347 |
DvdProfiler *p = (DvdProfiler*)d->prof_data;
|
|
|
348 |
|
|
|
349 |
PetscFunctionBegin;
|
|
|
350 |
|
|
|
351 |
/* Free local data */
|
|
|
352 |
ierr = PetscFree(p); CHKERRQ(ierr);
|
|
|
353 |
d->prof_data = PETSC_NULL;
|
|
|
354 |
|
|
|
355 |
PetscFunctionReturn(0);
|
|
|
356 |
}
|
|
|
357 |
|
|
|
358 |
|
|
|
359 |
|
| 1795 |
eromero |
360 |
/*
|
|
|
361 |
Configure the harmonics.
|
|
|
362 |
switch(mode) {
|
|
|
363 |
DVD_HARM_RR: harmonic RR
|
|
|
364 |
DVD_HARM_RRR: relative harmonic RR
|
|
|
365 |
DVD_HARM_REIGS: rightmost eigenvalues
|
|
|
366 |
DVD_HARM_LEIGS: largest eigenvalues
|
|
|
367 |
}
|
|
|
368 |
fixedTarged, if true use the target instead of the best eigenvalue
|
|
|
369 |
target, the fixed target to be used
|
|
|
370 |
*/
|
|
|
371 |
typedef struct {
|
|
|
372 |
PetscScalar
|
|
|
373 |
Wa, Wb, /* span{W} = span{Wa*AV - Wb*BV} */
|
|
|
374 |
Pa, Pb; /* H=W'*(Pa*AV - Pb*BV), G=W'*(Wa*AV - Wb*BV) */
|
|
|
375 |
PetscTruth
|
|
|
376 |
withTarget;
|
|
|
377 |
HarmType_t
|
|
|
378 |
mode;
|
| 1883 |
eromero |
379 |
|
|
|
380 |
/* old values of eps */
|
|
|
381 |
EPSWhich
|
|
|
382 |
old_which;
|
|
|
383 |
PetscErrorCode
|
|
|
384 |
(*old_which_func)(EPS,PetscScalar,PetscScalar,PetscScalar,PetscScalar,
|
|
|
385 |
PetscInt*,void*);
|
|
|
386 |
void
|
|
|
387 |
*old_which_ctx;
|
| 1795 |
eromero |
388 |
} dvdHarmonic;
|
|
|
389 |
|
| 1883 |
eromero |
390 |
PetscErrorCode dvd_harm_start(dvdDashboard *d);
|
|
|
391 |
PetscErrorCode dvd_harm_end(dvdDashboard *d);
|
| 2021 |
eromero |
392 |
PetscErrorCode dvd_harm_d(dvdDashboard *d);
|
| 1795 |
eromero |
393 |
PetscErrorCode dvd_harm_transf(dvdHarmonic *dvdh, PetscScalar t);
|
|
|
394 |
PetscErrorCode dvd_harm_updateW(dvdDashboard *d);
|
|
|
395 |
PetscErrorCode dvd_harm_proj(dvdDashboard *d);
|
| 1883 |
eromero |
396 |
PetscErrorCode dvd_harm_sort(EPS eps, PetscScalar ar, PetscScalar ai,
|
|
|
397 |
PetscScalar br, PetscScalar bi, PetscInt *r,
|
|
|
398 |
void *ctx);
|
|
|
399 |
PetscErrorCode dvd_harm_eigs_trans(dvdDashboard *d);
|
| 1795 |
eromero |
400 |
|
|
|
401 |
PetscErrorCode dvd_harm_conf(dvdDashboard *d, dvdBlackboard *b,
|
|
|
402 |
HarmType_t mode, PetscTruth fixedTarget,
|
|
|
403 |
PetscScalar t)
|
|
|
404 |
{
|
|
|
405 |
PetscErrorCode ierr;
|
|
|
406 |
dvdHarmonic *dvdh;
|
|
|
407 |
|
|
|
408 |
PetscFunctionBegin;
|
|
|
409 |
|
| 1883 |
eromero |
410 |
/* Set the problem to GNHEP */
|
|
|
411 |
// TODO: d->G maybe is upper triangular due to biorthogonality of V and W
|
|
|
412 |
d->sEP = d->sA = d->sB = 0;
|
|
|
413 |
|
| 1795 |
eromero |
414 |
/* Setup the step */
|
|
|
415 |
if (b->state >= DVD_STATE_CONF) {
|
|
|
416 |
ierr = PetscMalloc(sizeof(dvdHarmonic), &dvdh); CHKERRQ(ierr);
|
|
|
417 |
dvdh->withTarget = fixedTarget;
|
|
|
418 |
dvdh->mode = mode;
|
| 2177 |
jroman |
419 |
if (fixedTarget) dvd_harm_transf(dvdh, t);
|
| 1795 |
eromero |
420 |
d->calcpairs_W_data = dvdh;
|
|
|
421 |
d->calcpairs_W = dvd_harm_updateW;
|
|
|
422 |
d->calcpairs_proj_trans = dvd_harm_proj;
|
| 1883 |
eromero |
423 |
d->calcpairs_eigs_trans = dvd_harm_eigs_trans;
|
|
|
424 |
|
|
|
425 |
DVD_FL_ADD(d->startList, dvd_harm_start);
|
|
|
426 |
DVD_FL_ADD(d->endList, dvd_harm_end);
|
| 1992 |
eromero |
427 |
DVD_FL_ADD(d->destroyList, dvd_harm_d);
|
| 1795 |
eromero |
428 |
}
|
|
|
429 |
|
|
|
430 |
PetscFunctionReturn(0);
|
|
|
431 |
}
|
|
|
432 |
|
| 1883 |
eromero |
433 |
|
|
|
434 |
#undef __FUNCT__
|
| 1992 |
eromero |
435 |
#define __FUNCT__ "dvd_harm_d"
|
| 2021 |
eromero |
436 |
PetscErrorCode dvd_harm_d(dvdDashboard *d)
|
| 1992 |
eromero |
437 |
{
|
|
|
438 |
PetscErrorCode ierr;
|
|
|
439 |
|
|
|
440 |
PetscFunctionBegin;
|
|
|
441 |
|
|
|
442 |
/* Free local data */
|
|
|
443 |
ierr = PetscFree(d->calcpairs_W_data); CHKERRQ(ierr);
|
|
|
444 |
d->calcpairs_W_data = PETSC_NULL;
|
|
|
445 |
|
|
|
446 |
PetscFunctionReturn(0);
|
|
|
447 |
}
|
|
|
448 |
|
|
|
449 |
|
|
|
450 |
#undef __FUNCT__
|
| 1883 |
eromero |
451 |
#define __FUNCT__ "dvd_harm_start"
|
|
|
452 |
PetscErrorCode dvd_harm_start(dvdDashboard *d)
|
|
|
453 |
{
|
|
|
454 |
dvdHarmonic *data = (dvdHarmonic*)d->calcpairs_W_data;
|
|
|
455 |
|
|
|
456 |
PetscFunctionBegin;
|
|
|
457 |
|
|
|
458 |
/* Overload the eigenpairs selection routine */
|
| 2096 |
eromero |
459 |
data->old_which = d->eps->which;
|
|
|
460 |
data->old_which_func = d->eps->which_func;
|
|
|
461 |
data->old_which_ctx = d->eps->which_ctx;
|
| 1975 |
eromero |
462 |
d->eps->which = EPS_WHICH_USER;
|
| 1883 |
eromero |
463 |
d->eps->which_func = dvd_harm_sort;
|
|
|
464 |
d->eps->which_ctx = data;
|
|
|
465 |
|
|
|
466 |
PetscFunctionReturn(0);
|
|
|
467 |
}
|
|
|
468 |
|
|
|
469 |
|
|
|
470 |
#undef __FUNCT__
|
|
|
471 |
#define __FUNCT__ "dvd_harm_end"
|
|
|
472 |
PetscErrorCode dvd_harm_end(dvdDashboard *d)
|
|
|
473 |
{
|
|
|
474 |
dvdHarmonic *data = (dvdHarmonic*)d->calcpairs_W_data;
|
|
|
475 |
|
|
|
476 |
PetscFunctionBegin;
|
|
|
477 |
|
|
|
478 |
/* Restore the eigenpairs selection routine */
|
|
|
479 |
d->eps->which = data->old_which;
|
|
|
480 |
d->eps->which_func = data->old_which_func;
|
|
|
481 |
d->eps->which_ctx = data->old_which_ctx;
|
|
|
482 |
|
|
|
483 |
PetscFunctionReturn(0);
|
|
|
484 |
}
|
|
|
485 |
|
|
|
486 |
|
| 1795 |
eromero |
487 |
PetscErrorCode dvd_harm_transf(dvdHarmonic *dvdh, PetscScalar t)
|
|
|
488 |
{
|
|
|
489 |
PetscFunctionBegin;
|
|
|
490 |
|
|
|
491 |
switch(dvdh->mode) {
|
|
|
492 |
case DVD_HARM_RR: /* harmonic RR */
|
| 1883 |
eromero |
493 |
dvdh->Wa = 1.0; dvdh->Wb = t; dvdh->Pa = 0.0; dvdh->Pb = -1.0; break;
|
| 1795 |
eromero |
494 |
case DVD_HARM_RRR: /* relative harmonic RR */
|
|
|
495 |
dvdh->Wa = 1.0; dvdh->Wb = t; dvdh->Pa = 1.0; dvdh->Pb = 0.0; break;
|
|
|
496 |
case DVD_HARM_REIGS: /* rightmost eigenvalues */
|
| 1883 |
eromero |
497 |
dvdh->Wa = 1.0; dvdh->Wb = t; dvdh->Pa = 1.0; dvdh->Pb = -PetscConj(t);
|
|
|
498 |
break;
|
| 1795 |
eromero |
499 |
case DVD_HARM_LEIGS: /* largest eigenvalues */
|
| 1883 |
eromero |
500 |
dvdh->Wa = 0.0; dvdh->Wb = 1.0; dvdh->Pa = 1.0; dvdh->Pb = 0.0; break;
|
|
|
501 |
case DVD_HARM_NONE:
|
|
|
502 |
default:
|
| 2214 |
jroman |
503 |
SETERRQ(PETSC_COMM_WORLD,1, "Harmonic type not supported");
|
| 1795 |
eromero |
504 |
}
|
|
|
505 |
|
| 2035 |
eromero |
506 |
/* Check the transformation does not change the sign of the imaginary part */
|
|
|
507 |
#if !defined(PETSC_USE_COMPLEX)
|
|
|
508 |
if (dvdh->Pb*dvdh->Wa - dvdh->Wb*dvdh->Pa < 0.0)
|
|
|
509 |
dvdh->Pa*= -1.0, dvdh->Pb*= -1.0;
|
|
|
510 |
#endif
|
|
|
511 |
|
| 1795 |
eromero |
512 |
PetscFunctionReturn(0);
|
|
|
513 |
}
|
|
|
514 |
|
|
|
515 |
PetscErrorCode dvd_harm_updateW(dvdDashboard *d)
|
|
|
516 |
{
|
|
|
517 |
dvdHarmonic *data = (dvdHarmonic*)d->calcpairs_W_data;
|
|
|
518 |
PetscErrorCode ierr;
|
|
|
519 |
PetscInt i;
|
|
|
520 |
|
|
|
521 |
PetscFunctionBegin;
|
|
|
522 |
|
|
|
523 |
/* Update the target if it is necessary */
|
| 2177 |
jroman |
524 |
if (!data->withTarget) dvd_harm_transf(data, d->eigr[0]);
|
| 1795 |
eromero |
525 |
|
|
|
526 |
for(i=d->V_new_s; i<d->V_new_e; i++) {
|
| 1883 |
eromero |
527 |
/* W(i) <- Wa*AV(i) - Wb*BV(i) */
|
| 1820 |
eromero |
528 |
ierr = VecCopy(d->AV[i], d->W[i]); CHKERRQ(ierr);
|
| 1883 |
eromero |
529 |
ierr = VecAXPBY(d->W[i], -data->Wb, data->Wa, (d->BV?d->BV:d->V)[i]);
|
|
|
530 |
CHKERRQ(ierr);
|
| 1795 |
eromero |
531 |
}
|
|
|
532 |
|
|
|
533 |
PetscFunctionReturn(0);
|
|
|
534 |
}
|
|
|
535 |
|
|
|
536 |
PetscErrorCode dvd_harm_proj(dvdDashboard *d)
|
|
|
537 |
{
|
|
|
538 |
dvdHarmonic *data = (dvdHarmonic*)d->calcpairs_W_data;
|
|
|
539 |
PetscInt i,j;
|
|
|
540 |
|
|
|
541 |
PetscFunctionBegin;
|
|
|
542 |
|
|
|
543 |
if (d->sH != d->sG) {
|
| 2214 |
jroman |
544 |
SETERRQ(PETSC_COMM_WORLD,1,"Projected matrices H and G must have the same structure");
|
| 1795 |
eromero |
545 |
PetscFunctionReturn(1);
|
|
|
546 |
}
|
|
|
547 |
|
|
|
548 |
/* [H G] <- [Pa*H - Pb*G, Wa*H - Wb*G] */
|
|
|
549 |
if (DVD_ISNOT(d->sH,DVD_MAT_LTRIANG)) /* Upper triangular part */
|
|
|
550 |
for(i=d->V_new_s; i<d->V_new_e; i++)
|
|
|
551 |
for(j=0; j<=i; j++) {
|
|
|
552 |
PetscScalar h = d->H[d->ldH*i+j], g = d->G[d->ldH*i+j];
|
|
|
553 |
d->H[d->ldH*i+j] = data->Pa*h - data->Pb*g;
|
|
|
554 |
d->G[d->ldH*i+j] = data->Wa*h - data->Wb*g;
|
|
|
555 |
}
|
|
|
556 |
if (DVD_ISNOT(d->sH,DVD_MAT_UTRIANG)) /* Lower triangular part */
|
|
|
557 |
for(i=0; i<d->V_new_e; i++)
|
| 1883 |
eromero |
558 |
for(j=PetscMax(d->V_new_s,i+(DVD_ISNOT(d->sH,DVD_MAT_LTRIANG)?1:0));
|
|
|
559 |
j<d->V_new_e; j++) {
|
| 1795 |
eromero |
560 |
PetscScalar h = d->H[d->ldH*i+j], g = d->G[d->ldH*i+j];
|
|
|
561 |
d->H[d->ldH*i+j] = data->Pa*h - data->Pb*g;
|
|
|
562 |
d->G[d->ldH*i+j] = data->Wa*h - data->Wb*g;
|
|
|
563 |
}
|
|
|
564 |
|
|
|
565 |
PetscFunctionReturn(0);
|
|
|
566 |
}
|
|
|
567 |
|
| 1883 |
eromero |
568 |
PetscErrorCode dvd_harm_backtrans(dvdHarmonic *data, PetscScalar *ar,
|
|
|
569 |
PetscScalar *ai)
|
|
|
570 |
{
|
| 1990 |
eromero |
571 |
PetscScalar xr;
|
|
|
572 |
#if !defined(PETSC_USE_COMPLEX)
|
|
|
573 |
PetscScalar xi, k;
|
|
|
574 |
#endif
|
|
|
575 |
|
| 1883 |
eromero |
576 |
PetscFunctionBegin;
|
| 2214 |
jroman |
577 |
PetscValidPointer(ar,2);
|
| 1990 |
eromero |
578 |
xr = *ar;
|
|
|
579 |
#if !defined(PETSC_USE_COMPLEX)
|
| 2214 |
jroman |
580 |
PetscValidPointer(ai,3);
|
| 1990 |
eromero |
581 |
xi = *ai;
|
|
|
582 |
|
|
|
583 |
if (xi != 0.0) {
|
|
|
584 |
k = (data->Pa - data->Wa*xr)*(data->Pa - data->Wa*xr) +
|
|
|
585 |
data->Wa*data->Wa*xi*xi;
|
|
|
586 |
*ar = (data->Pb*data->Pa - (data->Pb*data->Wa + data->Wb*data->Pa)*xr +
|
|
|
587 |
data->Wb*data->Wa*(xr*xr + xi*xi))/k;
|
|
|
588 |
*ai = (data->Pb*data->Wa - data->Wb*data->Pa)*xi/k;
|
|
|
589 |
} else
|
|
|
590 |
#endif
|
|
|
591 |
*ar = (data->Pb - data->Wb*xr) / (data->Pa - data->Wa*xr);
|
|
|
592 |
|
| 1883 |
eromero |
593 |
PetscFunctionReturn(0);
|
|
|
594 |
}
|
|
|
595 |
|
|
|
596 |
|
|
|
597 |
PetscErrorCode dvd_harm_sort(EPS eps, PetscScalar ar, PetscScalar ai,
|
|
|
598 |
PetscScalar br, PetscScalar bi, PetscInt *r,
|
|
|
599 |
void *ctx)
|
|
|
600 |
{
|
|
|
601 |
dvdHarmonic *data = (dvdHarmonic*)ctx;
|
|
|
602 |
PetscErrorCode ierr;
|
|
|
603 |
|
|
|
604 |
PetscFunctionBegin;
|
|
|
605 |
|
|
|
606 |
/* Back-transform the harmonic values */
|
|
|
607 |
dvd_harm_backtrans(data, &ar, &ai);
|
|
|
608 |
dvd_harm_backtrans(data, &br, &bi);
|
|
|
609 |
|
|
|
610 |
/* Compare values using the user options for the eigenpairs selection */
|
|
|
611 |
eps->which = data->old_which;
|
|
|
612 |
eps->which_func = data->old_which_func;
|
|
|
613 |
eps->which_ctx = data->old_which_ctx;
|
|
|
614 |
ierr = EPSCompareEigenvalues(eps, ar, ai, br, bi, r); CHKERRQ(ierr);
|
|
|
615 |
|
|
|
616 |
/* Restore the eps values */
|
| 1975 |
eromero |
617 |
eps->which = EPS_WHICH_USER;
|
| 1883 |
eromero |
618 |
eps->which_func = dvd_harm_sort;
|
|
|
619 |
eps->which_ctx = data;
|
|
|
620 |
|
|
|
621 |
PetscFunctionReturn(0);
|
|
|
622 |
}
|
|
|
623 |
|
|
|
624 |
PetscErrorCode dvd_harm_eigs_trans(dvdDashboard *d)
|
|
|
625 |
{
|
|
|
626 |
dvdHarmonic *data = (dvdHarmonic*)d->calcpairs_W_data;
|
|
|
627 |
PetscInt i;
|
|
|
628 |
|
|
|
629 |
PetscFunctionBegin;
|
|
|
630 |
|
|
|
631 |
for(i=0; i<d->size_H; i++)
|
|
|
632 |
dvd_harm_backtrans(data, &d->eigr[i], &d->eigi[i]);
|
|
|
633 |
|
|
|
634 |
PetscFunctionReturn(0);
|
|
|
635 |
}
|
|
|
636 |
|
|
|
637 |
|