| 1619 |
slepc |
1 |
/*
|
|
|
2 |
SLEPc eigensolver: "davidson"
|
|
|
3 |
|
|
|
4 |
Step: improve the eigenvectors X
|
|
|
5 |
|
| 2110 |
jroman |
6 |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
7 |
SLEPc - Scalable Library for Eigenvalue Problem Computations
|
| 2575 |
eromero |
8 |
Copyright (c) 2002-2011, Universitat 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"
|
| 2283 |
jroman |
27 |
#include <slepcvec.h>
|
| 2605 |
eromero |
28 |
#include <slepcblaslapack.h>
|
| 1619 |
slepc |
29 |
|
| 2021 |
eromero |
30 |
PetscErrorCode dvd_improvex_PfuncV(dvdDashboard *d, void *funcV, Vec *D,
|
|
|
31 |
PetscInt max_size_D, PetscInt r_s, PetscInt r_e, Vec *auxV,
|
|
|
32 |
PetscScalar *auxS);
|
| 1867 |
eromero |
33 |
PetscErrorCode dvd_matmult_jd(Mat A, Vec in, Vec out);
|
| 1960 |
eromero |
34 |
PetscErrorCode dvd_matgetvecs_jd(Mat A, Vec *right, Vec *left);
|
| 2021 |
eromero |
35 |
PetscErrorCode dvd_improvex_jd_d(dvdDashboard *d);
|
| 2244 |
eromero |
36 |
PetscErrorCode dvd_improvex_jd_start(dvdDashboard *d);
|
|
|
37 |
PetscErrorCode dvd_improvex_jd_end(dvdDashboard *d);
|
| 2021 |
eromero |
38 |
PetscErrorCode dvd_improvex_jd_gen(dvdDashboard *d, Vec *D,
|
|
|
39 |
PetscInt max_size_D, PetscInt r_s,
|
|
|
40 |
PetscInt r_e, PetscInt *size_D);
|
| 2605 |
eromero |
41 |
PetscErrorCode dvd_improvex_jd_proj_cuv(dvdDashboard *d, PetscInt i_s,
|
|
|
42 |
PetscInt i_e, Vec **u, Vec **v, Vec *kr, Vec **auxV, PetscScalar **auxS,
|
|
|
43 |
PetscScalar *theta, PetscScalar *thetai, PetscScalar *pX, PetscScalar *pY,
|
|
|
44 |
PetscInt ld);
|
|
|
45 |
PetscErrorCode dvd_improvex_jd_proj_uv_KXX(dvdDashboard *d, PetscInt i_s,
|
|
|
46 |
PetscInt i_e, Vec *u, Vec *v, Vec *kr, Vec *auxV, PetscScalar *theta,
|
| 1980 |
eromero |
47 |
PetscScalar *thetai, PetscScalar *pX, PetscScalar *pY, PetscInt ld);
|
| 2396 |
eromero |
48 |
PetscErrorCode dvd_improvex_jd_proj_uv_KZX(dvdDashboard *d, PetscInt i_s,
|
| 2605 |
eromero |
49 |
PetscInt i_e, Vec *u, Vec *v, Vec *kr, Vec *auxV, PetscScalar *theta,
|
| 2396 |
eromero |
50 |
PetscScalar *thetai, PetscScalar *pX, PetscScalar *pY, PetscInt ld);
|
| 2021 |
eromero |
51 |
PetscErrorCode dvd_improvex_jd_lit_const_0(dvdDashboard *d, PetscInt i,
|
|
|
52 |
PetscScalar* theta, PetscScalar* thetai,
|
|
|
53 |
PetscInt *maxits, PetscReal *tol);
|
|
|
54 |
PetscErrorCode dvd_improvex_get_eigenvectors(dvdDashboard *d, PetscScalar *pX,
|
|
|
55 |
PetscScalar *pY, PetscInt ld_,
|
|
|
56 |
PetscScalar *auxS, PetscInt size_auxS);
|
| 2605 |
eromero |
57 |
PetscErrorCode dvd_improvex_apply_proj(dvdDashboard *d, Vec *V, PetscInt cV, PetscScalar *auxS);
|
| 1735 |
eromero |
58 |
|
| 2142 |
eromero |
59 |
#define size_Z (64*4)
|
| 1965 |
eromero |
60 |
|
| 1867 |
eromero |
61 |
/**** JD update step (I - Kfg'/(g'Kf)) K(A - sB) (I - Kfg'/(g'Kf)) t = (I - Kfg'/(g'Kf))r ****/
|
|
|
62 |
|
|
|
63 |
typedef struct {
|
|
|
64 |
PetscInt size_X;
|
|
|
65 |
void
|
|
|
66 |
*old_improveX_data; /* old improveX_data */
|
|
|
67 |
improveX_type
|
|
|
68 |
old_improveX; /* old improveX */
|
|
|
69 |
KSP ksp; /* correction equation solver */
|
| 2605 |
eromero |
70 |
Vec
|
| 1965 |
eromero |
71 |
friends, /* reference vector for composite vectors */
|
| 1867 |
eromero |
72 |
*auxV; /* auxiliar vectors */
|
| 2605 |
eromero |
73 |
PetscScalar *auxS, /* auxiliar scalars */
|
|
|
74 |
*theta,
|
| 1960 |
eromero |
75 |
*thetai; /* the shifts used in the correction eq. */
|
| 1867 |
eromero |
76 |
PetscInt maxits, /* maximum number of iterations */
|
| 1960 |
eromero |
77 |
r_s, r_e, /* the selected eigenpairs to improve */
|
| 1965 |
eromero |
78 |
ksp_max_size; /* the ksp maximum subvectors size */
|
| 1883 |
eromero |
79 |
PetscReal tol, /* the maximum solution tolerance */
|
| 2608 |
eromero |
80 |
lastTol, /* last tol for dynamic stopping criterion */
|
| 1883 |
eromero |
81 |
fix; /* tolerance for using the approx. eigenvalue */
|
| 2608 |
eromero |
82 |
PetscBool
|
|
|
83 |
dynamic; /* if the dynamic stopping criterion is applied */
|
| 1867 |
eromero |
84 |
dvdDashboard
|
|
|
85 |
*d; /* the currect dvdDashboard reference */
|
| 2244 |
eromero |
86 |
PC old_pc; /* old pc in ksp */
|
| 2605 |
eromero |
87 |
Vec
|
|
|
88 |
*u, /* new X vectors */
|
|
|
89 |
*real_KZ, /* original KZ */
|
|
|
90 |
*KZ; /* KZ vecs for the projector KZ*inv(X'*KZ)*X' */
|
|
|
91 |
PetscScalar
|
|
|
92 |
*XKZ, /* X'*KZ */
|
|
|
93 |
*iXKZ; /* inverse of XKZ */
|
|
|
94 |
PetscInt
|
|
|
95 |
ldXKZ, /* leading dimension of XKZ */
|
|
|
96 |
size_iXKZ, /* size of iXKZ */
|
|
|
97 |
ldiXKZ, /* leading dimension of iXKZ */
|
|
|
98 |
size_KZ, /* size of converged KZ */
|
|
|
99 |
size_real_KZ, /* original size of KZ */
|
|
|
100 |
size_cX, /* last value of d->size_cX */
|
|
|
101 |
old_size_X; /* last number of improved vectors */
|
|
|
102 |
PetscBLASInt
|
|
|
103 |
*iXKZPivots; /* array of pivots */
|
| 1867 |
eromero |
104 |
} dvdImprovex_jd;
|
|
|
105 |
|
| 2605 |
eromero |
106 |
#define _Ceil(A,B) ((A)/(B)+((A)%(B)==0?0:1))
|
|
|
107 |
#define FromIntToScalar(S) (_Ceil((S)*sizeof(PetscBLASInt),sizeof(PetscScalar)))
|
|
|
108 |
|
| 1867 |
eromero |
109 |
#undef __FUNCT__
|
|
|
110 |
#define __FUNCT__ "dvd_improvex_jd"
|
| 2021 |
eromero |
111 |
PetscErrorCode dvd_improvex_jd(dvdDashboard *d, dvdBlackboard *b, KSP ksp,
|
| 2608 |
eromero |
112 |
PetscInt max_bs, PetscInt cX_impr, PetscBool dynamic)
|
| 1867 |
eromero |
113 |
{
|
|
|
114 |
PetscErrorCode ierr;
|
|
|
115 |
dvdImprovex_jd *data;
|
| 2605 |
eromero |
116 |
PetscBool t, herm = DVD_IS(d->sEP, DVD_EP_HERMITIAN)?PETSC_TRUE:PETSC_FALSE;
|
| 2244 |
eromero |
117 |
PC pc;
|
| 2605 |
eromero |
118 |
PetscInt size_P;
|
| 1867 |
eromero |
119 |
|
|
|
120 |
PetscFunctionBegin;
|
|
|
121 |
|
| 1960 |
eromero |
122 |
/* Setting configuration constrains */
|
| 2605 |
eromero |
123 |
ierr = PetscTypeCompare((PetscObject)ksp, KSPPREONLY, &t); CHKERRQ(ierr);
|
|
|
124 |
if (t) ksp = PETSC_NULL;
|
|
|
125 |
|
| 1960 |
eromero |
126 |
/* If the arithmetic is real and the problem is not Hermitian, then
|
| 1965 |
eromero |
127 |
the block size is incremented in one */
|
| 2320 |
jroman |
128 |
#if !defined(PETSC_USE_COMPLEX)
|
| 2605 |
eromero |
129 |
if (!herm) {
|
| 1965 |
eromero |
130 |
max_bs++;
|
| 2605 |
eromero |
131 |
b->max_size_P = PetscMax(b->max_size_P, 2);
|
|
|
132 |
} else
|
| 1960 |
eromero |
133 |
#endif
|
| 2605 |
eromero |
134 |
b->max_size_P = PetscMax(b->max_size_P, 1);
|
|
|
135 |
b->max_size_X = PetscMax(b->max_size_X, max_bs);
|
|
|
136 |
size_P = b->max_size_P+cX_impr;
|
|
|
137 |
b->max_size_auxV = PetscMax(b->max_size_auxV, b->max_size_X*(ksp?3:2));
|
|
|
138 |
/* u, kr?, auxV */
|
|
|
139 |
b->own_scalars+= size_P*size_P; /* XKZ */
|
| 1965 |
eromero |
140 |
b->max_size_auxS = PetscMax(b->max_size_auxS,
|
| 2605 |
eromero |
141 |
(herm?0:1)*2*b->max_size_proj*b->max_size_proj + /* pX, pY */
|
|
|
142 |
b->max_size_X*3 + /* theta, thetai */
|
|
|
143 |
size_P*size_P + /* iXKZ */
|
|
|
144 |
FromIntToScalar(size_P) + /* iXkZPivots */
|
|
|
145 |
PetscMax(PetscMax(
|
|
|
146 |
3*b->max_size_proj*b->max_size_X, /* dvd_improvex_apply_proj */
|
|
|
147 |
8*cX_impr*b->max_size_X),
|
|
|
148 |
/* dvd_improvex_jd_proj_cuv_KZX */
|
|
|
149 |
(herm?0:1)*11*b->max_size_proj+4*b->max_size_proj*b->max_size_proj));
|
| 1968 |
eromero |
150 |
/* dvd_improvex_get_eigenvectors */
|
| 2605 |
eromero |
151 |
b->own_vecs+= size_P; /* KZ */
|
| 1960 |
eromero |
152 |
|
| 2244 |
eromero |
153 |
/* Setup the preconditioner */
|
|
|
154 |
if (ksp) {
|
|
|
155 |
ierr = KSPGetPC(ksp, &pc); CHKERRQ(ierr);
|
|
|
156 |
ierr = dvd_static_precond_PC(d, b, pc); CHKERRQ(ierr);
|
|
|
157 |
} else {
|
|
|
158 |
ierr = dvd_static_precond_PC(d, b, 0); CHKERRQ(ierr);
|
|
|
159 |
}
|
|
|
160 |
|
| 1867 |
eromero |
161 |
/* Setup the step */
|
|
|
162 |
if (b->state >= DVD_STATE_CONF) {
|
|
|
163 |
ierr = PetscMalloc(sizeof(dvdImprovex_jd), &data); CHKERRQ(ierr);
|
| 2608 |
eromero |
164 |
data->dynamic = dynamic;
|
| 2605 |
eromero |
165 |
data->size_real_KZ = size_P;
|
|
|
166 |
data->real_KZ = b->free_vecs; b->free_vecs+= data->size_real_KZ;
|
|
|
167 |
d->max_size_cX_in_impr = cX_impr;
|
|
|
168 |
data->XKZ = b->free_scalars; b->free_scalars+= size_P*size_P;
|
|
|
169 |
data->ldXKZ = size_P;
|
| 1867 |
eromero |
170 |
data->size_X = b->max_size_X;
|
|
|
171 |
data->old_improveX_data = d->improveX_data;
|
|
|
172 |
d->improveX_data = data;
|
|
|
173 |
data->old_improveX = d->improveX;
|
| 2605 |
eromero |
174 |
data->ksp = ksp;
|
| 1867 |
eromero |
175 |
data->d = d;
|
|
|
176 |
d->improveX = dvd_improvex_jd_gen;
|
| 2244 |
eromero |
177 |
data->ksp_max_size = max_bs;
|
| 1867 |
eromero |
178 |
|
| 2244 |
eromero |
179 |
DVD_FL_ADD(d->startList, dvd_improvex_jd_start);
|
|
|
180 |
DVD_FL_ADD(d->endList, dvd_improvex_jd_end);
|
|
|
181 |
DVD_FL_ADD(d->destroyList, dvd_improvex_jd_d);
|
|
|
182 |
}
|
|
|
183 |
|
|
|
184 |
PetscFunctionReturn(0);
|
|
|
185 |
}
|
|
|
186 |
|
|
|
187 |
|
|
|
188 |
#undef __FUNCT__
|
|
|
189 |
#define __FUNCT__ "dvd_improvex_jd_start"
|
|
|
190 |
PetscErrorCode dvd_improvex_jd_start(dvdDashboard *d)
|
|
|
191 |
{
|
|
|
192 |
PetscErrorCode ierr;
|
|
|
193 |
dvdImprovex_jd *data = (dvdImprovex_jd*)d->improveX_data;
|
|
|
194 |
PetscInt rA, cA, rlA, clA;
|
|
|
195 |
Mat A;
|
|
|
196 |
PetscBool t;
|
|
|
197 |
PC pc;
|
|
|
198 |
|
|
|
199 |
PetscFunctionBegin;
|
|
|
200 |
|
| 2605 |
eromero |
201 |
data->KZ = data->real_KZ;
|
|
|
202 |
data->size_KZ = data->size_cX = data->old_size_X = 0;
|
| 2608 |
eromero |
203 |
data->lastTol = data->dynamic?0.5:0.0;
|
| 2605 |
eromero |
204 |
|
| 2244 |
eromero |
205 |
/* Setup the ksp */
|
|
|
206 |
if(data->ksp) {
|
| 2605 |
eromero |
207 |
/* Create the reference vector */
|
|
|
208 |
ierr = VecCreateCompWithVecs(d->V, data->ksp_max_size, PETSC_NULL,
|
|
|
209 |
&data->friends); CHKERRQ(ierr);
|
|
|
210 |
|
| 2244 |
eromero |
211 |
/* Save the current pc and set a PCNONE */
|
|
|
212 |
ierr = KSPGetPC(data->ksp, &data->old_pc); CHKERRQ(ierr);
|
|
|
213 |
ierr = PetscTypeCompare((PetscObject)data->old_pc, PCNONE, &t);
|
|
|
214 |
CHKERRQ(ierr);
|
| 2608 |
eromero |
215 |
data->lastTol = 0.5;
|
| 2244 |
eromero |
216 |
if (t) {
|
|
|
217 |
data->old_pc = 0;
|
|
|
218 |
} else {
|
|
|
219 |
ierr = PetscObjectReference((PetscObject)data->old_pc); CHKERRQ(ierr);
|
|
|
220 |
ierr = PCCreate(((PetscObject)d->eps)->comm, &pc); CHKERRQ(ierr);
|
|
|
221 |
ierr = PCSetType(pc, PCNONE); CHKERRQ(ierr);
|
|
|
222 |
ierr = PCSetOperators(pc, d->A, d->A, SAME_PRECONDITIONER); CHKERRQ(ierr);
|
|
|
223 |
ierr = KSPSetPC(data->ksp, pc); CHKERRQ(ierr);
|
| 2305 |
jroman |
224 |
ierr = PCDestroy(&pc); CHKERRQ(ierr);
|
| 1980 |
eromero |
225 |
}
|
| 1992 |
eromero |
226 |
|
| 2244 |
eromero |
227 |
/* Create the (I-v*u')*K*(A-s*B) matrix */
|
|
|
228 |
ierr = MatGetSize(d->A, &rA, &cA); CHKERRQ(ierr);
|
|
|
229 |
ierr = MatGetLocalSize(d->A, &rlA, &clA); CHKERRQ(ierr);
|
|
|
230 |
ierr = MatCreateShell(((PetscObject)d->A)->comm, rlA*data->ksp_max_size,
|
|
|
231 |
clA*data->ksp_max_size, rA*data->ksp_max_size,
|
|
|
232 |
cA*data->ksp_max_size, data, &A); CHKERRQ(ierr);
|
|
|
233 |
ierr = MatShellSetOperation(A, MATOP_MULT,
|
|
|
234 |
(void(*)(void))dvd_matmult_jd); CHKERRQ(ierr);
|
|
|
235 |
ierr = MatShellSetOperation(A, MATOP_GET_VECS,
|
|
|
236 |
(void(*)(void))dvd_matgetvecs_jd);
|
|
|
237 |
CHKERRQ(ierr);
|
|
|
238 |
|
| 2519 |
eromero |
239 |
/* Try to avoid KSPReset */
|
|
|
240 |
ierr = KSPGetOperatorsSet(data->ksp,&t,PETSC_NULL);CHKERRQ(ierr);
|
|
|
241 |
if (t) {
|
|
|
242 |
Mat M;
|
|
|
243 |
PetscInt rM;
|
|
|
244 |
ierr = KSPGetOperators(data->ksp,&M,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
|
|
|
245 |
ierr = MatGetSize(M,&rM,PETSC_NULL);CHKERRQ(ierr);
|
|
|
246 |
if (rM != rA*data->ksp_max_size) { ierr = KSPReset(data->ksp);CHKERRQ(ierr); }
|
|
|
247 |
}
|
| 2244 |
eromero |
248 |
ierr = KSPSetOperators(data->ksp, A, A, SAME_PRECONDITIONER);
|
|
|
249 |
CHKERRQ(ierr);
|
|
|
250 |
ierr = KSPSetUp(data->ksp); CHKERRQ(ierr);
|
| 2305 |
jroman |
251 |
ierr = MatDestroy(&A); CHKERRQ(ierr);
|
| 2605 |
eromero |
252 |
} else {
|
| 2244 |
eromero |
253 |
data->old_pc = 0;
|
| 2605 |
eromero |
254 |
data->friends = PETSC_NULL;
|
|
|
255 |
}
|
| 2244 |
eromero |
256 |
|
|
|
257 |
PetscFunctionReturn(0);
|
|
|
258 |
}
|
|
|
259 |
|
|
|
260 |
|
|
|
261 |
#undef __FUNCT__
|
|
|
262 |
#define __FUNCT__ "dvd_improvex_jd_end"
|
|
|
263 |
PetscErrorCode dvd_improvex_jd_end(dvdDashboard *d)
|
|
|
264 |
{
|
|
|
265 |
PetscErrorCode ierr;
|
|
|
266 |
dvdImprovex_jd *data = (dvdImprovex_jd*)d->improveX_data;
|
|
|
267 |
|
|
|
268 |
PetscFunctionBegin;
|
|
|
269 |
|
| 2605 |
eromero |
270 |
if (data->friends) { ierr = VecDestroy(&data->friends); CHKERRQ(ierr); }
|
|
|
271 |
|
| 2244 |
eromero |
272 |
/* Restore the pc of ksp */
|
|
|
273 |
if (data->old_pc) {
|
|
|
274 |
ierr = KSPSetPC(data->ksp, data->old_pc); CHKERRQ(ierr);
|
| 2305 |
jroman |
275 |
ierr = PCDestroy(&data->old_pc); CHKERRQ(ierr);
|
| 1960 |
eromero |
276 |
}
|
|
|
277 |
|
|
|
278 |
PetscFunctionReturn(0);
|
|
|
279 |
}
|
|
|
280 |
|
|
|
281 |
|
|
|
282 |
#undef __FUNCT__
|
| 1992 |
eromero |
283 |
#define __FUNCT__ "dvd_improvex_jd_d"
|
| 2021 |
eromero |
284 |
PetscErrorCode dvd_improvex_jd_d(dvdDashboard *d)
|
| 1992 |
eromero |
285 |
{
|
|
|
286 |
PetscErrorCode ierr;
|
|
|
287 |
dvdImprovex_jd *data = (dvdImprovex_jd*)d->improveX_data;
|
|
|
288 |
|
|
|
289 |
PetscFunctionBegin;
|
|
|
290 |
|
|
|
291 |
/* Restore changes in dvdDashboard */
|
|
|
292 |
d->improveX_data = data->old_improveX_data;
|
|
|
293 |
|
|
|
294 |
/* Free local data and objects */
|
|
|
295 |
ierr = PetscFree(data); CHKERRQ(ierr);
|
|
|
296 |
|
|
|
297 |
PetscFunctionReturn(0);
|
|
|
298 |
}
|
|
|
299 |
|
|
|
300 |
|
|
|
301 |
#undef __FUNCT__
|
| 1867 |
eromero |
302 |
#define __FUNCT__ "dvd_improvex_jd_gen"
|
| 2021 |
eromero |
303 |
PetscErrorCode dvd_improvex_jd_gen(dvdDashboard *d, Vec *D,
|
| 1867 |
eromero |
304 |
PetscInt max_size_D, PetscInt r_s,
|
|
|
305 |
PetscInt r_e, PetscInt *size_D)
|
|
|
306 |
{
|
|
|
307 |
dvdImprovex_jd *data = (dvdImprovex_jd*)d->improveX_data;
|
|
|
308 |
PetscErrorCode ierr;
|
| 1960 |
eromero |
309 |
PetscInt i, j, n, maxits, maxits0, lits, s;
|
| 2605 |
eromero |
310 |
PetscScalar *pX, *pY, *auxS = d->auxS, *auxS0;
|
| 1960 |
eromero |
311 |
PetscReal tol, tol0;
|
|
|
312 |
Vec *u, *v, *kr, kr_comp, D_comp;
|
| 1867 |
eromero |
313 |
|
|
|
314 |
PetscFunctionBegin;
|
|
|
315 |
|
|
|
316 |
/* Quick exit */
|
|
|
317 |
if ((max_size_D == 0) || r_e-r_s <= 0) {
|
|
|
318 |
/* Callback old improveX */
|
|
|
319 |
if (data->old_improveX) {
|
|
|
320 |
d->improveX_data = data->old_improveX_data;
|
|
|
321 |
data->old_improveX(d, PETSC_NULL, 0, 0, 0, PETSC_NULL);
|
|
|
322 |
d->improveX_data = data;
|
|
|
323 |
}
|
|
|
324 |
PetscFunctionReturn(0);
|
|
|
325 |
}
|
|
|
326 |
|
|
|
327 |
n = PetscMin(PetscMin(data->size_X, max_size_D), r_e-r_s);
|
| 2214 |
jroman |
328 |
if (n == 0) SETERRQ(PETSC_COMM_SELF,1, "n == 0!\n");
|
|
|
329 |
if (data->size_X < r_e-r_s) SETERRQ(PETSC_COMM_SELF,1, "size_X < r_e-r_s!\n");
|
| 1867 |
eromero |
330 |
|
| 1965 |
eromero |
331 |
/* Compute the eigenvectors of the selected pairs */
|
| 2555 |
eromero |
332 |
if (DVD_IS(d->sEP, DVD_EP_HERMITIAN)) {
|
|
|
333 |
pX = pY = d->pX;
|
|
|
334 |
} else {
|
|
|
335 |
pX = auxS; auxS+= d->size_H*d->size_H;
|
|
|
336 |
pY = auxS; auxS+= d->size_H*d->size_H;
|
|
|
337 |
ierr = dvd_improvex_get_eigenvectors(d, pX, pY, d->size_H, auxS,
|
|
|
338 |
d->size_auxS-(auxS-d->auxS));
|
|
|
339 |
CHKERRQ(ierr);
|
|
|
340 |
}
|
| 1965 |
eromero |
341 |
|
| 2608 |
eromero |
342 |
/* Restart lastTol if a new pair converged */
|
|
|
343 |
if (data->dynamic && data->size_cX < d->size_cX)
|
|
|
344 |
data->lastTol = 0.5;
|
|
|
345 |
|
| 2605 |
eromero |
346 |
for(i=0, s=0, auxS0=auxS; i<n; i+=s) {
|
| 1960 |
eromero |
347 |
/* If the selected eigenvalue is complex, but the arithmetic is real... */
|
| 2320 |
jroman |
348 |
#if !defined(PETSC_USE_COMPLEX)
|
| 1965 |
eromero |
349 |
if (PetscAbsScalar(d->eigi[i] != 0.0)) {
|
|
|
350 |
if (i+2 <= max_size_D) s=2; else break;
|
| 1960 |
eromero |
351 |
} else
|
|
|
352 |
#endif
|
|
|
353 |
s=1;
|
|
|
354 |
|
| 1872 |
eromero |
355 |
data->auxV = d->auxV;
|
| 1960 |
eromero |
356 |
data->r_s = r_s+i; data->r_e = r_s+i+s;
|
| 2605 |
eromero |
357 |
auxS = auxS0;
|
|
|
358 |
data->theta = auxS; auxS+= 2*s;
|
|
|
359 |
data->thetai = auxS; auxS+= s;
|
|
|
360 |
/* If GD, kr = D */
|
|
|
361 |
if (!data->ksp) {
|
|
|
362 |
kr = &D[i];
|
| 1867 |
eromero |
363 |
|
| 2605 |
eromero |
364 |
/* If JD, kr = auxV */
|
|
|
365 |
} else {
|
|
|
366 |
kr = data->auxV; data->auxV+= s;
|
|
|
367 |
}
|
|
|
368 |
|
| 1867 |
eromero |
369 |
/* Compute theta, maximum iterations and tolerance */
|
| 1960 |
eromero |
370 |
maxits = 0; tol = 1;
|
|
|
371 |
for(j=0; j<s; j++) {
|
|
|
372 |
ierr = d->improvex_jd_lit(d, r_s+i+j, &data->theta[2*j],
|
|
|
373 |
&data->thetai[j], &maxits0, &tol0);
|
|
|
374 |
CHKERRQ(ierr);
|
|
|
375 |
maxits+= maxits0; tol*= tol0;
|
|
|
376 |
}
|
| 2608 |
eromero |
377 |
maxits/= s; tol = data->dynamic?data->lastTol:exp(log(tol)/s);
|
| 1867 |
eromero |
378 |
|
| 1965 |
eromero |
379 |
/* Compute u, v and kr */
|
| 2605 |
eromero |
380 |
ierr = dvd_improvex_jd_proj_cuv(d, r_s+i, r_s+i+s, &u, &v, kr,
|
|
|
381 |
&data->auxV, &auxS, data->theta, data->thetai,
|
|
|
382 |
&pX[d->size_H*(r_s+i+d->cX_in_H)], &pY[d->size_H*(r_s+i+d->cX_in_H)], d->size_H);
|
| 1965 |
eromero |
383 |
CHKERRQ(ierr);
|
| 2605 |
eromero |
384 |
data->u = u;
|
| 1965 |
eromero |
385 |
|
| 2018 |
eromero |
386 |
/* Check if the first eigenpairs are converged */
|
|
|
387 |
if (i == 0) {
|
|
|
388 |
ierr = d->preTestConv(d, 0, s, s, PETSC_NULL, PETSC_NULL, &d->npreconv);
|
|
|
389 |
CHKERRQ(ierr);
|
|
|
390 |
if (d->npreconv > 0) break;
|
|
|
391 |
}
|
|
|
392 |
|
| 2396 |
eromero |
393 |
/* Compute kr <- kr - v*(u'*kr) */
|
| 2605 |
eromero |
394 |
ierr = dvd_improvex_apply_proj(d, kr, s, auxS); CHKERRQ(ierr);
|
| 1867 |
eromero |
395 |
|
| 2605 |
eromero |
396 |
/* If JD */
|
|
|
397 |
if (data->ksp) {
|
|
|
398 |
data->auxS = auxS;
|
|
|
399 |
|
|
|
400 |
/* kr <- -kr */
|
| 1980 |
eromero |
401 |
for(j=0; j<s; j++) {
|
| 2605 |
eromero |
402 |
ierr = VecScale(kr[j], -1.0); CHKERRQ(ierr);
|
| 1980 |
eromero |
403 |
}
|
| 2605 |
eromero |
404 |
|
| 1980 |
eromero |
405 |
/* Compouse kr and D */
|
|
|
406 |
ierr = VecCreateCompWithVecs(kr, data->ksp_max_size, data->friends,
|
|
|
407 |
&kr_comp); CHKERRQ(ierr);
|
|
|
408 |
ierr = VecCreateCompWithVecs(&D[i], data->ksp_max_size, data->friends,
|
|
|
409 |
&D_comp); CHKERRQ(ierr);
|
|
|
410 |
ierr = VecCompSetVecs(data->friends, PETSC_NULL, s); CHKERRQ(ierr);
|
|
|
411 |
|
|
|
412 |
/* Solve the correction equation */
|
|
|
413 |
ierr = KSPSetTolerances(data->ksp, tol, PETSC_DEFAULT, PETSC_DEFAULT,
|
|
|
414 |
maxits); CHKERRQ(ierr);
|
|
|
415 |
ierr = KSPSolve(data->ksp, kr_comp, D_comp); CHKERRQ(ierr);
|
|
|
416 |
ierr = KSPGetIterationNumber(data->ksp, &lits); CHKERRQ(ierr);
|
|
|
417 |
d->eps->OP->lineariterations+= lits;
|
|
|
418 |
|
|
|
419 |
/* Destroy the composed ks and D */
|
| 2305 |
jroman |
420 |
ierr = VecDestroy(&kr_comp); CHKERRQ(ierr);
|
|
|
421 |
ierr = VecDestroy(&D_comp); CHKERRQ(ierr);
|
| 1980 |
eromero |
422 |
}
|
| 1867 |
eromero |
423 |
}
|
| 1965 |
eromero |
424 |
*size_D = i;
|
| 2608 |
eromero |
425 |
if (data->dynamic) data->lastTol = PetscMax(data->lastTol/2.0,PETSC_MACHINE_EPSILON*10.0);
|
| 1867 |
eromero |
426 |
|
|
|
427 |
/* Callback old improveX */
|
|
|
428 |
if (data->old_improveX) {
|
|
|
429 |
d->improveX_data = data->old_improveX_data;
|
|
|
430 |
data->old_improveX(d, PETSC_NULL, 0, 0, 0, PETSC_NULL);
|
|
|
431 |
d->improveX_data = data;
|
|
|
432 |
}
|
|
|
433 |
|
|
|
434 |
PetscFunctionReturn(0);
|
|
|
435 |
}
|
|
|
436 |
|
|
|
437 |
|
|
|
438 |
#undef __FUNCT__
|
|
|
439 |
#define __FUNCT__ "dvd_matmult_jd"
|
|
|
440 |
PetscErrorCode dvd_matmult_jd(Mat A, Vec in, Vec out)
|
|
|
441 |
{
|
|
|
442 |
PetscErrorCode ierr;
|
|
|
443 |
dvdImprovex_jd *data;
|
| 1960 |
eromero |
444 |
PetscInt n, i;
|
| 1965 |
eromero |
445 |
const Vec *inx, *outx, *Bx;
|
| 1867 |
eromero |
446 |
|
|
|
447 |
PetscFunctionBegin;
|
|
|
448 |
|
|
|
449 |
ierr = MatShellGetContext(A, (void**)&data); CHKERRQ(ierr);
|
| 1960 |
eromero |
450 |
ierr = VecCompGetVecs(in, &inx, PETSC_NULL); CHKERRQ(ierr);
|
|
|
451 |
ierr = VecCompGetVecs(out, &outx, PETSC_NULL); CHKERRQ(ierr);
|
|
|
452 |
n = data->r_e - data->r_s;
|
| 1867 |
eromero |
453 |
|
| 1883 |
eromero |
454 |
/* aux <- theta[1]A*in - theta[0]*B*in */
|
| 1960 |
eromero |
455 |
for(i=0; i<n; i++) {
|
|
|
456 |
ierr = MatMult(data->d->A, inx[i], data->auxV[i]); CHKERRQ(ierr);
|
|
|
457 |
}
|
| 1875 |
eromero |
458 |
if (data->d->B) {
|
| 1960 |
eromero |
459 |
for(i=0; i<n; i++) {
|
|
|
460 |
ierr = MatMult(data->d->B, inx[i], outx[i]); CHKERRQ(ierr);
|
|
|
461 |
}
|
| 1965 |
eromero |
462 |
Bx = outx;
|
|
|
463 |
} else
|
|
|
464 |
Bx = inx;
|
|
|
465 |
|
|
|
466 |
for(i=0; i<n; i++) {
|
| 2320 |
jroman |
467 |
#if !defined(PETSC_USE_COMPLEX)
|
| 1965 |
eromero |
468 |
if(data->d->eigi[data->r_s+i] != 0.0) {
|
|
|
469 |
/* aux_i <- [ t_2i+1*A*inx_i - t_2i*Bx_i + ti_i*Bx_i+1;
|
|
|
470 |
aux_i+1 t_2i+1*A*inx_i+1 - ti_i*Bx_i - t_2i*Bx_i+1 ] */
|
|
|
471 |
ierr = VecAXPBYPCZ(data->auxV[i], -data->theta[2*i], data->thetai[i],
|
|
|
472 |
data->theta[2*i+1], Bx[i], Bx[i+1]);
|
|
|
473 |
CHKERRQ(ierr);
|
|
|
474 |
ierr = VecAXPBYPCZ(data->auxV[i+1], -data->thetai[i],
|
|
|
475 |
-data->theta[2*i], data->theta[2*i+1], Bx[i],
|
|
|
476 |
Bx[i+1]); CHKERRQ(ierr);
|
|
|
477 |
i++;
|
|
|
478 |
} else
|
| 1960 |
eromero |
479 |
#endif
|
| 1965 |
eromero |
480 |
{
|
| 1960 |
eromero |
481 |
ierr = VecAXPBY(data->auxV[i], -data->theta[i*2], data->theta[i*2+1],
|
| 1965 |
eromero |
482 |
Bx[i]); CHKERRQ(ierr);
|
| 1960 |
eromero |
483 |
}
|
| 1875 |
eromero |
484 |
}
|
| 1867 |
eromero |
485 |
|
|
|
486 |
/* out <- K * aux */
|
| 1960 |
eromero |
487 |
for(i=0; i<n; i++) {
|
|
|
488 |
ierr = data->d->improvex_precond(data->d, data->r_s+i, data->auxV[i],
|
|
|
489 |
outx[i]); CHKERRQ(ierr);
|
|
|
490 |
}
|
| 1867 |
eromero |
491 |
|
| 2396 |
eromero |
492 |
/* out <- out - v*(u'*out) */
|
| 2605 |
eromero |
493 |
ierr = dvd_improvex_apply_proj(data->d, (Vec*)outx, n, data->auxS);CHKERRQ(ierr);
|
| 1867 |
eromero |
494 |
|
|
|
495 |
PetscFunctionReturn(0);
|
|
|
496 |
}
|
|
|
497 |
|
|
|
498 |
|
|
|
499 |
#undef __FUNCT__
|
| 1960 |
eromero |
500 |
#define __FUNCT__ "dvd_matgetvecs_jd"
|
|
|
501 |
PetscErrorCode dvd_matgetvecs_jd(Mat A, Vec *right, Vec *left)
|
|
|
502 |
{
|
|
|
503 |
PetscErrorCode ierr;
|
|
|
504 |
Vec *r, *l;
|
|
|
505 |
dvdImprovex_jd *data;
|
|
|
506 |
PetscInt n, i;
|
|
|
507 |
|
|
|
508 |
PetscFunctionBegin;
|
|
|
509 |
|
|
|
510 |
ierr = MatShellGetContext(A, (void**)&data); CHKERRQ(ierr);
|
| 1965 |
eromero |
511 |
n = data->ksp_max_size;
|
| 1960 |
eromero |
512 |
if (right) {
|
|
|
513 |
ierr = PetscMalloc(sizeof(Vec)*n, &r); CHKERRQ(ierr);
|
|
|
514 |
}
|
|
|
515 |
if (left) {
|
|
|
516 |
ierr = PetscMalloc(sizeof(Vec)*n, &l); CHKERRQ(ierr);
|
|
|
517 |
}
|
|
|
518 |
for (i=0; i<n; i++) {
|
|
|
519 |
ierr = MatGetVecs(data->d->A, right?&r[i]:PETSC_NULL,
|
|
|
520 |
left?&l[i]:PETSC_NULL); CHKERRQ(ierr);
|
|
|
521 |
}
|
|
|
522 |
if(right) {
|
| 1965 |
eromero |
523 |
ierr = VecCreateCompWithVecs(r, n, data->friends, right); CHKERRQ(ierr);
|
| 1960 |
eromero |
524 |
for (i=0; i<n; i++) {
|
| 2305 |
jroman |
525 |
ierr = VecDestroy(&r[i]); CHKERRQ(ierr);
|
| 1960 |
eromero |
526 |
}
|
|
|
527 |
}
|
|
|
528 |
if(left) {
|
| 1965 |
eromero |
529 |
ierr = VecCreateCompWithVecs(l, n, data->friends, left); CHKERRQ(ierr);
|
| 1960 |
eromero |
530 |
for (i=0; i<n; i++) {
|
| 2305 |
jroman |
531 |
ierr = VecDestroy(&l[i]); CHKERRQ(ierr);
|
| 1960 |
eromero |
532 |
}
|
|
|
533 |
}
|
|
|
534 |
|
|
|
535 |
if (right) {
|
|
|
536 |
ierr = PetscFree(r); CHKERRQ(ierr);
|
|
|
537 |
}
|
|
|
538 |
if (left) {
|
|
|
539 |
ierr = PetscFree(l); CHKERRQ(ierr);
|
|
|
540 |
}
|
|
|
541 |
|
|
|
542 |
PetscFunctionReturn(0);
|
|
|
543 |
}
|
|
|
544 |
|
|
|
545 |
|
|
|
546 |
#undef __FUNCT__
|
| 1867 |
eromero |
547 |
#define __FUNCT__ "dvd_improvex_jd_proj_uv"
|
| 2021 |
eromero |
548 |
PetscErrorCode dvd_improvex_jd_proj_uv(dvdDashboard *d, dvdBlackboard *b,
|
|
|
549 |
ProjType_t p)
|
| 1867 |
eromero |
550 |
{
|
|
|
551 |
PetscFunctionBegin;
|
|
|
552 |
|
|
|
553 |
/* Setup the step */
|
|
|
554 |
if (b->state >= DVD_STATE_CONF) {
|
| 2605 |
eromero |
555 |
switch(p) {
|
|
|
556 |
case DVD_PROJ_KXX:
|
|
|
557 |
d->improvex_jd_proj_uv = dvd_improvex_jd_proj_uv_KXX; break;
|
|
|
558 |
case DVD_PROJ_KZX:
|
|
|
559 |
d->improvex_jd_proj_uv = dvd_improvex_jd_proj_uv_KZX; break;
|
|
|
560 |
}
|
| 1867 |
eromero |
561 |
}
|
|
|
562 |
|
|
|
563 |
PetscFunctionReturn(0);
|
|
|
564 |
}
|
|
|
565 |
|
| 2605 |
eromero |
566 |
#undef __FUNCT__
|
|
|
567 |
#define __FUNCT__ "dvd_improvex_jd_proj_cuv"
|
|
|
568 |
/*
|
|
|
569 |
Compute: u <- X, v <- K*(theta[0]*A+theta[1]*B)*X,
|
|
|
570 |
kr <- K^{-1}*(A-eig*B)*X, being X <- V*pX[i_s..i_e-1], Y <- W*pY[i_s..i_e-1]
|
|
|
571 |
where
|
|
|
572 |
auxV, 4*(i_e-i_s) auxiliar global vectors
|
|
|
573 |
pX,pY, the right and left eigenvectors of the projected system
|
|
|
574 |
ld, the leading dimension of pX and pY
|
|
|
575 |
auxS: max(8*bs*max_size_cX_in_proj,size_V*size_V)
|
|
|
576 |
*/
|
|
|
577 |
PetscErrorCode dvd_improvex_jd_proj_cuv(dvdDashboard *d, PetscInt i_s,
|
|
|
578 |
PetscInt i_e, Vec **u, Vec **v, Vec *kr, Vec **auxV, PetscScalar **auxS,
|
|
|
579 |
PetscScalar *theta, PetscScalar *thetai, PetscScalar *pX, PetscScalar *pY,
|
|
|
580 |
PetscInt ld)
|
|
|
581 |
{
|
|
|
582 |
PetscErrorCode ierr;
|
|
|
583 |
PetscInt n = i_e - i_s, size_KZ, V_new, rm, i;
|
|
|
584 |
PetscScalar *wS0, *wS1;
|
|
|
585 |
dvdImprovex_jd *data = (dvdImprovex_jd*)d->improveX_data;
|
|
|
586 |
PetscBLASInt s, ldXKZ, info;
|
|
|
587 |
|
|
|
588 |
PetscFunctionBegin;
|
|
|
589 |
|
|
|
590 |
/* Check consistency */
|
|
|
591 |
V_new = d->size_cX - data->size_cX;
|
|
|
592 |
if (V_new > data->old_size_X) { SETERRQ(PETSC_COMM_SELF,1, "Consistency broken!"); }
|
|
|
593 |
data->old_size_X = n;
|
|
|
594 |
|
|
|
595 |
/* KZ <- KZ(rm:) */
|
|
|
596 |
rm = PetscMax(V_new+data->size_KZ-d->max_size_cX_in_impr, 0);
|
|
|
597 |
if (rm > 0) for (i=rm; i<data->size_KZ+V_new; i++) {
|
|
|
598 |
ierr = VecCopy(data->KZ[i], data->KZ[i-rm]);CHKERRQ(ierr);
|
|
|
599 |
}
|
|
|
600 |
data->size_KZ+= V_new-rm;
|
|
|
601 |
data->size_cX = d->size_cX;
|
|
|
602 |
|
|
|
603 |
/* XKZ <- XKZ(rm:,rm:) */
|
|
|
604 |
if (rm > 0) for (i=rm; i<data->size_KZ+V_new; i++) {
|
|
|
605 |
ierr = SlepcDenseCopy(&data->XKZ[i*data->ldXKZ+i], data->ldXKZ, &data->XKZ[(i-rm)*data->ldXKZ+i-rm], data->ldXKZ, data->size_KZ, 1);CHKERRQ(ierr);
|
|
|
606 |
}
|
|
|
607 |
|
|
|
608 |
/* Compute X, KZ and KR */
|
|
|
609 |
*u = *auxV; *auxV+= n;
|
|
|
610 |
*v = &data->KZ[data->size_KZ];
|
|
|
611 |
ierr = d->improvex_jd_proj_uv(d, i_s, i_e, *u, *v, kr, *auxV, theta, thetai,
|
|
|
612 |
pX, pY, ld);CHKERRQ(ierr);
|
|
|
613 |
|
|
|
614 |
/* XKZ <- X'*KZ */
|
|
|
615 |
size_KZ = data->size_KZ+n;
|
|
|
616 |
wS0 = *auxS; wS1 = wS0+2*n*data->size_KZ+n*n;
|
|
|
617 |
ierr = VecsMult(data->XKZ, 0, data->ldXKZ, d->V-data->size_KZ, 0, data->size_KZ, data->KZ, 0, size_KZ, wS0, wS1);CHKERRQ(ierr);
|
|
|
618 |
ierr = VecsMult(&data->XKZ[data->size_KZ], 0, data->ldXKZ, *u, 0, n, data->KZ, 0, size_KZ, wS0, wS1);CHKERRQ(ierr);
|
|
|
619 |
|
|
|
620 |
/* iXKZ <- inv(XKZ) */
|
|
|
621 |
s = PetscBLASIntCast(size_KZ);
|
|
|
622 |
data->ldiXKZ = data->size_iXKZ = size_KZ;
|
|
|
623 |
data->iXKZ = *auxS; *auxS+= size_KZ*size_KZ;
|
|
|
624 |
data->iXKZPivots = (PetscBLASInt*)*auxS;
|
|
|
625 |
*auxS += FromIntToScalar(size_KZ);
|
|
|
626 |
ierr = SlepcDenseCopy(data->iXKZ,data->ldiXKZ,data->XKZ,data->ldXKZ,size_KZ,size_KZ);CHKERRQ(ierr);
|
|
|
627 |
ldXKZ = PetscBLASIntCast(data->ldiXKZ);
|
|
|
628 |
LAPACKgetrf_(&s, &s, data->iXKZ, &ldXKZ, data->iXKZPivots, &info);
|
|
|
629 |
if (info) SETERRQ1(PETSC_COMM_WORLD,PETSC_ERR_LIB, "Error in Lapack XGETRF %d", info);
|
|
|
630 |
|
|
|
631 |
PetscFunctionReturn(0);
|
|
|
632 |
}
|
|
|
633 |
|
| 1980 |
eromero |
634 |
#define DVD_COMPLEX_RAYLEIGH_QUOTIENT(ur,ui,Axr,Axi,Bxr,Bxi,eigr,eigi,b,ierr)\
|
|
|
635 |
{ \
|
|
|
636 |
ierr = VecDot((Axr), (ur), &(b)[0]); CHKERRQ(ierr); /* r*A*r */ \
|
|
|
637 |
ierr = VecDot((Axr), (ui), &(b)[1]); CHKERRQ(ierr); /* i*A*r */ \
|
|
|
638 |
ierr = VecDot((Axi), (ur), &(b)[2]); CHKERRQ(ierr); /* r*A*i */ \
|
|
|
639 |
ierr = VecDot((Axi), (ui), &(b)[3]); CHKERRQ(ierr); /* i*A*i */ \
|
|
|
640 |
ierr = VecDot((Bxr), (ur), &(b)[4]); CHKERRQ(ierr); /* r*B*r */ \
|
|
|
641 |
ierr = VecDot((Bxr), (ui), &(b)[5]); CHKERRQ(ierr); /* i*B*r */ \
|
|
|
642 |
ierr = VecDot((Bxi), (ur), &(b)[6]); CHKERRQ(ierr); /* r*B*i */ \
|
|
|
643 |
ierr = VecDot((Bxi), (ui), &(b)[7]); CHKERRQ(ierr); /* i*B*i */ \
|
|
|
644 |
(b)[0] = (b)[0]+(b)[3]; /* rAr+iAi */ \
|
|
|
645 |
(b)[2] = (b)[2]-(b)[1]; /* rAi-iAr */ \
|
|
|
646 |
(b)[4] = (b)[4]+(b)[7]; /* rBr+iBi */ \
|
|
|
647 |
(b)[6] = (b)[6]-(b)[5]; /* rBi-iBr */ \
|
|
|
648 |
(b)[7] = (b)[4]*(b)[4] + (b)[6]*(b)[6]; /* k */ \
|
|
|
649 |
*(eigr) = ((b)[0]*(b)[4] + (b)[2]*(b)[6]) / (b)[7]; /* eig_r */ \
|
|
|
650 |
*(eigi) = ((b)[2]*(b)[4] - (b)[0]*(b)[6]) / (b)[7]; /* eig_i */ \
|
|
|
651 |
}
|
| 1867 |
eromero |
652 |
|
| 1980 |
eromero |
653 |
#if !defined(PETSC_USE_COMPLEX)
|
| 2007 |
eromero |
654 |
#define DVD_COMPUTE_N_RR(eps,i,i_s,n,eigr,eigi,u,Ax,Bx,b,ierr) \
|
| 1980 |
eromero |
655 |
for((i)=0; (i)<(n); (i)++) { \
|
|
|
656 |
if ((eigi)[(i_s)+(i)] != 0.0) { \
|
|
|
657 |
/* eig_r = [(rAr+iAi)*(rBr+iBi) + (rAi-iAr)*(rBi-iBr)]/k \
|
|
|
658 |
eig_i = [(rAi-iAr)*(rBr+iBi) - (rAr+iAi)*(rBi-iBr)]/k \
|
|
|
659 |
k = (rBr+iBi)*(rBr+iBi) + (rBi-iBr)*(rBi-iBr) */ \
|
|
|
660 |
DVD_COMPLEX_RAYLEIGH_QUOTIENT((u)[(i)], (u)[(i)+1], (Ax)[(i)], \
|
|
|
661 |
(Ax)[(i)+1], (Bx)[(i)], (Bx)[(i)+1], &(b)[8], &(b)[9], (b), (ierr)); \
|
|
|
662 |
if (PetscAbsScalar((eigr)[(i_s)+(i)] - (b)[8])/ \
|
| 2034 |
eromero |
663 |
PetscAbsScalar((eigr)[(i_s)+(i)]) > 1e-10 || \
|
| 1980 |
eromero |
664 |
PetscAbsScalar((eigi)[(i_s)+(i)] - (b)[9])/ \
|
| 2034 |
eromero |
665 |
PetscAbsScalar((eigi)[(i_s)+(i)]) > 1e-10 ) { \
|
| 2394 |
jroman |
666 |
(ierr) = PetscInfo4((eps), "The eigenvalue %G+%G is far from its "\
|
|
|
667 |
"Rayleigh quotient value %G+%G\n", \
|
| 2007 |
eromero |
668 |
(eigr)[(i_s)+(i)], \
|
|
|
669 |
(eigi)[(i_s)+1], (b)[8], (b)[9]); \
|
| 1980 |
eromero |
670 |
} \
|
|
|
671 |
(i)++; \
|
|
|
672 |
} \
|
|
|
673 |
}
|
|
|
674 |
#else
|
| 2007 |
eromero |
675 |
#define DVD_COMPUTE_N_RR(eps,i,i_s,n,eigr,eigi,u,Ax,Bx,b,ierr) \
|
| 1980 |
eromero |
676 |
for((i)=0; (i)<(n); (i)++) { \
|
|
|
677 |
(ierr) = VecDot((Ax)[(i)], (u)[(i)], &(b)[0]); CHKERRQ(ierr); \
|
|
|
678 |
(ierr) = VecDot((Bx)[(i)], (u)[(i)], &(b)[1]); CHKERRQ(ierr); \
|
|
|
679 |
(b)[0] = (b)[0]/(b)[1]; \
|
|
|
680 |
if (PetscAbsScalar((eigr)[(i_s)+(i)] - (b)[0])/ \
|
| 2034 |
eromero |
681 |
PetscAbsScalar((eigr)[(i_s)+(i)]) > 1e-10 ) { \
|
| 2394 |
jroman |
682 |
(ierr) = PetscInfo4((eps), "The eigenvalue %G+%G is far from its " \
|
|
|
683 |
"Rayleigh quotient value %G+%G\n", \
|
| 2007 |
eromero |
684 |
PetscRealPart((eigr)[(i_s)+(i)]), \
|
| 1981 |
eromero |
685 |
PetscImaginaryPart((eigr)[(i_s)+(i)]), PetscRealPart((b)[0]), \
|
|
|
686 |
PetscImaginaryPart((b)[0])); \
|
| 1980 |
eromero |
687 |
} \
|
|
|
688 |
}
|
|
|
689 |
#endif
|
|
|
690 |
|
| 1981 |
eromero |
691 |
#if !defined(PETSC_USE_COMPLEX)
|
|
|
692 |
#define DVD_NORM_FOR_UV(x) PetscAbsScalar(x)
|
|
|
693 |
#else
|
|
|
694 |
#define DVD_NORM_FOR_UV(x) (x)
|
|
|
695 |
#endif
|
|
|
696 |
|
| 1980 |
eromero |
697 |
#define DVD_NORMALIZE_UV(u,v,ierr,a) { \
|
|
|
698 |
(ierr) = VecDot((u), (v), &(a)); CHKERRQ(ierr); \
|
| 1981 |
eromero |
699 |
if ((a) == 0.0) { \
|
| 2214 |
jroman |
700 |
SETERRQ(((PetscObject)u)->comm,1, "Inappropriate approximate eigenvector norm"); \
|
| 1980 |
eromero |
701 |
} \
|
|
|
702 |
if ((u) == (v)) { \
|
| 1981 |
eromero |
703 |
ierr = VecScale((u), 1.0/PetscSqrtScalar(DVD_NORM_FOR_UV(a))); \
|
|
|
704 |
CHKERRQ(ierr); \
|
| 1980 |
eromero |
705 |
} else { \
|
|
|
706 |
ierr = VecScale((u), 1.0/(a)); CHKERRQ(ierr); \
|
|
|
707 |
} \
|
|
|
708 |
}
|
|
|
709 |
|
|
|
710 |
|
| 2223 |
jroman |
711 |
#undef __FUNCT__
|
| 2396 |
eromero |
712 |
#define __FUNCT__ "dvd_improvex_jd_proj_uv_KZX"
|
|
|
713 |
/*
|
| 2519 |
eromero |
714 |
Compute: u <- X, v <- K*(theta[0]*A+theta[1]*B)*X,
|
| 2396 |
eromero |
715 |
kr <- K^{-1}*(A-eig*B)*X, being X <- V*pX[i_s..i_e-1], Y <- W*pY[i_s..i_e-1]
|
|
|
716 |
where
|
|
|
717 |
auxV, 4*(i_e-i_s) auxiliar global vectors
|
|
|
718 |
pX,pY, the right and left eigenvectors of the projected system
|
|
|
719 |
ld, the leading dimension of pX and pY
|
|
|
720 |
*/
|
|
|
721 |
PetscErrorCode dvd_improvex_jd_proj_uv_KZX(dvdDashboard *d, PetscInt i_s,
|
| 2605 |
eromero |
722 |
PetscInt i_e, Vec *u, Vec *v, Vec *kr, Vec *auxV, PetscScalar *theta,
|
| 2396 |
eromero |
723 |
PetscScalar *thetai, PetscScalar *pX, PetscScalar *pY, PetscInt ld)
|
|
|
724 |
{
|
|
|
725 |
PetscErrorCode ierr;
|
|
|
726 |
PetscInt n = i_e - i_s, i;
|
| 2605 |
eromero |
727 |
PetscScalar b[16];
|
|
|
728 |
Vec *Ax, *Bx, *r=auxV, X[4];
|
| 2396 |
eromero |
729 |
/* The memory manager doen't allow to call a subroutines */
|
|
|
730 |
PetscScalar Z[size_Z];
|
|
|
731 |
|
|
|
732 |
PetscFunctionBegin;
|
|
|
733 |
|
|
|
734 |
/* u <- X(i) */
|
| 2605 |
eromero |
735 |
ierr = SlepcUpdateVectorsZ(u, 0.0, 1.0, d->V-d->cX_in_H, d->size_V+d->cX_in_H, pX, ld, d->size_H, n); CHKERRQ(ierr);
|
| 2558 |
eromero |
736 |
/* nX(i) <- ||X(i)|| */
|
|
|
737 |
if (d->correctXnorm) {
|
|
|
738 |
for (i=0; i<n; i++) {
|
| 2605 |
eromero |
739 |
ierr = VecNormBegin(u[i], NORM_2, &d->nX[i_s+i]);CHKERRQ(ierr);
|
| 2558 |
eromero |
740 |
}
|
|
|
741 |
for (i=0; i<n; i++) {
|
| 2605 |
eromero |
742 |
ierr = VecNormEnd(u[i], NORM_2, &d->nX[i_s+i]);CHKERRQ(ierr);
|
| 2558 |
eromero |
743 |
}
|
|
|
744 |
} else {
|
|
|
745 |
for (i=0; i<n; i++) d->nX[i_s+i] = 1.0;
|
|
|
746 |
}
|
| 2396 |
eromero |
747 |
|
|
|
748 |
/* v <- theta[0]A*u + theta[1]*B*u */
|
|
|
749 |
|
|
|
750 |
/* Bx <- B*X(i) */
|
| 2605 |
eromero |
751 |
Bx = kr;
|
| 2396 |
eromero |
752 |
for(i=i_s; i<i_e; i++) d->nX[i] = 1.0;
|
|
|
753 |
if (d->BV) {
|
| 2605 |
eromero |
754 |
ierr = SlepcUpdateVectorsZ(Bx, 0.0, 1.0, d->BV-d->cX_in_H, d->size_BV+d->cX_in_H, pX, ld, d->size_H, n); CHKERRQ(ierr);
|
| 2396 |
eromero |
755 |
} else {
|
|
|
756 |
for(i=0; i<n; i++) {
|
|
|
757 |
if (d->B) {
|
| 2605 |
eromero |
758 |
ierr = MatMult(d->B, u[i], Bx[i]); CHKERRQ(ierr);
|
| 2396 |
eromero |
759 |
} else {
|
| 2605 |
eromero |
760 |
ierr = VecCopy(u[i], Bx[i]); CHKERRQ(ierr);
|
| 2396 |
eromero |
761 |
}
|
|
|
762 |
}
|
|
|
763 |
}
|
|
|
764 |
|
|
|
765 |
/* Ax <- A*X(i) */
|
|
|
766 |
Ax = r;
|
| 2605 |
eromero |
767 |
ierr = SlepcUpdateVectorsZ(Ax, 0.0, 1.0, d->AV-d->cX_in_H, d->size_AV+d->cX_in_H, pX, ld, d->size_H, n); CHKERRQ(ierr);
|
| 2396 |
eromero |
768 |
|
|
|
769 |
/* v <- Y(i) */
|
| 2605 |
eromero |
770 |
ierr = SlepcUpdateVectorsZ(v, 0.0, 1.0, (d->W?d->W:d->V)-d->cX_in_H, d->size_V+d->cX_in_H, pY, ld, d->size_H, n); CHKERRQ(ierr);
|
| 2396 |
eromero |
771 |
|
|
|
772 |
/* Recompute the eigenvalue */
|
| 2605 |
eromero |
773 |
DVD_COMPUTE_N_RR(d->eps, i, i_s, n, d->eigr, d->eigi, v, Ax, Bx, b, ierr);
|
| 2396 |
eromero |
774 |
|
|
|
775 |
for(i=0; i<n; i++) {
|
|
|
776 |
#if !defined(PETSC_USE_COMPLEX)
|
|
|
777 |
if(d->eigi[i_s+i] != 0.0) {
|
|
|
778 |
/* [r_i r_i+1 kr_i kr_i+1]*= [ theta_2i' 0 1 0
|
|
|
779 |
|
|
|
780 |
theta_2i+1 -thetai_i -eigr_i -eigi_i
|
|
|
781 |
thetai_i theta_2i+1 eigi_i -eigr_i ] */
|
|
|
782 |
b[0] = b[5] = PetscConj(theta[2*i]);
|
|
|
783 |
b[2] = b[7] = -theta[2*i+1];
|
|
|
784 |
b[6] = -(b[3] = thetai[i]);
|
|
|
785 |
b[1] = b[4] = 0.0;
|
|
|
786 |
b[8] = b[13] = 1.0;
|
|
|
787 |
b[10] = b[15] = -d->eigr[i_s+i];
|
|
|
788 |
b[14] = -(b[11] = d->eigi[i_s+i]);
|
|
|
789 |
b[9] = b[12] = 0.0;
|
|
|
790 |
X[0] = Ax[i]; X[1] = Ax[i+1]; X[2] = Bx[i]; X[3] = Bx[i+1];
|
|
|
791 |
ierr = SlepcUpdateVectorsD(X, 4, 1.0, b, 4, 4, 4, Z, size_Z);
|
|
|
792 |
CHKERRQ(ierr);
|
|
|
793 |
i++;
|
|
|
794 |
} else
|
|
|
795 |
#endif
|
|
|
796 |
{
|
| 2558 |
eromero |
797 |
/* [Ax_i Bx_i]*= [ theta_2i' 1/nX_i
|
|
|
798 |
theta_2i+1 -eig_i/nX_i ] */
|
| 2396 |
eromero |
799 |
b[0] = PetscConj(theta[i*2]);
|
|
|
800 |
b[1] = theta[i*2+1];
|
| 2558 |
eromero |
801 |
b[2] = 1.0/d->nX[i_s+i];
|
|
|
802 |
b[3] = -d->eigr[i_s+i]/d->nX[i_s+i];
|
| 2396 |
eromero |
803 |
X[0] = Ax[i]; X[1] = Bx[i];
|
|
|
804 |
ierr = SlepcUpdateVectorsD(X, 2, 1.0, b, 2, 2, 2, Z, size_Z);
|
|
|
805 |
CHKERRQ(ierr);
|
|
|
806 |
}
|
|
|
807 |
}
|
|
|
808 |
|
|
|
809 |
/* v <- K^{-1} r = K^{-1}(theta_2i'*Ax + theta_2i+1*Bx) */
|
|
|
810 |
for(i=0; i<n; i++) {
|
| 2605 |
eromero |
811 |
ierr = d->improvex_precond(d, i_s+i, r[i], v[i]); CHKERRQ(ierr);
|
| 2396 |
eromero |
812 |
}
|
|
|
813 |
|
|
|
814 |
/* kr <- K^{-1}*kr = K^{-1}*(Ax - eig_i*Bx) */
|
|
|
815 |
d->calcpairs_proj_res(d, i_s, i_e, Bx);
|
|
|
816 |
for(i=0; i<n; i++) {
|
|
|
817 |
ierr = VecCopy(Bx[i], r[i]); CHKERRQ(ierr);
|
| 2605 |
eromero |
818 |
ierr = d->improvex_precond(d, i_s+i, r[i], kr[i]); CHKERRQ(ierr);
|
| 2396 |
eromero |
819 |
}
|
|
|
820 |
|
|
|
821 |
PetscFunctionReturn(0);
|
|
|
822 |
}
|
|
|
823 |
|
|
|
824 |
#undef __FUNCT__
|
| 2605 |
eromero |
825 |
#define __FUNCT__ "dvd_improvex_jd_proj_uv_KXX"
|
| 1980 |
eromero |
826 |
/*
|
| 2605 |
eromero |
827 |
Compute: u <- K^{-1}*X, v <- X,
|
| 1980 |
eromero |
828 |
kr <- K^{-1}*(A-eig*B)*X, being X <- V*pX[i_s..i_e-1]
|
|
|
829 |
where
|
|
|
830 |
auxV, 4*(i_e-i_s) auxiliar global vectors
|
|
|
831 |
pX,pY, the right and left eigenvectors of the projected system
|
|
|
832 |
ld, the leading dimension of pX and pY
|
|
|
833 |
*/
|
| 2605 |
eromero |
834 |
PetscErrorCode dvd_improvex_jd_proj_uv_KXX(dvdDashboard *d, PetscInt i_s,
|
|
|
835 |
PetscInt i_e, Vec *u, Vec *v, Vec *kr, Vec *auxV, PetscScalar *theta,
|
| 1980 |
eromero |
836 |
PetscScalar *thetai, PetscScalar *pX, PetscScalar *pY, PetscInt ld)
|
|
|
837 |
{
|
|
|
838 |
PetscErrorCode ierr;
|
|
|
839 |
PetscInt n = i_e - i_s, i;
|
| 2605 |
eromero |
840 |
PetscScalar b[16];
|
|
|
841 |
Vec *Ax, *Bx, *r = auxV, X[4];
|
| 1980 |
eromero |
842 |
/* The memory manager doen't allow to call a subroutines */
|
|
|
843 |
PetscScalar Z[size_Z];
|
| 1867 |
eromero |
844 |
|
| 1980 |
eromero |
845 |
PetscFunctionBegin;
|
|
|
846 |
|
|
|
847 |
/* [v u] <- X(i) Y(i) */
|
| 2605 |
eromero |
848 |
ierr = SlepcUpdateVectorsZ(v, 0.0, 1.0, d->V-d->cX_in_H, d->size_V+d->cX_in_H, pX, ld, d->size_H, n); CHKERRQ(ierr);
|
|
|
849 |
ierr = SlepcUpdateVectorsZ(u, 0.0, 1.0, (d->W?d->W:d->V)-d->cX_in_H, d->size_V+d->cX_in_H, pY, ld, d->size_H, n); CHKERRQ(ierr);
|
| 1980 |
eromero |
850 |
|
|
|
851 |
/* Bx <- B*X(i) */
|
| 2605 |
eromero |
852 |
Bx = kr;
|
| 1980 |
eromero |
853 |
for(i=i_s; i<i_e; i++) d->nX[i] = 1.0;
|
|
|
854 |
if (d->BV) {
|
| 2605 |
eromero |
855 |
ierr = SlepcUpdateVectorsZ(Bx, 0.0, 1.0, d->BV-d->cX_in_H, d->size_BV+d->cX_in_H, pX, ld, d->size_H, n); CHKERRQ(ierr);
|
| 1980 |
eromero |
856 |
} else {
|
|
|
857 |
if (d->B) {
|
|
|
858 |
for(i=0; i<n; i++) {
|
| 2605 |
eromero |
859 |
ierr = MatMult(d->B, v[i], Bx[i]); CHKERRQ(ierr);
|
| 1980 |
eromero |
860 |
}
|
|
|
861 |
} else
|
| 2605 |
eromero |
862 |
Bx = v;
|
| 1980 |
eromero |
863 |
}
|
|
|
864 |
|
|
|
865 |
/* Ax <- A*X(i) */
|
|
|
866 |
Ax = r;
|
| 2605 |
eromero |
867 |
ierr = SlepcUpdateVectorsZ(Ax, 0.0, 1.0, d->AV-d->cX_in_H, d->size_AV+d->cX_in_H, pX, ld, d->size_H, n); CHKERRQ(ierr);
|
| 1980 |
eromero |
868 |
|
|
|
869 |
/* Recompute the eigenvalue */
|
| 2605 |
eromero |
870 |
DVD_COMPUTE_N_RR(d->eps, i, i_s, n, d->eigr, d->eigi, u, Ax, Bx, b, ierr);
|
| 1980 |
eromero |
871 |
|
|
|
872 |
for(i=0; i<n; i++) {
|
|
|
873 |
if (d->eigi[i_s+i] == 0.0) {
|
|
|
874 |
/* r <- Ax -eig*Bx */
|
|
|
875 |
ierr = VecAXPBY(r[i], -d->eigr[i_s+i], 1.0, Bx[i]); CHKERRQ(ierr);
|
|
|
876 |
} else {
|
| 2034 |
eromero |
877 |
/* [r_i r_i+1 kr_i kr_i+1]*= [ 1 0
|
|
|
878 |
|
|
|
879 |
-eigr_i -eigi_i
|
|
|
880 |
eigi_i -eigr_i] */
|
|
|
881 |
b[0] = b[5] = 1.0;
|
|
|
882 |
b[2] = b[7] = -d->eigr[i_s+i];
|
|
|
883 |
b[6] = -(b[3] = d->eigi[i_s+i]);
|
| 1980 |
eromero |
884 |
b[1] = b[4] = 0.0;
|
| 2605 |
eromero |
885 |
X[0] = r[i]; X[1] = r[i+1]; X[2] = kr[i]; X[3] = kr[i+1];
|
| 1980 |
eromero |
886 |
ierr = SlepcUpdateVectorsD(X, 4, 1.0, b, 4, 4, 2, Z, size_Z);
|
|
|
887 |
CHKERRQ(ierr);
|
|
|
888 |
i++;
|
|
|
889 |
}
|
|
|
890 |
}
|
|
|
891 |
|
|
|
892 |
/* kr <- K^{-1}*r */
|
|
|
893 |
d->calcpairs_proj_res(d, i_s, i_e, r);
|
|
|
894 |
for(i=0; i<n; i++) {
|
| 2605 |
eromero |
895 |
ierr = d->improvex_precond(d, i_s+i, r[i], kr[i]); CHKERRQ(ierr);
|
| 1980 |
eromero |
896 |
}
|
|
|
897 |
|
| 2605 |
eromero |
898 |
/* u <- K^{-1} X(i) */
|
| 1980 |
eromero |
899 |
for(i=0; i<n; i++) {
|
| 2605 |
eromero |
900 |
ierr = d->improvex_precond(d, i_s+i, v[i], u[i]); CHKERRQ(ierr);
|
| 1980 |
eromero |
901 |
}
|
|
|
902 |
|
|
|
903 |
PetscFunctionReturn(0);
|
|
|
904 |
}
|
|
|
905 |
|
|
|
906 |
|
|
|
907 |
#undef __FUNCT__
|
| 2223 |
jroman |
908 |
#define __FUNCT__ "dvd_improvex_jd_lit_const"
|
| 2021 |
eromero |
909 |
PetscErrorCode dvd_improvex_jd_lit_const(dvdDashboard *d, dvdBlackboard *b,
|
|
|
910 |
PetscInt maxits, PetscReal tol,
|
|
|
911 |
PetscReal fix)
|
| 1867 |
eromero |
912 |
{
|
|
|
913 |
dvdImprovex_jd *data = (dvdImprovex_jd*)d->improveX_data;
|
|
|
914 |
|
|
|
915 |
PetscFunctionBegin;
|
|
|
916 |
|
|
|
917 |
/* Setup the step */
|
|
|
918 |
if (b->state >= DVD_STATE_CONF) {
|
|
|
919 |
data->maxits = maxits;
|
|
|
920 |
data->tol = tol;
|
| 1883 |
eromero |
921 |
data->fix = fix;
|
| 1867 |
eromero |
922 |
d->improvex_jd_lit = dvd_improvex_jd_lit_const_0;
|
|
|
923 |
}
|
|
|
924 |
|
|
|
925 |
PetscFunctionReturn(0);
|
|
|
926 |
}
|
|
|
927 |
|
|
|
928 |
|
|
|
929 |
#undef __FUNCT__
|
|
|
930 |
#define __FUNCT__ "dvd_improvex_jd_lit_const_0"
|
| 2021 |
eromero |
931 |
PetscErrorCode dvd_improvex_jd_lit_const_0(dvdDashboard *d, PetscInt i,
|
|
|
932 |
PetscScalar* theta, PetscScalar* thetai, PetscInt *maxits, PetscReal *tol)
|
| 1867 |
eromero |
933 |
{
|
|
|
934 |
dvdImprovex_jd *data = (dvdImprovex_jd*)d->improveX_data;
|
| 1960 |
eromero |
935 |
PetscReal a;
|
| 1867 |
eromero |
936 |
|
|
|
937 |
PetscFunctionBegin;
|
| 2474 |
jroman |
938 |
a = SlepcAbsEigenvalue(d->eigr[i],d->eigi[i]);
|
| 1867 |
eromero |
939 |
|
| 1960 |
eromero |
940 |
if (d->nR[i]/a < data->fix) {
|
|
|
941 |
theta[0] = d->eigr[i];
|
|
|
942 |
theta[1] = 1.0;
|
| 2320 |
jroman |
943 |
#if !defined(PETSC_USE_COMPLEX)
|
| 1960 |
eromero |
944 |
*thetai = d->eigi[i];
|
|
|
945 |
#endif
|
|
|
946 |
} else {
|
|
|
947 |
theta[0] = d->target[0];
|
|
|
948 |
theta[1] = d->target[1];
|
| 2320 |
jroman |
949 |
#if !defined(PETSC_USE_COMPLEX)
|
| 1960 |
eromero |
950 |
*thetai = 0.0;
|
|
|
951 |
#endif
|
|
|
952 |
}
|
|
|
953 |
|
| 2320 |
jroman |
954 |
#if defined(PETSC_USE_COMPLEX)
|
| 1960 |
eromero |
955 |
if(thetai) *thetai = 0.0;
|
|
|
956 |
#endif
|
| 1867 |
eromero |
957 |
*maxits = data->maxits;
|
|
|
958 |
*tol = data->tol;
|
|
|
959 |
|
|
|
960 |
PetscFunctionReturn(0);
|
|
|
961 |
}
|
|
|
962 |
|
|
|
963 |
|
| 1735 |
eromero |
964 |
/**** Patterns implementation *************************************************/
|
| 1675 |
slepc |
965 |
|
| 1744 |
eromero |
966 |
typedef PetscInt (*funcV0_t)(dvdDashboard*, PetscInt, PetscInt, Vec*);
|
|
|
967 |
typedef PetscInt (*funcV1_t)(dvdDashboard*, PetscInt, PetscInt, Vec*,
|
| 1751 |
eromero |
968 |
PetscScalar*, Vec);
|
| 1744 |
eromero |
969 |
|
| 1735 |
eromero |
970 |
#undef __FUNCT__
|
|
|
971 |
#define __FUNCT__ "dvd_improvex_PfuncV"
|
| 2223 |
jroman |
972 |
/* Compute D <- K^{-1} * funcV[r_s..r_e] */
|
| 2021 |
eromero |
973 |
PetscErrorCode dvd_improvex_PfuncV(dvdDashboard *d, void *funcV, Vec *D,
|
|
|
974 |
PetscInt max_size_D, PetscInt r_s, PetscInt r_e, Vec *auxV,
|
|
|
975 |
PetscScalar *auxS)
|
| 1735 |
eromero |
976 |
{
|
|
|
977 |
PetscErrorCode ierr;
|
|
|
978 |
PetscInt i;
|
|
|
979 |
|
|
|
980 |
PetscFunctionBegin;
|
|
|
981 |
|
|
|
982 |
if (max_size_D >= r_e-r_s+1) {
|
|
|
983 |
/* The optimized version needs one vector extra of D */
|
|
|
984 |
/* D(1:r.size) = R(r_s:r_e-1) */
|
| 1751 |
eromero |
985 |
if (auxS) ((funcV1_t)funcV)(d, r_s, r_e, D+1, auxS, auxV[0]);
|
| 1744 |
eromero |
986 |
else ((funcV0_t)funcV)(d, r_s, r_e, D+1);
|
| 1735 |
eromero |
987 |
|
|
|
988 |
/* D = K^{-1} * R */
|
|
|
989 |
for (i=0; i<r_e-r_s; i++) {
|
| 1743 |
eromero |
990 |
ierr = d->improvex_precond(d, i+r_s, D[i+1], D[i]); CHKERRQ(ierr);
|
| 1735 |
eromero |
991 |
}
|
|
|
992 |
} else if (max_size_D == r_e-r_s) {
|
|
|
993 |
/* Non-optimized version */
|
|
|
994 |
/* auxV <- R[r_e-1] */
|
| 1751 |
eromero |
995 |
if (auxS) ((funcV1_t)funcV)(d, r_e-1, r_e, auxV, auxS, auxV[1]);
|
|
|
996 |
else ((funcV0_t)funcV)(d, r_e-1, r_e, auxV);
|
| 1735 |
eromero |
997 |
|
|
|
998 |
/* D(1:r.size-1) = R(r_s:r_e-2) */
|
| 1751 |
eromero |
999 |
if (auxS) ((funcV1_t)funcV)(d, r_s, r_e-1, D+1, auxS, auxV[1]);
|
| 1744 |
eromero |
1000 |
else ((funcV0_t)funcV)(d, r_s, r_e-1, D+1);
|
| 1735 |
eromero |
1001 |
|
|
|
1002 |
/* D = K^{-1} * R */
|
|
|
1003 |
for (i=0; i<r_e-r_s-1; i++) {
|
| 1743 |
eromero |
1004 |
ierr = d->improvex_precond(d, i+r_s, D[i+1], D[i]); CHKERRQ(ierr);
|
| 1735 |
eromero |
1005 |
}
|
| 1751 |
eromero |
1006 |
ierr = d->improvex_precond(d, r_e-1, auxV[0], D[r_e-r_s-1]); CHKERRQ(ierr);
|
| 1735 |
eromero |
1007 |
} else {
|
| 2214 |
jroman |
1008 |
SETERRQ(PETSC_COMM_SELF,1, "Problem: r_e-r_s > max_size_D!");
|
| 1735 |
eromero |
1009 |
}
|
|
|
1010 |
|
|
|
1011 |
PetscFunctionReturn(0);
|
|
|
1012 |
}
|
|
|
1013 |
|
|
|
1014 |
|
| 2223 |
jroman |
1015 |
#undef __FUNCT__
|
|
|
1016 |
#define __FUNCT__ "dvd_improvex_get_eigenvectors"
|
| 1965 |
eromero |
1017 |
/* Compute the left and right projected eigenvectors where,
|
|
|
1018 |
pX, the returned right eigenvectors
|
|
|
1019 |
pY, the returned left eigenvectors,
|
|
|
1020 |
ld_, the leading dimension of pX and pY,
|
|
|
1021 |
auxS, auxiliar vector of size length 6*d->size_H
|
|
|
1022 |
*/
|
| 2021 |
eromero |
1023 |
PetscErrorCode dvd_improvex_get_eigenvectors(dvdDashboard *d, PetscScalar *pX,
|
|
|
1024 |
PetscScalar *pY, PetscInt ld, PetscScalar *auxS, PetscInt size_auxS)
|
| 1965 |
eromero |
1025 |
{
|
|
|
1026 |
PetscErrorCode ierr;
|
|
|
1027 |
|
|
|
1028 |
PetscFunctionBegin;
|
|
|
1029 |
|
| 1968 |
eromero |
1030 |
ierr = SlepcDenseCopy(pY, ld, d->T?d->pY:d->pX, d->ldpX, d->size_H,
|
| 1965 |
eromero |
1031 |
d->size_H); CHKERRQ(ierr);
|
| 1968 |
eromero |
1032 |
ierr = SlepcDenseCopy(pX, ld, d->pX, d->ldpX, d->size_H, d->size_H);
|
| 1965 |
eromero |
1033 |
CHKERRQ(ierr);
|
|
|
1034 |
|
| 1968 |
eromero |
1035 |
/* [qX, qY] <- eig(S, T); pX <- d->pX * qX; pY <- d->pY * qY */
|
|
|
1036 |
ierr = dvd_compute_eigenvectors(d->size_H, d->S, d->ldS, d->T, d->ldT, pX,
|
| 1969 |
eromero |
1037 |
ld, pY, ld, auxS, size_auxS, PETSC_TRUE);
|
|
|
1038 |
CHKERRQ(ierr);
|
| 1965 |
eromero |
1039 |
|
|
|
1040 |
/* 2-Normalize the columns of pX an pY */
|
| 1968 |
eromero |
1041 |
ierr = SlepcDenseNorm(pX, ld, d->size_H, d->size_H, d->eigi); CHKERRQ(ierr);
|
|
|
1042 |
ierr = SlepcDenseNorm(pY, ld, d->size_H, d->size_H, d->eigi); CHKERRQ(ierr);
|
| 1965 |
eromero |
1043 |
|
|
|
1044 |
PetscFunctionReturn(0);
|
|
|
1045 |
}
|
| 2605 |
eromero |
1046 |
|
|
|
1047 |
#undef __FUNCT__
|
|
|
1048 |
#define __FUNCT__ "dvd_improvex_apply_proj"
|
|
|
1049 |
/* Compute (I - KZ*iXKZ*X')*V where,
|
|
|
1050 |
V, the vectors to apply the projector,
|
|
|
1051 |
cV, the number of vectors in V,
|
|
|
1052 |
auxS, auxiliar vector of size length 3*size_iXKZ*cV
|
|
|
1053 |
*/
|
|
|
1054 |
PetscErrorCode dvd_improvex_apply_proj(dvdDashboard *d, Vec *V, PetscInt cV, PetscScalar *auxS)
|
|
|
1055 |
{
|
|
|
1056 |
PetscErrorCode ierr;
|
|
|
1057 |
dvdImprovex_jd *data = (dvdImprovex_jd*)d->improveX_data;
|
|
|
1058 |
PetscInt size_in = data->size_iXKZ*cV, i, ldh;
|
|
|
1059 |
PetscScalar *h, *in, *out;
|
|
|
1060 |
PetscBLASInt cV_, n, info, ld;
|
|
|
1061 |
DvdReduction r;
|
|
|
1062 |
DvdReductionChunk
|
|
|
1063 |
ops[4];
|
|
|
1064 |
DvdMult_copy_func
|
|
|
1065 |
sr[4];
|
|
|
1066 |
|
|
|
1067 |
PetscFunctionBegin;
|
|
|
1068 |
|
|
|
1069 |
/* Check consistency */
|
|
|
1070 |
if (cV > 2) { SETERRQ(PETSC_COMM_SELF,1, "Consistency broken!"); }
|
|
|
1071 |
|
|
|
1072 |
/* h <- X'*V */
|
|
|
1073 |
h = auxS; in = h+size_in; out = in+size_in; ldh = data->size_iXKZ;
|
|
|
1074 |
ierr = SlepcAllReduceSumBegin(ops, 4, in, out, size_in, &r,
|
|
|
1075 |
((PetscObject)d->V[0])->comm); CHKERRQ(ierr);
|
|
|
1076 |
for (i=0; i<cV; i++) {
|
|
|
1077 |
ierr = VecsMultS(&h[i*ldh],0,ldh,d->V-data->size_KZ,0,data->size_KZ,V+i,0,1,&r,&sr[i*2]);CHKERRQ(ierr);
|
|
|
1078 |
ierr = VecsMultS(&h[i*ldh+data->size_KZ],0,ldh,data->u,0,data->size_iXKZ-data->size_KZ,V+i,0,1,&r,&sr[i*2+1]);CHKERRQ(ierr);
|
|
|
1079 |
}
|
|
|
1080 |
ierr = SlepcAllReduceSumEnd(&r); CHKERRQ(ierr);
|
|
|
1081 |
|
|
|
1082 |
/* h <- iXKZ\h */
|
|
|
1083 |
cV_ = PetscBLASIntCast(cV);
|
|
|
1084 |
n = PetscBLASIntCast(data->size_iXKZ);
|
|
|
1085 |
ld = PetscBLASIntCast(data->ldiXKZ);
|
|
|
1086 |
LAPACKgetrs_("N", &n, &cV_, data->iXKZ, &ld, data->iXKZPivots, h, &n, &info);
|
|
|
1087 |
if (info) SETERRQ1(PETSC_COMM_WORLD,PETSC_ERR_LIB, "Error in Lapack XGETRS %d", info);
|
|
|
1088 |
|
|
|
1089 |
/* V <- V - KZ*h */
|
|
|
1090 |
for (i=0; i<cV; i++) {
|
|
|
1091 |
ierr = SlepcUpdateVectorsZ(V+i,1.0,-1.0,data->KZ,data->size_iXKZ,&h[ldh*i],ldh,data->size_iXKZ,1);CHKERRQ(ierr);
|
|
|
1092 |
}
|
|
|
1093 |
|
|
|
1094 |
PetscFunctionReturn(0);
|
|
|
1095 |
}
|