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: test for restarting, updateV, restartV
5
 
6
*/
7
 
1985 eromero 8
#include "davidson.h"
1619 slepc 9
 
10
PetscTruth dvd_isrestarting_fullV(dvdDashboard *d);
2021 eromero 11
PetscErrorCode dvd_managementV_basic_d(dvdDashboard *d);
12
PetscErrorCode dvd_updateV_extrapol(dvdDashboard *d);
1795 eromero 13
PetscErrorCode dvd_updateV_conv_gen(dvdDashboard *d);
14
PetscErrorCode dvd_updateV_restart_gen(dvdDashboard *d);
15
PetscErrorCode dvd_updateV_update_gen(dvdDashboard *d);
2034 eromero 16
PetscErrorCode dvd_updateV_conv_finish(dvdDashboard *d);
2018 eromero 17
PetscErrorCode dvd_updateV_testConv(dvdDashboard *d, PetscInt s, PetscInt pre,
18
                                    PetscInt e, Vec *auxV, PetscScalar *auxS,
19
                                    PetscInt *nConv);
1795 eromero 20
PetscErrorCode dvd_updateV_restartV_aux(Vec *V, PetscInt size_V,
21
                                        PetscScalar *U, PetscInt ldU,
22
                                        PetscScalar *pX, PetscInt ldpX,
23
                                        PetscInt cpX, PetscScalar *oldpX,
24
                                        PetscInt ldoldpX, PetscInt roldpX,
25
                                        PetscInt coldpX, PetscScalar *auxS,
26
                                        PetscInt size_auxS,
27
                                        PetscInt *new_size_V);
28
PetscErrorCode dvd_updateV_YtWx(PetscScalar *S, PetscInt ldS,
1883 eromero 29
                                Vec *Y, PetscInt cY, Vec *y, PetscInt cy,
30
                                Vec *W, PetscInt cW, PetscScalar *x,
31
                                PetscInt ldx,
32
                                PetscInt rx, PetscInt cx, Vec *auxV);
1619 slepc 33
typedef struct {
34
  PetscInt bs,      /* common number of approximated eigenpairs obtained */
35
    real_max_size_V,
36
                    /* real max size of V */
1743 eromero 37
    min_size_V,     /* restart with this number of eigenvectors */
2023 eromero 38
    plusk,          /* when restart, save plusk vectors from last iteration */
39
    mpd;            /* max size of the searching subspace */
1795 eromero 40
  Vec *real_V,      /* real start vectors V */
41
    *new_cY;        /* new left converged eigenvectors from the last iter */
1619 slepc 42
  void
43
    *old_updateV_data;
44
                    /* old updateV data */
45
  isRestarting_type
46
    old_isRestarting;
47
                    /* old isRestarting */
1743 eromero 48
  PetscScalar
1795 eromero 49
    *oldU,          /* previous projected right igenvectors */
50
    *oldV;          /* previous projected left eigenvectors */
1743 eromero 51
  PetscInt
52
    ldoldU,         /* leading dimension of oldU */
1795 eromero 53
    size_oldU,      /* size of oldU */
54
    size_new_cY;    /* size of new_cY */
2037 eromero 55
  PetscTruth
56
    allResiduals;   /* if computing all the residuals */
1619 slepc 57
} dvdManagV_basic;
58
 
59
#undef __FUNCT__  
60
#define __FUNCT__ "dvd_managementV_basic"
2021 eromero 61
PetscErrorCode dvd_managementV_basic(dvdDashboard *d, dvdBlackboard *b,
2023 eromero 62
                                     PetscInt bs, PetscInt max_size_V,
63
                                     PetscInt mpd, PetscInt min_size_V,
2037 eromero 64
                                     PetscInt plusk, PetscTruth harm,
65
                                     PetscTruth allResiduals)
