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
1302 slepc 1
/*
2
     Routines related to orthogonalization.
1303 slepc 3
     See the SLEPc Technical Report STR-1 for a detailed explanation.
1376 slepc 4
 
5
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6
      SLEPc - Scalable Library for Eigenvalue Problem Computations
7
      Copyright (c) 2002-2007, Universidad Politecnica de Valencia, Spain
8
 
9
      This file is part of SLEPc. See the README file for conditions of use
10
      and additional information.
11
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1302 slepc 12
*/
1376 slepc 13
 
1521 slepc 14
#include "private/ipimpl.h"      /*I "slepcip.h" I*/
1302 slepc 15
#include "slepcblaslapack.h"
16
 
17
/*
1307 slepc 18
   IPOrthogonalizeMGS - Compute one step of Modified Gram-Schmidt
1302 slepc 19
*/
20
#undef __FUNCT__  
1307 slepc 21
#define __FUNCT__ "IPOrthogonalizeMGS"
1509 slepc 22
static PetscErrorCode IPOrthogonalizeMGS(IP ip,PetscInt n,PetscTruth *which,Vec *V,Vec v,PetscScalar *H)
1302 slepc 23
{
24
  PetscErrorCode ierr;
1509 slepc 25
  PetscInt       j;
1307 slepc 26
 
27
  PetscFunctionBegin;
28
  for (j=0; j<n; j++)
29
    if (!which || which[j]) {
30
      /* h_j = ( v, v_j ) */
31
      ierr = IPInnerProduct(ip,v,V[j],&H[j]);CHKERRQ(ierr);
32
      /* v <- v - h_j v_j */
33
      ierr = VecAXPY(v,-H[j],V[j]);CHKERRQ(ierr);
34
    }
35
  PetscFunctionReturn(0);
36
}
37
 
38
/*
39
   IPOrthogonalizeCGS - Compute |v'| (estimated), |v| and one step of CGS with only one global synchronization
40
*/
41
#undef __FUNCT__  
42
#define __FUNCT__ "IPOrthogonalizeCGS"
1509 slepc 43
PetscErrorCode IPOrthogonalizeCGS(IP ip,PetscInt n,PetscTruth *which,Vec *V,Vec v,PetscScalar *H,PetscReal *onorm,PetscReal *norm,Vec work)
1307 slepc 44
{
45
  PetscErrorCode ierr;
1509 slepc 46
  PetscInt       j;
1302 slepc 47
  PetscScalar    alpha;
48
  PetscReal      sum;
49
 
50
  PetscFunctionBegin;
1307 slepc 51
  /* h = W^* v ; alpha = (v , v) */
52
  if (which) {
53
  /* use select array */
54
    for (j=0; j<n; j++)
1329 slepc 55
      if (which[j]) { ierr = IPInnerProductBegin(ip,v,V[j],&H[j]);CHKERRQ(ierr); }
1307 slepc 56
    if (onorm || norm) { ierr = IPInnerProductBegin(ip,v,v,&alpha);CHKERRQ(ierr); }
57
    for (j=0; j<n; j++)
58
      if (which[j]) { ierr = IPInnerProductEnd(ip,v,V[j],&H[j]);CHKERRQ(ierr); }
59
    if (onorm || norm) { ierr = IPInnerProductEnd(ip,v,v,&alpha);CHKERRQ(ierr); }
60
  } else { /* merge comunications */
61
    if (onorm || norm) {
1381 slepc 62
      ierr = IPMInnerProductBegin(ip,v,n,V,H);CHKERRQ(ierr);
1307 slepc 63
      ierr = IPInnerProductBegin(ip,v,v,&alpha);CHKERRQ(ierr);
1381 slepc 64
      ierr = IPMInnerProductEnd(ip,v,n,V,H);CHKERRQ(ierr);
1307 slepc 65
      ierr = IPInnerProductEnd(ip,v,v,&alpha);CHKERRQ(ierr);
66
    } else { /* use simpler function */
1381 slepc 67
      ierr = IPMInnerProduct(ip,v,n,V,H);CHKERRQ(ierr);
1302 slepc 68
    }
1307 slepc 69
  }
1302 slepc 70
 
1307 slepc 71
  /* q = v - V h */
1329 slepc 72
  ierr = VecSet(work,0.0);CHKERRQ(ierr);
1307 slepc 73
  if (which) {
74
    for (j=0; j<n; j++)
1329 slepc 75
      if (which[j]) { ierr = VecAXPY(work,H[j],V[j]);CHKERRQ(ierr); }
1307 slepc 76
  } else {
1329 slepc 77
    ierr = VecMAXPY(work,n,H,V);CHKERRQ(ierr);  
1307 slepc 78
  }
1329 slepc 79
  ierr = VecAXPY(v,-1.0,work);CHKERRQ(ierr);
1302 slepc 80
 
1307 slepc 81
  /* compute |v| */
82
  if (onorm) *onorm = sqrt(PetscRealPart(alpha));
83
 
84
  /* compute |v'| */
85
  if (norm) {
86
    sum = 0.0;
87
    for (j=0; j<n; j++)
88
      if (!which || which[j])
89
        sum += PetscRealPart(H[j] * PetscConj(H[j]));
90
    *norm = PetscRealPart(alpha)-sum;
1329 slepc 91
    if (*norm <= 0.0) {
1307 slepc 92
      ierr = IPNorm(ip,v,norm);CHKERRQ(ierr);
93
    } else *norm = sqrt(*norm);
94
  }
95
  PetscFunctionReturn(0);
96
}
97
 
