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