1619 slepc 66
{
67
  PetscErrorCode  ierr;
68
  dvdManagV_basic *data;
1960 eromero 69
  PetscInt        i;
1619 slepc 70
 
71
  PetscFunctionBegin;
72
 
73
  /* Setting configuration constrains */
2023 eromero 74
  mpd = PetscMin(mpd, max_size_V);
75
  min_size_V = PetscMin(min_size_V, mpd-bs);
76
  b->max_size_X = PetscMax(b->max_size_X, PetscMax(bs, min_size_V));
1820 eromero 77
  b->max_size_auxV = PetscMax(PetscMax(b->max_size_auxV,
2023 eromero 78
                                       b->max_size_X /* updateV_conv_gen */ ),
1820 eromero 79
                                       2 /* testConv */ );
80
  b->max_size_auxS = PetscMax(PetscMax(PetscMax(b->max_size_auxS,
2023 eromero 81
                              max_size_V*b->max_size_X /* YtWx */ ),
1820 eromero 82
                              max_size_V*2 /* SlepcDenseOrth  */ ),
83
                              max_size_V*b->max_size_X /* testConv:res_0 */ );
2023 eromero 84
  b->max_size_V = mpd;
1795 eromero 85
  b->own_vecs+= max_size_V*(harm==PETSC_TRUE?2:1);      /* V, W? */
2023 eromero 86
  b->own_scalars+= max_size_V*2 /* eigr, eigr */ +
87
                   max_size_V /* nR */   +
88
                   max_size_V /* nX */   +
89
                   max_size_V /* errest */ +
1795 eromero 90
                   2*b->max_size_V*b->max_size_V*(harm==PETSC_TRUE?2:1)
2023 eromero 91
                                               /* MTX,MTY?,oldU,oldV? */;
1735 eromero 92
//  b->max_size_oldX = plusk;
1619 slepc 93
 
94
  /* Setup the step */
95
  if (b->state >= DVD_STATE_CONF) {
96
    ierr = PetscMalloc(sizeof(dvdManagV_basic), &data); CHKERRQ(ierr);
97
    data->real_max_size_V = max_size_V;
1735 eromero 98
    data->min_size_V = min_size_V;
1619 slepc 99
    data->real_V = b->free_vecs; b->free_vecs+= max_size_V;
100
    data->bs = bs;
1743 eromero 101
    data->plusk = plusk;
1820 eromero 102
    data->new_cY = PETSC_NULL;
103
    data->size_new_cY = 0;
2023 eromero 104
    data->mpd = mpd;
2037 eromero 105
    data->allResiduals = allResiduals;
1619 slepc 106
 
107
    d->V = data->real_V;
108
    d->max_size_V = data->real_max_size_V;
109
    d->cX = data->real_V;
2023 eromero 110
    d->eigr = b->free_scalars; b->free_scalars+= max_size_V;
111
    d->eigi = b->free_scalars; b->free_scalars+= max_size_V;
1883 eromero 112
#ifdef PETSC_USE_COMPLEX
2023 eromero 113
    for(i=0; i<max_size_V; i++) d->eigi[i] = 0.0;
1619 slepc 114
#endif
1735 eromero 115
    d->nR = (PetscReal*)b->free_scalars;
2023 eromero 116
    b->free_scalars = (PetscScalar*)(d->nR + max_size_V);
117
    for(i=0; i<max_size_V; i++) d->nR[i] = PETSC_MAX;
1764 eromero 118
    d->nX = (PetscReal*)b->free_scalars;
2023 eromero 119
    b->free_scalars = (PetscScalar*)(d->nX + max_size_V);
1735 eromero 120
    d->errest = (PetscReal*)b->free_scalars;
2023 eromero 121
    b->free_scalars = (PetscScalar*)(d->errest + max_size_V);
1619 slepc 122
    d->ceigr = d->eigr;
123
    d->ceigi = d->eigi;
1795 eromero 124
    d->MTX = b->free_scalars; b->free_scalars+= b->max_size_V*b->max_size_V;
1743 eromero 125
    data->oldU = b->free_scalars; b->free_scalars+= b->max_size_V*b->max_size_V;
1820 eromero 126
    data->ldoldU = 0;
127
    data->oldV = PETSC_NULL;
128
    d->W = PETSC_NULL;
129
    d->MTY = PETSC_NULL;
130
    d->ldMTY = 0;
1795 eromero 131
    if (harm == PETSC_TRUE) {
132
      d->W = b->free_vecs; b->free_vecs+= max_size_V;
133
      d->MTY = b->free_scalars; b->free_scalars+= b->max_size_V*b->max_size_V;
134
      data->oldV = b->free_scalars; b->free_scalars+= b->max_size_V*b->max_size_V;
135
    }
1829 eromero 136
 
1743 eromero 137
    data->size_oldU = 0;
1619 slepc 138
    data->old_updateV_data = d->updateV_data;
139
    d->updateV_data = data;
140
    data->old_isRestarting = d->isRestarting;
141
    d->isRestarting = dvd_isrestarting_fullV;
1795 eromero 142
    d->updateV = dvd_updateV_extrapol;
2018 eromero 143
    d->preTestConv = dvd_updateV_testConv;
2034 eromero 144
    DVD_FL_ADD(d->endList, dvd_updateV_conv_finish);
1619 slepc 145
    DVD_FL_ADD(d->destroyList, dvd_managementV_basic_d);
146
  }
147
 
148
  PetscFunctionReturn(0);
149
}
150
 
151
#undef __FUNCT__  
152
#define __FUNCT__ "dvd_isrestarting_fullV"
153
PetscTruth dvd_isrestarting_fullV(dvdDashboard *d)
154
{
155
  PetscTruth      restart;
156
  dvdManagV_basic *data = (dvdManagV_basic*)d->updateV_data;
157
 
158
  PetscFunctionBegin;
159
 
2023 eromero 160
  /* Take into account the possibility of conjugate eigenpairs */
161
#if defined(PETSC_USE_COMPLEX)
162
#define ONE 0
163
#else
164
#define ONE 1
165
#endif
1619 slepc 166
 
2023 eromero 167
  restart = (d->size_V + data->bs + ONE > PetscMin(data->mpd,d->max_size_V))?
168
                PETSC_TRUE:PETSC_FALSE;
169
 
170
#undef ONE
171
 
1619 slepc 172
  /* Check old isRestarting function */
173
  if ((restart == PETSC_FALSE) && (data->old_isRestarting))
174
    restart = data->old_isRestarting(d);
175
 
176
  PetscFunctionReturn(restart);
177
}
178
 