98
/*
99
   IPOrthogonalizeGS - Compute |v'|, |v| and one step of CGS or MGS
100
*/
101
#undef __FUNCT__  
102
#define __FUNCT__ "IPOrthogonalizeGS"
1509 slepc 103
static PetscErrorCode IPOrthogonalizeGS(IP ip,PetscInt n,PetscTruth *which,Vec *V,Vec v,PetscScalar *H,PetscReal *onorm,PetscReal *norm,Vec work)
1307 slepc 104
{
105
  PetscErrorCode ierr;
106
 
107
  PetscFunctionBegin;
108
  switch (ip->orthog_type) {
109
  case IP_CGS_ORTH:
1329 slepc 110
    ierr = IPOrthogonalizeCGS(ip,n,which,V,v,H,onorm,norm,work);CHKERRQ(ierr);
1302 slepc 111
    break;
112
  case IP_MGS_ORTH:
113
    /* compute |v| */
114
    if (onorm) { ierr = IPNorm(ip,v,onorm);CHKERRQ(ierr); }
1307 slepc 115
    ierr = IPOrthogonalizeMGS(ip,n,which,V,v,H);CHKERRQ(ierr);
1302 slepc 116
    /* compute |v'| */
117
    if (norm) { ierr = IPNorm(ip,v,norm);CHKERRQ(ierr); }
118
    break;
119
  default:
120
    SETERRQ(PETSC_ERR_ARG_WRONG,"Unknown orthogonalization type");
121
  }
122
  PetscFunctionReturn(0);
123
}
124
 
