Subversion Repositories slepc-dev

Rev

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