179
#undef __FUNCT__  
1735 eromero 180
#define __FUNCT__ "dvd_managementV_basic_d"
2021 eromero 181
PetscErrorCode dvd_managementV_basic_d(dvdDashboard *d)
1619 slepc 182
{
1735 eromero 183
  PetscErrorCode  ierr;
1619 slepc 184
  dvdManagV_basic *data = (dvdManagV_basic*)d->updateV_data;
185
 
186
  PetscFunctionBegin;
187
 
1735 eromero 188
  /* Restore changes in dvdDashboard */
189
  d->updateV_data = data->old_updateV_data;
190
 
191
  /* Free local data */
192
  ierr = PetscFree(data); CHKERRQ(ierr);
1653 slepc 193
 
1619 slepc 194
  PetscFunctionReturn(0);
195
}
196
 
197
#undef __FUNCT__  
1795 eromero 198
#define __FUNCT__ "dvd_updateV_extrapol"
2021 eromero 199
PetscErrorCode dvd_updateV_extrapol(dvdDashboard *d)
1619 slepc 200
{
201
  dvdManagV_basic *data = (dvdManagV_basic*)d->updateV_data;
1795 eromero 202
  PetscInt        i;
1619 slepc 203
  PetscErrorCode  ierr;
204
 
205
  PetscFunctionBegin;
206
 
1795 eromero 207
  /// Temporal! Copy the converged left eigenvectors to cY
208
  if (data->size_new_cY > 0) {
209
    for (i=0; i<data->size_new_cY; i++) {
210
      ierr = VecCopy(data->new_cY[i], d->cY[d->size_cY+i]); CHKERRQ(ierr);
211
    }
212
    d->size_cY+= data->size_new_cY;
213
    data->size_new_cY = 0;
214
  }
1743 eromero 215
 
2039 eromero 216
  ierr = d->calcpairs_selectPairs(d, data->min_size_V); CHKERRQ(ierr);
2033 eromero 217
 
2018 eromero 218
  /* If the subspaces doesn't need restart, add new vector */
219
  if (d->isRestarting(d) == PETSC_FALSE) {
220
    i = d->size_V;
221
    ierr = dvd_updateV_update_gen(d); CHKERRQ(ierr);
222
 
223
    /* If some vector were add, exit */
224
    if (i < d->size_V) { PetscFunctionReturn(0); }
225
  }
226
 
1972 eromero 227
  /* If some eigenpairs were converged, lock them  */
228
  if (d->npreconv > 0) {
229
    i = d->npreconv;
1795 eromero 230
    ierr = dvd_updateV_conv_gen(d); CHKERRQ(ierr);
1619 slepc 231
 
1972 eromero 232
    /* If some eigenpair was locked, exit */
233
    if (i > d->npreconv) { PetscFunctionReturn(0); }
234
  }
235
 
236
  /* Else, a restarting is performed */
237
  ierr = dvd_updateV_restart_gen(d); CHKERRQ(ierr);
238
 
1795 eromero 239
  PetscFunctionReturn(0);
240
}
1743 eromero 241
 