125
#undef __FUNCT__  
126
#define __FUNCT__ "IPOrthogonalize"
127
/*@
128
   IPOrthogonalize - Orthogonalize a vector with respect to a set of vectors.
129
 
130
   Collective on IP
131
 
132
   Input Parameters:
1303 slepc 133
+  ip    - the inner product (IP) context
1302 slepc 134
.  n      - number of columns of V
135
.  which  - logical array indicating columns of V to be used
1381 slepc 136
.  V      - set of vectors
137
-  work   - workspace vector
1302 slepc 138
 
139
   Input/Output Parameter:
140
.  v      - (input) vector to be orthogonalized and (output) result of
141
            orthogonalization
142
 
143
   Output Parameter:
144
+  H      - coefficients computed during orthogonalization
145
.  norm   - norm of the vector after being orthogonalized
146
-  lindep - flag indicating that refinement did not improve the quality
147
            of orthogonalization
148
 
149
   Notes:
150
   This function applies an orthogonal projector to project vector v onto the
151
   orthogonal complement of the span of the columns of V.
152
 
153
   On exit, v0 = [V v]*H, where v0 is the original vector v.
154
 
155
   This routine does not normalize the resulting vector.
156
 
157
   Level: developer
158
 
159
.seealso: IPSetOrthogonalization(), IPBiOrthogonalize()
160
@*/
1509 slepc 161
PetscErrorCode IPOrthogonalize(IP ip,PetscInt n,PetscTruth *which,Vec *V,Vec v,PetscScalar *H,PetscReal *norm,PetscTruth *lindep,Vec work)
1302 slepc 162
{
163
  PetscErrorCode ierr;
164
  PetscScalar    lh[100],*h,lc[100],*c;
1345 slepc 165
  PetscTruth     allocatedh = PETSC_FALSE,allocatedc = PETSC_FALSE,allocatedw = PETSC_FALSE;
1302 slepc 166
  PetscReal      onrm,nrm;
1509 slepc 167
  PetscInt       j,k;
1302 slepc 168
  PetscFunctionBegin;
169
  if (n==0) {
170
    if (norm) { ierr = IPNorm(ip,v,norm);CHKERRQ(ierr); }
171
    if (lindep) *lindep = PETSC_FALSE;
172
    PetscFunctionReturn(0);
173
  }
174
  ierr = PetscLogEventBegin(IP_Orthogonalize,ip,0,0,0);CHKERRQ(ierr);
175
 
1345 slepc 176
  /* allocate H, c and work if needed */
1302 slepc 177
  if (!H) {
178
    if (n<=100) h = lh;
179
    else {
180
      ierr = PetscMalloc(n*sizeof(PetscScalar),&h);CHKERRQ(ierr);
181
      allocatedh = PETSC_TRUE;
182
    }
183
  } else h = H;
184
  if (ip->orthog_ref != IP_ORTH_REFINE_NEVER) {
185
    if (n<=100) c = lc;
186
    else {
187
      ierr = PetscMalloc(n*sizeof(PetscScalar),&c);CHKERRQ(ierr);
188
      allocatedc = PETSC_TRUE;
189
    }
190
  }
1436 slepc 191
  if (!work && ip->orthog_type == IP_CGS_ORTH) {
1345 slepc 192
    ierr = VecDuplicate(v,&work);CHKERRQ(ierr);
1348 slepc 193
    allocatedw = PETSC_TRUE;
1345 slepc 194
  }
1302 slepc 195
 
196
  /* orthogonalize and compute onorm */
197
  switch (ip->orthog_ref) {
198
 
199
  case IP_ORTH_REFINE_NEVER:
1329 slepc 200
    ierr = IPOrthogonalizeGS(ip,n,which,V,v,h,PETSC_NULL,PETSC_NULL,work);CHKERRQ(ierr);
1302 slepc 201
    /* compute |v| */
202
    if (norm) { ierr = IPNorm(ip,v,norm);CHKERRQ(ierr); }
203
    /* linear dependence check does not work without refinement */
204
    if (lindep) *lindep = PETSC_FALSE;
205
    break;
206
 
207
  case IP_ORTH_REFINE_ALWAYS:
1329 slepc 208
    ierr = IPOrthogonalizeGS(ip,n,which,V,v,h,PETSC_NULL,PETSC_NULL,work);CHKERRQ(ierr);
1302 slepc 209
    if (lindep) {
1329 slepc 210
      ierr = IPOrthogonalizeGS(ip,n,which,V,v,c,&onrm,&nrm,work);CHKERRQ(ierr);
1302 slepc 211
      if (norm) *norm = nrm;
212
      if (nrm < ip->orthog_eta * onrm) *lindep = PETSC_TRUE;
213
      else *lindep = PETSC_FALSE;
214
    } else {
1329 slepc 215
      ierr = IPOrthogonalizeGS(ip,n,which,V,v,c,PETSC_NULL,norm,work);CHKERRQ(ierr);
1302 slepc 216
    }
217
    for (j=0;j<n;j++)
218
      if (!which || which[j]) h[j] += c[j];
219
    break;
220
 
221
  case IP_ORTH_REFINE_IFNEEDED:
1329 slepc 222
    ierr = IPOrthogonalizeGS(ip,n,which,V,v,h,&onrm,&nrm,work);CHKERRQ(ierr);
1302 slepc 223
    /* ||q|| < eta ||h|| */
224
    k = 1;
225
    while (k<3 && nrm < ip->orthog_eta * onrm) {
226
      k++;
227
      switch (ip->orthog_type) {
228
      case IP_CGS_ORTH:
1329 slepc 229
        ierr = IPOrthogonalizeGS(ip,n,which,V,v,c,&onrm,&nrm,work);CHKERRQ(ierr);
1302 slepc 230
        break;
231
      case IP_MGS_ORTH:
232
        onrm = nrm;
1329 slepc 233
        ierr = IPOrthogonalizeGS(ip,n,which,V,v,c,PETSC_NULL,&nrm,work);CHKERRQ(ierr);
1302 slepc 234
        break;
235
      default:
236
        SETERRQ(PETSC_ERR_ARG_WRONG,"Unknown orthogonalization type");
237
      }        
238
      for (j=0;j<n;j++)
239
        if (!which || which[j]) h[j] += c[j];
240
    }
241
    if (norm) *norm = nrm;
242
    if (lindep) {
243
      if (nrm < ip->orthog_eta * onrm) *lindep = PETSC_TRUE;
244
      else *lindep = PETSC_FALSE;
245
    }
246
 
247
    break;
248
  default:
249
    SETERRQ(PETSC_ERR_ARG_WRONG,"Unknown orthogonalization refinement");
250
  }
251
 
252
  /* free work space */
253
  if (allocatedc) { ierr = PetscFree(c);CHKERRQ(ierr); }
254
  if (allocatedh) { ierr = PetscFree(h);CHKERRQ(ierr); }
1345 slepc 255
  if (allocatedw) { ierr = VecDestroy(work);CHKERRQ(ierr); }
1302 slepc 256
 
257
  ierr = PetscLogEventEnd(IP_Orthogonalize,ip,0,0,0);CHKERRQ(ierr);
258
  PetscFunctionReturn(0);
259
}
1345 slepc 260
 
