Subversion Repositories slepc-dev

Rev

Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
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
}