1795 eromero 242
#undef __FUNCT__  
243
#define __FUNCT__ "dvd_updateV_conv_gen"
244
PetscErrorCode dvd_updateV_conv_gen(dvdDashboard *d)
245
{
246
  dvdManagV_basic *data = (dvdManagV_basic*)d->updateV_data;
1883 eromero 247
  PetscInt        i, j, npreconv, ldpX, inc_V, cMT, size_cX, size_cy;
1795 eromero 248
  PetscErrorCode  ierr;
1883 eromero 249
  PetscScalar     *pX;
250
  PetscReal       norm;
251
  Vec             *new_cY=0, *cX, *cy;
1829 eromero 252
  PetscTruth      lindep;
1795 eromero 253
 
254
  PetscFunctionBegin;
255
 
1972 eromero 256
  /* If the left subspace is present, constrains the converged pairs to the
257
     number of free vectors in V */
258
  if (d->cY && d->pY)
259
    npreconv = PetscMin(d->max_size_V-d->size_V, d->npreconv);
260
  else
261
    npreconv = d->npreconv;
1795 eromero 262
 
1972 eromero 263
  /* Constrains the converged pairs to nev */
1966 eromero 264
#ifndef PETSC_USE_COMPLEX
1972 eromero 265
  /* Tries to maintain together conjugate eigenpairs */
266
  for(i = 0;
267
      (i + (d->eigi[i]!=0.0?1:0) < npreconv) && (d->nconv + i < d->nev);
268
      i+= (d->eigi[i]!=0.0?2:1));
269
  npreconv = i;
270
#else
271
  npreconv = PetscMax(PetscMin(d->nev - d->nconv, npreconv), 0);
1966 eromero 272
#endif
273
 
1972 eromero 274
  if (d->npreconv == 0) { PetscFunctionReturn(0); }
275
 
1795 eromero 276
  /* f.cY <- [f.cY f.V*f.pY(0:npreconv-1)] */
277
  if (d->cY && d->pY) {
278
    new_cY = &d->V[d->size_V];
279
    ierr = SlepcUpdateVectorsZ(new_cY, 0.0, 1.0, d->W?d->W:d->V, d->size_V,
280
                               d->pY, d->ldpY, d->size_H, npreconv);
1743 eromero 281
    CHKERRQ(ierr);
1972 eromero 282
 
1795 eromero 283
    /// Temporal! Postpone the copy of new_cY to cY
284
    data->new_cY = new_cY;
285
    data->size_new_cY = npreconv;
1972 eromero 286
  }
1743 eromero 287
 
2034 eromero 288
#if !defined(PETSC_USE_COMPLEX)
289
  /* Correct the order of the conjugate eigenpairs */
290
  if (d->T) for (i=0; i<npreconv; i++) if (d->eigi[i] != 0.0) {
291
    if (d->eigi[i] < 0.0) {
292
      d->eigi[i]*= -1.0;
293
      d->eigi[i+1]*= -1.0;
294
      for (j=0; j<d->size_H; j++) d->pX[j+(i+1)*d->ldpX]*= -1.0;
295
      for (j=0; j<d->size_H; j++) d->S[j+(i+1)*d->ldS]*= -1.0;
296
      for (j=0; j<d->size_H; j++) d->T[j+(i+1)*d->ldT]*= -1.0;
297
    }
298
    i++;
299
  }
300
#endif
301
 
1829 eromero 302
  /* BcX <- orth(BcX, B*cX),
303
     auxV = B*X, being X the last converged eigenvectors */
304
  if (d->BcX) for(i=0; i<npreconv; i++) {
305
    /* BcX <- [BcX auxV(i)] */
306
    ierr = VecCopy(d->auxV[i], d->BcX[d->size_cX+i]); CHKERRQ(ierr);
307
    ierr = IPOrthogonalize(d->ipI, 0, PETSC_NULL, d->size_cX+i, PETSC_NULL,
308
                           d->BcX, d->BcX[d->size_cX+i], PETSC_NULL,
309
                           &norm, &lindep); CHKERRQ(ierr);
310
    if(lindep == PETSC_TRUE) {
311
        SETERRQ(1, "Error during orth(BcX, B*cX(new))!");
312
    }
313
    ierr = VecScale(d->BcX[d->size_cX+i], 1.0/norm); CHKERRQ(ierr);
314
  }
315
 
1795 eromero 316
  /* Harmonics restarts wiht right eigenvectors, and other with
317
     the left ones */
1829 eromero 318
  pX = (d->W||!d->cY||d->BcX)?d->pX:d->pY;
319
  ldpX = (d->W||!d->cY||d->BcX)?d->ldpX:d->ldpY;
1795 eromero 320
 
1829 eromero 321
  /* If BcX, f.V <- orth(BcX, f.V) */
322
  if (d->BcX) cMT = 0;
323
  else        cMT = d->size_H - npreconv;
324
 
1795 eromero 325
  /* f.MTX <- pY(npreconv:size_H-1), f.MTY <- f.pY(npreconv:size_H-1) */
326
  d->ldMTX = d->ldMTY = d->size_H;
327
  d->size_MT = d->size_H;
328
  d->MT_type = DVD_MT_ORTHO;
1883 eromero 329
  ierr = SlepcDenseCopy(d->MTX, d->ldMTX, &pX[ldpX*npreconv], ldpX,
330
                        d->size_H, cMT); CHKERRQ(ierr);
1795 eromero 331
  if (d->W && d->pY) {
1883 eromero 332
    ierr = SlepcDenseCopy(d->MTY, d->ldMTY, &d->pY[d->ldpY*npreconv], d->ldpY,
333
                          d->size_H, cMT); CHKERRQ(ierr);
1743 eromero 334
  }
1795 eromero 335
 
336
  /* [f.cX(f.nconv) f.V] <- f.V*[f.pX(0:npreconv-1) f.pY(npreconv:f.size_V-1)] */
337
  if (&d->cX[d->nconv] == d->V) { /* cX and V are contiguous */
338
    ierr = SlepcDenseCopy(pX, ldpX, d->pX, d->ldpX, d->size_H, npreconv);
339
    CHKERRQ(ierr);
340
    ierr = SlepcUpdateVectorsZ(d->V, 0.0, 1.0, d->V, d->size_V, pX,
341
                               ldpX, d->size_H, d->size_H); CHKERRQ(ierr);
342
    d->V+= npreconv;
343
    inc_V = npreconv;
344
    d->max_size_V-= npreconv;
345
  } else {
346
    SETERRQ(1, "Untested case!");
347
    ierr = SlepcUpdateVectorsZ(&d->cX[d->nconv], 0.0, 1.0, d->V, d->size_V,
348
                               d->pX, d->ldpX, d->size_H, npreconv);
349
    CHKERRQ(ierr);
350
    ierr = SlepcUpdateVectorsZ(d->V, 0.0, 1.0, d->V, d->size_V,
351
                               &pX[ldpX*npreconv], ldpX,
352
                               d->size_H, cMT); CHKERRQ(ierr);
353
    inc_V = 0;
1743 eromero 354
  }
1795 eromero 355
  d->size_cX+= npreconv;
356
  d->size_V -= npreconv;
1630 slepc 357
 
1883 eromero 358
  /* Udpate cS and cT, if needed */
359
  if (d->cS) {
360
    PetscInt size_cS = d->size_cX-npreconv;
361
    cX = d->cY?d->cY:d->cX; size_cX = d->cY?d->size_cY:d->size_cX;
362
    cy = d->cY?new_cY:0; size_cy = d->cY?npreconv:0;
363
    ierr =
364
    dvd_updateV_YtWx(&d->cS[d->ldcS*size_cS], d->ldcS, cX, size_cX, cy,
365
                     size_cy, d->AV, d->size_AV,
366
                     d->pX, d->ldpX,
367
                     d->size_H, npreconv, d->auxV); CHKERRQ(ierr);
368
 
369
    if (DVD_ISNOT(d->sEP, DVD_EP_STD)) {if (d->BV) {
370
      ierr =
371
      dvd_updateV_YtWx(&d->cT[d->ldcT*size_cS], d->ldcT, cX, size_cX, cy,
372
                       size_cy, d->BV, d->size_AV,
373
                       d->pX, d->ldpX,
374
                       d->size_H, npreconv, d->auxV); CHKERRQ(ierr);
375
    } else if (!d->B) {
376
      ierr = VecsMultIa(&d->cT[d->ldcT*size_cS], 0, d->ldcT, cX, 0, size_cX,
377
                        &d->cX[size_cS], 0, npreconv); CHKERRQ(ierr);
378
      ierr = VecsMultIa(&d->cT[d->ldcT*size_cS+size_cX], 0, d->ldcT, cy, 0,
379
                        size_cy, &d->cX[size_cS], 0, npreconv); CHKERRQ(ierr);
380
    } else {
381
      /* TODO: Only for nprecond==1 */
382
      ierr = MatMult(d->B, d->cX[d->size_cX-1], d->auxV[0]); CHKERRQ(ierr);
383
      ierr = VecsMultIa(&d->cT[d->ldcT*size_cS], 0, d->ldcT, cX, 0, size_cX,
384
                        &d->auxV[0], 0, npreconv); CHKERRQ(ierr);
385
      ierr = VecsMultIa(&d->cT[d->ldcT*size_cS+size_cX], 0, d->ldcT, cy, 0,
386
                        size_cy, &d->auxV[0], 0, npreconv); CHKERRQ(ierr);
387
    }}
388
  }
389
 
1795 eromero 390
  /* f.W <- f.W * f.MTY */
391
  if (d->W) {
392
    ierr = SlepcUpdateVectorsZ(d->W, 0.0, 1.0, d->W, d->size_V+npreconv,
393
                               d->MTY, d->ldMTY, d->size_H, cMT);
394
    CHKERRQ(ierr);
395
  }
1619 slepc 396
 
1795 eromero 397
  /* Lock the converged pairs */
398
  d->eigr+= npreconv;
399
#ifndef PETSC_USE_COMPLEX
400
  if (d->eigi) d->eigi+= npreconv;
401
#endif
402
  d->nconv+= npreconv;
403
  d->errest+= npreconv;
1619 slepc 404
 
1795 eromero 405
  /* Notify the changes in V and update the other subspaces */
406
  d->V_imm_s = inc_V;             d->V_imm_e = inc_V;
407
  d->V_tra_s = 0;                 d->V_tra_e = cMT;
1829 eromero 408
  d->V_new_s = d->V_tra_e;        d->V_new_e = d->size_V;
1743 eromero 409
 
1795 eromero 410
  /* Remove oldU */
411
  data->size_oldU = 0;
1743 eromero 412
 
1795 eromero 413
  /* f.pX <- I, f.pY <- I */
2021 eromero 414
  d->ldpX = d->size_H;
415
  if (d->pY) d->ldpY = d->size_H;
1795 eromero 416
  for(i=0; i<d->size_H; i++) {
417
    for(j=0; j<d->size_H; j++) {
418
      d->pX[d->ldpX*i+j] = 0.0;
419
      if (d->pY) d->pY[d->ldpY*i+j] = 0.0;
1735 eromero 420
    }
1795 eromero 421
    d->pX[d->ldpX*i+i] = 1.0;
422
    if (d->pY) d->pY[d->ldpY*i+i] = 1.0;
1619 slepc 423
  }
424
 
1795 eromero 425
  d->npreconv-= npreconv;
426
 
1619 slepc 427
  PetscFunctionReturn(0);
428
}
429
 