261
#undef __FUNCT__  
262
#define __FUNCT__ "IPQRDecomposition"
263
/*@
264
   IPQRDecomposition - Compute the QR factorization of a set of vectors.
265
 
266
   Collective on IP
267
 
268
   Input Parameters:
269
+  ip - the eigenproblem solver context
270
.  V - set of vectors
271
.  m - starting column
272
.  n - ending column
1381 slepc 273
.  ldr - leading dimension of R
274
-  work - workspace vector
1345 slepc 275
 
276
   Output Parameter:
277
.  R  - triangular matrix of QR factorization
278
 
279
   Notes:
280
   This routine orthonormalizes the columns of V so that V'*V=I up to
281
   working precision. It assumes that the first m columns (from 0 to m-1)
282
   are already orthonormal. The coefficients of the orthogonalization are
283
   stored in R so that V*R is equal to the original V.
284
 
285
   In some cases, this routine makes V B-orthonormal, that is, V'*B*V=I.
286
 
287
   If one of the vectors is linearly dependent wrt the rest (at working
288
   precision) then it is replaced by a random vector.
289
 
290
   Level: developer
291
 
292
.seealso: IPOrthogonalize(), IPNorm(), IPInnerProduct().
293
@*/
1509 slepc 294
PetscErrorCode IPQRDecomposition(IP ip,Vec *V,PetscInt m,PetscInt n,PetscScalar *R,PetscInt ldr,Vec work)
1345 slepc 295
{
296
  PetscErrorCode ierr;
1509 slepc 297
  PetscInt       k;
1345 slepc 298
  PetscReal      norm;
299
  PetscTruth     lindep;
300
 
301
  PetscFunctionBegin;
302
 
303
  for (k=m; k<n; k++) {
304
 
305
    /* orthogonalize v_k with respect to v_0, ..., v_{k-1} */
306
    if (R) { ierr = IPOrthogonalize(ip,k,PETSC_NULL,V,V[k],&R[0+ldr*k],&norm,&lindep,work);CHKERRQ(ierr); }
307
    else   { ierr = IPOrthogonalize(ip,k,PETSC_NULL,V,V[k],PETSC_NULL,&norm,&lindep,work);CHKERRQ(ierr); }
308
 
309
    /* normalize v_k: r_{k,k} = ||v_k||_2; v_k = v_k/r_{k,k} */
310
    if (norm==0.0 || lindep) {
311
      PetscInfo(ip,"Linearly dependent vector found, generating a new random vector\n");
312
      ierr = SlepcVecSetRandom(V[k]);CHKERRQ(ierr);
313
      ierr = IPNorm(ip,V[k],&norm);CHKERRQ(ierr);
314
    }
315
    ierr = VecScale(V[k],1.0/norm);CHKERRQ(ierr);
316
    if (R) R[k+ldr*k] = norm;
317
 
318
  }
319
 
320
  PetscFunctionReturn(0);
321
}
322
 
