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