430
#undef __FUNCT__  
2034 eromero 431
#define __FUNCT__ "dvd_updateV_conv_finish"
432
PetscErrorCode dvd_updateV_conv_finish(dvdDashboard *d)
433
{
434
  PetscErrorCode  ierr;
435
#if defined(PETSC_USE_COMPLEX)
436
  PetscInt        i, j;
437
  PetscScalar     s;
438
#endif  
439
 
440
  PetscFunctionBegin;
441
 
442
  /* Finish cS and cT */
443
  ierr = VecsMultIb(d->cS, 0, d->ldcS, d->nconv, d->nconv, d->auxS, d->V[0]);
444
  CHKERRQ(ierr);
445
  if (d->cT) {
446
    ierr = VecsMultIb(d->cT, 0, d->ldcT, d->nconv, d->nconv, d->auxS, d->V[0]);
447
    CHKERRQ(ierr);
448
  }
449
 
450
  /* Some functions need the diagonal elements in cT be real */
451
#if defined(PETSC_USE_COMPLEX)
452
  if (d->cT) for(i=0; i<d->nconv; i++) {
453
    s = PetscConj(d->cT[d->ldcT*i+i])/PetscAbsScalar(d->cT[d->ldcT*i+i]);
454
    for(j=0; j<=i; j++)
455
      d->cT[d->ldcT*i+j] = PetscRealPart(d->cT[d->ldcT*i+j]*s),
456
      d->cS[d->ldcS*i+j]*= s;
457
    ierr = VecScale(d->cX[i], s); CHKERRQ(ierr);
458
  }
459
#endif
460
 
461
  PetscFunctionReturn(0);
462
}
463
 