323
/*
324
    Biorthogonalization routine using classical Gram-Schmidt with refinement.
325
 */
326
#undef __FUNCT__  
327
#define __FUNCT__ "IPCGSBiOrthogonalization"
1509 slepc 328
static PetscErrorCode IPCGSBiOrthogonalization(IP ip,PetscInt n_,Vec *V,Vec *W,Vec v,PetscScalar *H,PetscReal *hnorm,PetscReal *norm)
1345 slepc 329
{
330
#if defined(SLEPC_MISSING_LAPACK_GELQF) || defined(SLEPC_MISSING_LAPACK_ORMLQ)
331
  PetscFunctionBegin;
332
  SETERRQ(PETSC_ERR_SUP,"xGELQF - Lapack routine is unavailable.");
333
#else
334
  PetscErrorCode ierr;
1509 slepc 335
  PetscBLASInt   j,ione=1,lwork,info,n=n_;
1345 slepc 336
  PetscScalar    shh[100],*lhh,*vw,*tau,one=1.0,*work;
337
  Vec            w;
338
 
339
  PetscFunctionBegin;
340
 
341
  /* Don't allocate small arrays */
342
  if (n<=100) lhh = shh;
343
  else { ierr = PetscMalloc(n*sizeof(PetscScalar),&lhh);CHKERRQ(ierr); }
344
  ierr = PetscMalloc(n*n*sizeof(PetscScalar),&vw);CHKERRQ(ierr);
345
  ierr = VecDuplicate(v,&w);CHKERRQ(ierr);
346
 
347
  for (j=0;j<n;j++) {
1381 slepc 348
    ierr = IPMInnerProduct(ip,V[j],n,W,vw+j*n);CHKERRQ(ierr);
1345 slepc 349
  }
350
  lwork = n;
351
  ierr = PetscMalloc(n*sizeof(PetscScalar),&tau);CHKERRQ(ierr);
352
  ierr = PetscMalloc(lwork*sizeof(PetscScalar),&work);CHKERRQ(ierr);
353
  LAPACKgelqf_(&n,&n,vw,&n,tau,work,&lwork,&info);
354
  if (info) SETERRQ1(PETSC_ERR_LIB,"Error in Lapack xGELQF %i",info);
355
 
356
  /*** First orthogonalization ***/
357
 
358
  /* h = W^* v */
359
  /* q = v - V h */
1381 slepc 360
  ierr = IPMInnerProduct(ip,v,n,W,H);CHKERRQ(ierr);
1345 slepc 361
  BLAStrsm_("L","L","N","N",&n,&ione,&one,vw,&n,H,&n,1,1,1,1);
362
  LAPACKormlq_("L","N",&n,&ione,&n,vw,&n,tau,H,&n,work,&lwork,&info,1,1);
363
  if (info) SETERRQ1(PETSC_ERR_LIB,"Error in Lapack xORMLQ %i",info);
364
  ierr = VecSet(w,0.0);CHKERRQ(ierr);
365
  ierr = VecMAXPY(w,n,H,V);CHKERRQ(ierr);
366
  ierr = VecAXPY(v,-1.0,w);CHKERRQ(ierr);
367
 
368
  /* compute norm of v */
369
  if (norm) { ierr = IPNorm(ip,v,norm);CHKERRQ(ierr); }
370
 
371
  if (n>100) { ierr = PetscFree(lhh);CHKERRQ(ierr); }
372
  ierr = PetscFree(vw);CHKERRQ(ierr);
373
  ierr = PetscFree(tau);CHKERRQ(ierr);
374
  ierr = PetscFree(work);CHKERRQ(ierr);
375
  ierr = VecDestroy(w);CHKERRQ(ierr);
376
  PetscFunctionReturn(0);
377
#endif
378
}
379
 