464
#undef __FUNCT__  
1795 eromero 465
#define __FUNCT__ "dvd_updateV_restart_gen"
466
PetscErrorCode dvd_updateV_restart_gen(dvdDashboard *d)
1750 eromero 467
{
468
  dvdManagV_basic *data = (dvdManagV_basic*)d->updateV_data;
1795 eromero 469
  PetscInt        size_plusk, size_X, new_size_X, i, j;
1750 eromero 470
  PetscErrorCode  ierr;
471
 
472
  PetscFunctionBegin;
473
 
1795 eromero 474
  /* Select size_X desired pairs from V */
475
  size_X = PetscMin(PetscMin(data->min_size_V,
476
                             d->size_V ),
477
                             d->max_size_V );
1750 eromero 478
 
1795 eromero 479
  /* Add plusk eigenvectors from the previous iteration */
480
  size_plusk = PetscMax(0, PetscMin(PetscMin(data->plusk,
481
                                    data->size_oldU ),
482
                                    d->max_size_V - size_X ));
1750 eromero 483
 
1795 eromero 484
  /* Modify the subspaces */
485
  d->ldMTX = d->size_MT = d->size_V;
486
  ierr = dvd_updateV_restartV_aux(d->V, d->size_V, d->MTX, d->ldMTX, d->pX,
487
                                  d->ldpX, size_X, data->oldU, data->ldoldU,
488
                                  data->size_oldU, size_plusk, d->auxS,
489
                                  d->size_auxS, &new_size_X); CHKERRQ(ierr);
490
  if (d->W && d->pY) {
491
    PetscInt new_size_Y;
492
    d->ldMTY = d->size_V;
493
    ierr = dvd_updateV_restartV_aux(d->W, d->size_V, d->MTY, d->ldMTY, d->pY,
494
                                    d->ldpY, size_X, data->oldV, data->ldoldU,
495
                                    data->size_oldU, new_size_X-size_X,
496
                                    d->auxS, d->size_auxS, &new_size_Y);
497
    CHKERRQ(ierr);
498
    new_size_X = PetscMin(new_size_X, new_size_Y);
499
  }
1751 eromero 500
 
1795 eromero 501
  /* Notify the changes in V and update the other subspaces */
502
  d->size_V = new_size_X;
503
  d->MT_type = DVD_MT_ORTHO;
504
  d->V_imm_s = 0;                 d->V_imm_e = 0;
505
  d->V_tra_s = 0;                 d->V_tra_e = new_size_X;
506
  d->V_new_s = d->V_tra_e;        d->V_new_e = d->V_tra_e;
1750 eromero 507
 
1795 eromero 508
  /* Remove oldU */
509
  data->size_oldU = 0;
1750 eromero 510
 
2037 eromero 511
  /* Remove npreconv */
1934 eromero 512
  d->npreconv = 0;
513
 
1795 eromero 514
  /* f.pX <- I, f.pY <- I */
2021 eromero 515
  d->ldpX = d->size_H;
516
  if (d->pY) d->ldpY = d->size_H;
1795 eromero 517
  for(i=0; i<d->size_H; i++) {
518
    for(j=0; j<d->size_H; j++) {
519
      d->pX[d->ldpX*i+j] = 0.0;
520
      if (d->pY) d->pY[d->ldpY*i+j] = 0.0;
1752 eromero 521
    }
1795 eromero 522
    d->pX[d->ldpX*i+i] = 1.0;
523
    if (d->pY) d->pY[d->ldpY*i+i] = 1.0;
524
  }
1752 eromero 525
 
1795 eromero 526
  PetscFunctionReturn(0);
527
}
1750 eromero 528
 
529
 
1795 eromero 530
#undef __FUNCT__  
531
#define __FUNCT__ "dvd_updateV_update_gen"
532
PetscErrorCode dvd_updateV_update_gen(dvdDashboard *d)
533
{
534
  dvdManagV_basic *data = (dvdManagV_basic*)d->updateV_data;
535
  PetscInt        size_D;
536
  PetscErrorCode  ierr;
1750 eromero 537
 
1795 eromero 538
  PetscFunctionBegin;
1750 eromero 539
 
540
  /* Select the desired pairs */
541
  size_D = PetscMin(PetscMin(PetscMin(data->bs,
542
                                      d->size_V ),
543
                                      d->max_size_V-d->size_V ),
544
                                      d->size_H );
545
  if (size_D == 0) {
546
    PetscPrintf(PETSC_COMM_WORLD, "MON: D:%d H:%d\n", size_D, d->size_H);
547
    d->initV(d);
548
    d->calcPairs(d);
549
    //SETERRQ(1, "D == 0!\n");
550
    //PetscFunctionReturn(1);
551
  }
552
 
553
//  PetscPrintf(PETSC_COMM_WORLD, "EIGS: ");
554
//  for(i=0; i<d->size_H; i++) PetscPrintf(PETSC_COMM_WORLD, "%d:%g ", i, d->eigr[i]);
555
//  PetscPrintf(PETSC_COMM_WORLD, "\n");
556
 
557
  /* Fill V with D */
2021 eromero 558
  ierr = d->improveX(d, d->V+d->size_V, d->max_size_V-d->size_V, 0, size_D,
559
                     &size_D); CHKERRQ(ierr);
1750 eromero 560
 
1972 eromero 561
  /* If D is empty, exit */
562
  if (size_D == 0) { PetscFunctionReturn(0); }
1965 eromero 563
 
1750 eromero 564
  /* Get the converged pairs */
2037 eromero 565
  ierr = dvd_updateV_testConv(d, 0, size_D,
566
    data->allResiduals==PETSC_TRUE?d->size_V:size_D, d->auxV, d->auxS,
567
    &d->npreconv); CHKERRQ(ierr);
1750 eromero 568
 
569
  /* Notify the changes in V */
570
  d->size_V+= size_D;
571
  d->size_D = size_D;
572
  d->V_imm_s = 0;                 d->V_imm_e = d->size_V-size_D;
573
  d->V_tra_s = 0;                 d->V_tra_e = 0;
574
  d->V_new_s = d->size_V-size_D;  d->V_new_e = d->size_V;
575
 
576
  /* Save the projected eigenvectors */
577
  if (data->plusk > 0) {
578
    data->ldoldU = data->size_oldU = d->size_H;
1795 eromero 579
    ierr = SlepcDenseCopy(data->oldU, data->ldoldU, d->pX, d->ldpX, d->size_H,
580
                          d->size_H); CHKERRQ(ierr);
581
    if (d->pY && d->W) {
582
      ierr = SlepcDenseCopy(data->oldV, data->ldoldU, d->pY, d->ldpY, d->size_H,
583
                            d->size_H); CHKERRQ(ierr);
1750 eromero 584
    }
585
  }
586
 
587
  PetscFunctionReturn(0);
588
}
589
 
590
 
591
#undef __FUNCT__  
1735 eromero 592
#define __FUNCT__ "dvd_updateV_testConv"
2018 eromero 593
PetscErrorCode dvd_updateV_testConv(dvdDashboard *d, PetscInt s, PetscInt pre,
594
                                    PetscInt e, Vec *auxV, PetscScalar *auxS,
595
                                                      PetscInt *nConv)
1619 slepc 596
{
1735 eromero 597
  PetscInt        i;
1966 eromero 598
#ifndef PETSC_USE_COMPLEX
599
  PetscInt        j;
600
#endif
1735 eromero 601
  PetscReal       norm;
1619 slepc 602
  PetscErrorCode  ierr;
2037 eromero 603
  PetscTruth      conv, c;
604
  dvdManagV_basic *data = (dvdManagV_basic*)d->updateV_data;
1619 slepc 605
 
606
  PetscFunctionBegin;
607
 
1743 eromero 608
  *nConv = s;
2037 eromero 609
  for(i=s, conv=PETSC_TRUE;
610
      (conv == PETSC_TRUE || data->allResiduals == PETSC_TRUE) && (i < e);
611
      i++) {
1764 eromero 612
    if (i >= pre) {
2037 eromero 613
      ierr = d->calcpairs_X(d, i, i+1, &auxV[1]); CHKERRQ(ierr);
1764 eromero 614
      if ((d->B) && DVD_IS(d->sEP, DVD_EP_STD)) {
615
        ierr = MatMult(d->B, auxV[1], auxV[0]); CHKERRQ(ierr);
616
      }
2021 eromero 617
      ierr = d->calcpairs_residual(d, i, i+1, auxV, auxS, auxV[1]);
618
      CHKERRQ(ierr);
1735 eromero 619
    }
1764 eromero 620
    norm = d->nR[i]/d->nX[i];
2037 eromero 621
    c = d->testConv(d, d->eigr[i], d->eigi[i], norm, &d->errest[i]);
622
    if (conv == PETSC_TRUE && c == PETSC_TRUE) *nConv = i+1;
623
    else conv = PETSC_FALSE;
1735 eromero 624
  }
2037 eromero 625
  pre = PetscMax(pre, i);
1966 eromero 626
 
627
#ifndef PETSC_USE_COMPLEX
628
  /* Enforce converged conjugate conjugate complex eigenpairs */
629
  for(j=0; j<*nConv; j++) if(d->eigi[j] != 0.0) j++;
630
  if(j > *nConv) (*nConv)--;
631
#endif
2037 eromero 632
  for(i=pre; i<e; i++) d->errest[i] = d->nR[i] = PETSC_MAX;
1735 eromero 633
 
1619 slepc 634
  PetscFunctionReturn(0);
635
}
636
 