380
#undef __FUNCT__  
381
#define __FUNCT__ "IPBiOrthogonalize"
382
/*@
383
   IPBiOrthogonalize - Bi-orthogonalize a vector with respect to a set of vectors.
384
 
385
   Collective on IP
386
 
387
   Input Parameters:
1349 slepc 388
+  ip - the inner product context
1345 slepc 389
.  n - number of columns of V
390
.  V - set of vectors
391
-  W - set of vectors
392
 
393
   Input/Output Parameter:
394
.  v - vector to be orthogonalized
395
 
396
   Output Parameter:
397
+  H  - coefficients computed during orthogonalization
398
-  norm - norm of the vector after being orthogonalized
399
 
400
   Notes:
401
   This function applies an oblique projector to project vector v onto the
402
   span of the columns of V along the orthogonal complement of the column
403
   space of W.
404
 
405
   On exit, v0 = [V v]*H, where v0 is the original vector v.
406
 
407
   This routine does not normalize the resulting vector.
408
 
409
   Level: developer
410
 
411
.seealso: IPSetOrthogonalization(), IPOrthogonalize()
412
@*/
1509 slepc 413
PetscErrorCode IPBiOrthogonalize(IP ip,PetscInt n,Vec *V,Vec *W,Vec v,PetscScalar *H,PetscReal *norm)
1345 slepc 414
{
415
  PetscErrorCode ierr;
416
  PetscScalar    lh[100],*h;
417
  PetscTruth     allocated = PETSC_FALSE;
418
  PetscReal      lhnrm,*hnrm,lnrm,*nrm;
419
  PetscFunctionBegin;
420
  if (n==0) {
421
    if (norm) { ierr = IPNorm(ip,v,norm);CHKERRQ(ierr); }
422
  } else {
423
    ierr = PetscLogEventBegin(IP_Orthogonalize,ip,0,0,0);CHKERRQ(ierr);
424
 
425
    /* allocate H if needed */
426
    if (!H) {
427
      if (n<=100) h = lh;
428
      else {
429
        ierr = PetscMalloc(n*sizeof(PetscScalar),&h);CHKERRQ(ierr);
430
        allocated = PETSC_TRUE;
431
      }
432
    } else h = H;
433
 
434
    /* retrieve hnrm and nrm for linear dependence check or conditional refinement */
435
    if (ip->orthog_ref == IP_ORTH_REFINE_IFNEEDED) {
436
      hnrm = &lhnrm;
437
      if (norm) nrm = norm;
438
      else nrm = &lnrm;
439
    } else {
440
      hnrm = PETSC_NULL;
441
      nrm = norm;
442
    }
443
 
444
    switch (ip->orthog_type) {
445
      case IP_CGS_ORTH:
446
        ierr = IPCGSBiOrthogonalization(ip,n,V,W,v,h,hnrm,nrm);CHKERRQ(ierr);
447
        break;
448
      default:
449
        SETERRQ(PETSC_ERR_ARG_WRONG,"Unknown orthogonalization type");
450
    }
451
 
452
    if (allocated) { ierr = PetscFree(h);CHKERRQ(ierr); }
453
 
454
    ierr = PetscLogEventEnd(IP_Orthogonalize,ip,0,0,0);CHKERRQ(ierr);
455
  }
456
  PetscFunctionReturn(0);
457
}
458