1795 eromero 637
 
638
/*
639
  U <- [pX(0:size_X-1) gs(pX(0:size_X-1), oldpX(0:size_plusk-1))]
640
  V <- V * U,
641
  where
642
  new_size_V, return the new size of V
643
  auxS, auxiliar vector of size 2*ldpX, at least
644
  size_auxS, the size of auxS
645
*/
646
#undef __FUNCT__  
647
#define __FUNCT__ "dvd_updateV_restartV_aux"
648
PetscErrorCode dvd_updateV_restartV_aux(Vec *V, PetscInt size_V,
649
                                        PetscScalar *U, PetscInt ldU,
650
                                        PetscScalar *pX, PetscInt ldpX,
651
                                        PetscInt cpX, PetscScalar *oldpX,
652
                                        PetscInt ldoldpX, PetscInt roldpX,
653
                                        PetscInt coldpX, PetscScalar *auxS,
654
                                        PetscInt size_auxS,
655
                                        PetscInt *new_size_V)
656
{
657
  PetscInt        i, j;
658
  PetscErrorCode  ierr;
659
 
660
  PetscFunctionBegin;
661
 
662
  /* Add the size_X best eigenpairs */
663
  ierr = SlepcDenseCopy(U, ldU, pX, ldpX, size_V, cpX); CHKERRQ(ierr);
664
 
665
  /* Add plusk eigenvectors from the previous iteration */
666
  ierr = SlepcDenseCopy(&U[cpX*ldU], ldU, oldpX, ldoldpX, roldpX, coldpX);
667
  CHKERRQ(ierr);
668
  for(i=cpX; i<cpX+coldpX; i++)
669
    for(j=roldpX; j<size_V; j++)
670
        U[i*ldU+j] = 0.0;
671
 
672
  /* U <- orth(U) */
673
  /// Temporal! Correct sentence: U <- orth(U(0:size_X-1), U(size_X:size_X+size_plusk))
674
  if (coldpX > 0) {
675
    ierr = SlepcDenseOrth(U, ldU, size_V, cpX+coldpX, auxS, size_auxS,
676
                          new_size_V); CHKERRQ(ierr);
677
  } else
678
    *new_size_V = cpX;
679
 
680
  /* V <- V * U */
681
  ierr = SlepcUpdateVectorsZ(V, 0.0, 1.0, V, size_V, U, ldU, size_V,
682
                             *new_size_V); CHKERRQ(ierr);
683
 
684
  PetscFunctionReturn(0);
685
}
686
 
687
/*
1883 eromero 688
  Compute S = [ Y' * W * x
689
                y' * W * x ]
1795 eromero 690
  where
691
  ldS, the leading dimension of S,
692
  cY, number of vectors of Y,
693
  ldy, the leading dimension of y,
694
  ry,cy, rows and columns of y,
695
  cW, number of vectors of W,
696
  ldH, the leading dimension of H,
697
  rH,cH, rows and columns of H,
698
  ldx, the leading dimension of y,
699
  rx,cx, rows and columns of x,
700
  r, a reduction,
701
  sr, a permanent space,
1829 eromero 702
  auxV, array of auxiliar vectors of size cx (at the end, auxV <- W*x),
1795 eromero 703
  auxS, auxiliar scalar vector of size rH*cx.
704
*/
705
#undef __FUNCT__
706
#define __FUNCT__ "dvd_updateV_YtWx"
707
PetscErrorCode dvd_updateV_YtWx(PetscScalar *S, PetscInt ldS,
1883 eromero 708
                                Vec *Y, PetscInt cY, Vec *y, PetscInt cy,
709
                                Vec *W, PetscInt cW, PetscScalar *x,
710
                                PetscInt ldx,
711
                                PetscInt rx, PetscInt cx, Vec *auxV)
1795 eromero 712
{
713
  PetscErrorCode  ierr;
714
 
715
  PetscFunctionBegin;
716
 
717
  /* auxV <- W * x */
718
  ierr = SlepcUpdateVectorsZ(auxV, 0.0, 1.0, W, cW, x, ldx, rx, cx);
719
  CHKERRQ(ierr);
720
 
721
  /* S(0:cY-1, 0:cx-1) <- Y' * auxV */
722
  ierr = VecsMultIa(S, 0, ldS, Y, 0, cY, auxV, 0, cx); CHKERRQ(ierr);
723
 
1883 eromero 724
  /* S(cY:cY+cy-1, 0:cx-1) <- y' * auxV */
725
  ierr = VecsMultIa(&S[cY], 0, ldS, y, 0, cy, auxV, 0, cx); CHKERRQ(ierr);
1795 eromero 726
 
727
  PetscFunctionReturn(0);
728
}
729