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
1376 slepc 1
/*
2
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 3
   SLEPc - Scalable Library for Eigenvalue Problem Computations
4
   Copyright (c) 2002-2009, Universidad Politecnica de Valencia, Spain
6 dsic.upv.es!jroman 5
 
1672 slepc 6
   This file is part of SLEPc.
7
 
8
   SLEPc is free software: you can redistribute it and/or modify it under  the
9
   terms of version 3 of the GNU Lesser General Public License as published by
10
   the Free Software Foundation.
11
 
12
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
13
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
14
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
15
   more details.
16
 
17
   You  should have received a copy of the GNU Lesser General  Public  License
18
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
1376 slepc 19
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
20
*/
21
 
183 dsic.upv.es!antodo 22
#include "slepc.h" /*I "slepc.h" I*/
1601 slepc 23
#include "petscblaslapack.h"
572 dsic.upv.es!antodo 24
#include <stdlib.h>
6 dsic.upv.es!jroman 25
 
1602 slepc 26
PetscLogEvent SLEPC_UpdateVectors = 0;
1601 slepc 27
 
6 dsic.upv.es!jroman 28
#undef __FUNCT__  
29
#define __FUNCT__ "SlepcVecSetRandom"
30
/*@
31
   SlepcVecSetRandom - Sets all components of a vector to random numbers which
572 dsic.upv.es!antodo 32
   follow a uniform distribution in [0,1).
6 dsic.upv.es!jroman 33
 
34
   Collective on Vec
35
 
36
   Input/Output Parameter:
37
.  x  - the vector
38
 
39
   Note:
40
   This operation is equivalent to VecSetRandom - the difference is that the
41
   vector generated by SlepcVecSetRandom is the same irrespective of the size
42
   of the communicator.
43
 
44
   Level: developer
45
 
46
.seealso: VecSetRandom()
47
@*/
476 dsic.upv.es!antodo 48
PetscErrorCode SlepcVecSetRandom(Vec x)
6 dsic.upv.es!jroman 49
{
476 dsic.upv.es!antodo 50
  PetscErrorCode ierr;
982 slepc 51
  PetscInt       i,n,low,high;
572 dsic.upv.es!antodo 52
  PetscScalar    *px,t;
877 dsic.upv.es!jroman 53
#if defined(PETSC_HAVE_DRAND48)
572 dsic.upv.es!antodo 54
  static unsigned short seed[3] = { 1, 3, 2 };
877 dsic.upv.es!jroman 55
#endif
572 dsic.upv.es!antodo 56
 
6 dsic.upv.es!jroman 57
  PetscFunctionBegin;
58
  ierr = VecGetSize(x,&n);CHKERRQ(ierr);
59
  ierr = VecGetOwnershipRange(x,&low,&high);CHKERRQ(ierr);
60
  ierr = VecGetArray(x,&px);CHKERRQ(ierr);
572 dsic.upv.es!antodo 61
  for (i=0;i<n;i++) {
643 dsic.upv.es!antodo 62
#if defined(PETSC_HAVE_DRAND48)
572 dsic.upv.es!antodo 63
    t = erand48(seed);
643 dsic.upv.es!antodo 64
#elif defined(PETSC_HAVE_RAND)
1520 slepc 65
    t = rand()/(PetscReal)((unsigned int)RAND_MAX+1);
643 dsic.upv.es!antodo 66
#else
67
    t = 0.5;
68
#endif
572 dsic.upv.es!antodo 69
    if (i>=low && i<high) px[i-low] = t;
70
  }
6 dsic.upv.es!jroman 71
  ierr = VecRestoreArray(x,&px);CHKERRQ(ierr);
72
  PetscFunctionReturn(0);
73
}
74
 
75
#undef __FUNCT__  
76
#define __FUNCT__ "SlepcIsHermitian"
77
/*@
78
   SlepcIsHermitian - Checks if a matrix is Hermitian or not.
79
 
80
   Collective on Mat
81
 
82
   Input parameter:
83
.  A  - the matrix
84
 
85
   Output parameter:
86
.  is  - flag indicating if the matrix is Hermitian
87
 
88
   Notes:
89
   The result of Ax and A^Hx (with a random x) is compared, but they
90
   could be equal also for some non-Hermitian matrices.
91
 
1389 slepc 92
   This routine will not work with matrix formats MATSEQSBAIJ or MATMPISBAIJ,
93
   or when PETSc is configured with complex scalars.
6 dsic.upv.es!jroman 94
 
95
   Level: developer
96
 
97
@*/
476 dsic.upv.es!antodo 98
PetscErrorCode SlepcIsHermitian(Mat A,PetscTruth *is)
6 dsic.upv.es!jroman 99
{
476 dsic.upv.es!antodo 100
  PetscErrorCode ierr;
982 slepc 101
  PetscInt       M,N,m,n;
476 dsic.upv.es!antodo 102
  Vec            x,w1,w2;
103
  MPI_Comm       comm;
104
  PetscReal      norm;
105
  PetscTruth     has;
6 dsic.upv.es!jroman 106
 
107
  PetscFunctionBegin;
108
 
109
#if !defined(PETSC_USE_COMPLEX)
110
  ierr = PetscTypeCompare((PetscObject)A,MATSEQSBAIJ,is);CHKERRQ(ierr);
111
  if (*is) PetscFunctionReturn(0);
112
  ierr = PetscTypeCompare((PetscObject)A,MATMPISBAIJ,is);CHKERRQ(ierr);
113
  if (*is) PetscFunctionReturn(0);
114
#endif
115
 
116
  *is = PETSC_FALSE;
117
  ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
118
  ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr);
119
  if (M!=N) PetscFunctionReturn(0);
120
  ierr = MatHasOperation(A,MATOP_MULT,&has);CHKERRQ(ierr);
121
  if (!has) PetscFunctionReturn(0);
122
  ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&has);CHKERRQ(ierr);
123
  if (!has) PetscFunctionReturn(0);
124
 
125
  ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
126
  ierr = VecCreate(comm,&x);CHKERRQ(ierr);
127
  ierr = VecSetSizes(x,n,N);CHKERRQ(ierr);
128
  ierr = VecSetFromOptions(x);CHKERRQ(ierr);
129
  ierr = SlepcVecSetRandom(x);CHKERRQ(ierr);
130
  ierr = VecDuplicate(x,&w1);CHKERRQ(ierr);
131
  ierr = VecDuplicate(x,&w2);CHKERRQ(ierr);
132
  ierr = MatMult(A,x,w1);CHKERRQ(ierr);
133
  ierr = MatMultTranspose(A,x,w2);CHKERRQ(ierr);
134
  ierr = VecConjugate(w2);CHKERRQ(ierr);
828 dsic.upv.es!antodo 135
  ierr = VecAXPY(w2,-1.0,w1);CHKERRQ(ierr);
6 dsic.upv.es!jroman 136
  ierr = VecNorm(w2,NORM_2,&norm);CHKERRQ(ierr);
137
  if (norm<1.0e-6) *is = PETSC_TRUE;
138
  ierr = VecDestroy(x);CHKERRQ(ierr);
139
  ierr = VecDestroy(w1);CHKERRQ(ierr);
140
  ierr = VecDestroy(w2);CHKERRQ(ierr);
141
 
142
  PetscFunctionReturn(0);
143
}
144
 
502 dsic.upv.es!antodo 145
#if !defined(PETSC_USE_COMPLEX)
491 dsic.upv.es!antodo 146
 
147
#undef __FUNCT__  
502 dsic.upv.es!antodo 148
#define __FUNCT__ "SlepcAbsEigenvalue"
604 dsic.upv.es!antodo 149
/*@C
617 dsic.upv.es!antodo 150
   SlepcAbsEigenvalue - Returns the absolute value of a complex number given
547 dsic.upv.es!jroman 151
   its real and imaginary parts.
152
 
153
   Not collective
154
 
155
   Input parameters:
156
+  x  - the real part of the complex number
157
-  y  - the imaginary part of the complex number
158
 
159
   Notes:
160
   This function computes sqrt(x**2+y**2), taking care not to cause unnecessary
161
   overflow. It is based on LAPACK's DLAPY2.
162
 
163
   Level: developer
164
 
165
@*/
502 dsic.upv.es!antodo 166
PetscReal SlepcAbsEigenvalue(PetscScalar x,PetscScalar y)
491 dsic.upv.es!antodo 167
{
502 dsic.upv.es!antodo 168
  PetscReal xabs,yabs,w,z,t;
491 dsic.upv.es!antodo 169
  PetscFunctionBegin;
502 dsic.upv.es!antodo 170
  xabs = PetscAbsReal(x);
171
  yabs = PetscAbsReal(y);
491 dsic.upv.es!antodo 172
  w = PetscMax(xabs,yabs);
173
  z = PetscMin(xabs,yabs);
502 dsic.upv.es!antodo 174
  if (z == 0.0) PetscFunctionReturn(w);
175
  t = z/w;
176
  PetscFunctionReturn(w*sqrt(1.0+t*t));  
491 dsic.upv.es!antodo 177
}
178
 
179
#endif
675 dsic.upv.es!antodo 180
 
181
#undef __FUNCT__  
182
#define __FUNCT__ "SlepcMatConvertSeqDense"
183
/*@C
683 dsic.upv.es!jroman 184
   SlepcMatConvertSeqDense - Converts a parallel matrix to another one in sequential
185
   dense format replicating the values in every processor.
675 dsic.upv.es!antodo 186
 
187
   Collective
188
 
189
   Input parameters:
190
+  A  - the source matrix
191
-  B  - the target matrix
192
 
193
   Level: developer
194
 
195
@*/
196
PetscErrorCode SlepcMatConvertSeqDense(Mat mat,Mat *newmat)
197
{
198
  PetscErrorCode ierr;
982 slepc 199
  PetscInt       m,n;
200
  PetscMPIInt    size;
675 dsic.upv.es!antodo 201
  MPI_Comm       comm;
202
  Mat            *M;
203
  IS             isrow, iscol;
204
  PetscTruth     flg;
205
 
206
  PetscFunctionBegin;
207
  PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
208
  PetscValidPointer(newmat,2);
209
 
210
  ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
211
  ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
212
 
213
  if (size > 1) {
214
    /* assemble full matrix on every processor */
215
    ierr = MatGetSize(mat,&m,&n);CHKERRQ(ierr);
216
    ierr = ISCreateStride(PETSC_COMM_SELF,m,0,1,&isrow);CHKERRQ(ierr);
217
    ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&iscol);CHKERRQ(ierr);
218
    ierr = MatGetSubMatrices(mat,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
219
    ierr = ISDestroy(isrow);CHKERRQ(ierr);
220
    ierr = ISDestroy(iscol);CHKERRQ(ierr);
221
 
683 dsic.upv.es!jroman 222
    /* Fake support for "inplace" convert */
675 dsic.upv.es!antodo 223
    if (*newmat == mat) {
224
      ierr = MatDestroy(mat);CHKERRQ(ierr);
225
    }
226
    *newmat = *M;
227
    ierr = PetscFree(M);CHKERRQ(ierr);    
228
 
229
    /* convert matrix to MatSeqDense */
230
    ierr = PetscTypeCompare((PetscObject)*newmat,MATSEQDENSE,&flg); CHKERRQ(ierr);
231
    if (!flg) {
784 dsic.upv.es!antodo 232
      ierr = MatConvert(*newmat,MATSEQDENSE,MAT_INITIAL_MATRIX,newmat);CHKERRQ(ierr);
675 dsic.upv.es!antodo 233
    }
234
  } else {
235
    /* convert matrix to MatSeqDense */
784 dsic.upv.es!antodo 236
    ierr = MatConvert(mat,MATSEQDENSE,MAT_INITIAL_MATRIX,newmat);CHKERRQ(ierr);
675 dsic.upv.es!antodo 237
  }
238
 
239
  PetscFunctionReturn(0);  
240
}
683 dsic.upv.es!jroman 241
 
834 dsic.upv.es!antodo 242
#undef __FUNCT__  
877 dsic.upv.es!jroman 243
#define __FUNCT__ "SlepcCheckOrthogonality"
244
/*@
245
   SlepcCheckOrthogonality - Checks (or prints) the level of orthogonality
246
   of a set of vectors.
247
 
248
   Collective on Vec
249
 
250
   Input parameters:
251
+  V  - a set of vectors
252
.  nv - number of V vectors
253
.  W  - an alternative set of vectors (optional)
254
.  nw - number of W vectors
255
-  B  - matrix defining the inner product (optional)
256
 
257
   Output parameter:
258
.  lev - level of orthogonality (optional)
259
 
260
   Notes:
261
   This function computes W'*V and prints the result. It is intended to check
262
   the level of bi-orthogonality of the vectors in the two sets. If W is equal
263
   to PETSC_NULL then V is used, thus checking the orthogonality of the V vectors.
264
 
265
   If matrix B is provided then the check uses the B-inner product, W'*B*V.
266
 
879 ono.com!jroman 267
   If lev is not PETSC_NULL, it will contain the level of orthogonality
268
   computed as ||W'*V - I|| in the Frobenius norm. Otherwise, the matrix W'*V
269
   is printed.
877 dsic.upv.es!jroman 270
 
271
   Level: developer
272
 
273
@*/
274
PetscErrorCode SlepcCheckOrthogonality(Vec *V,PetscInt nv,Vec *W,PetscInt nw,Mat B,PetscScalar *lev)
275
{
276
  PetscErrorCode ierr;
1510 slepc 277
  PetscInt       i,j;
1120 slepc 278
  PetscScalar    *vals;
279
  Vec            w;
280
  MPI_Comm       comm;
877 dsic.upv.es!jroman 281
 
282
  PetscFunctionBegin;
283
  if (nv<=0 || nw<=0) PetscFunctionReturn(0);
1120 slepc 284
  ierr = PetscObjectGetComm((PetscObject)V[0],&comm);CHKERRQ(ierr);
285
  ierr = PetscMalloc(nv*sizeof(PetscScalar),&vals);CHKERRQ(ierr);
286
  if (B) { ierr = VecDuplicate(V[0],&w);CHKERRQ(ierr); }
287
  if (lev) *lev = 0.0;
288
  for (i=0;i<nw;i++) {
289
    if (B) {
290
      if (W) { ierr = MatMultTranspose(B,W[i],w);CHKERRQ(ierr); }
291
      else { ierr = MatMultTranspose(B,V[i],w);CHKERRQ(ierr); }
292
    }
293
    else {
294
      if (W) w = W[i];
295
      else w = V[i];
296
    }
297
    ierr = VecMDot(w,nv,V,vals);CHKERRQ(ierr);
877 dsic.upv.es!jroman 298
    for (j=0;j<nv;j++) {
1120 slepc 299
      if (lev) *lev += (j==i)? (vals[j]-1.0)*(vals[j]-1.0): vals[j]*vals[j];
300
      else {
301
#ifndef PETSC_USE_COMPLEX
302
        ierr = PetscPrintf(comm," %12g  ",vals[j]);CHKERRQ(ierr);
303
#else
304
        ierr = PetscPrintf(comm," %12g%+12gi ",PetscRealPart(vals[j]),PetscImaginaryPart(vals[j]));CHKERRQ(ierr);    
305
#endif
306
      }
877 dsic.upv.es!jroman 307
    }
1120 slepc 308
    if (!lev) { ierr = PetscPrintf(comm,"\n");CHKERRQ(ierr); }
877 dsic.upv.es!jroman 309
  }
1120 slepc 310
  ierr = PetscFree(vals);CHKERRQ(ierr);
311
  if (B) { ierr = VecDestroy(w);CHKERRQ(ierr); }
312
  if (lev) *lev = PetscSqrtScalar(*lev);
877 dsic.upv.es!jroman 313
  PetscFunctionReturn(0);
314
}
315
 
1601 slepc 316
#undef __FUNCT__  
317
#define __FUNCT__ "SlepcUpdateVectors"
1604 slepc 318
/*@
319
   SlepcUpdateVectors - Update a set of vectors V as V(:,s:e-1) = V*Q(:,s:e-1).
320
 
321
   Collective on Vec
322
 
323
   Input parameters:
324
+  n      - number of vectors in V
325
.  s      - first column of V to be overwritten
326
.  e      - first column of V not to be overwritten
327
.  Q      - matrix containing the coefficients of the update
328
.  ldq    - leading dimension of Q
329
-  qtrans - flag indicating if Q is to be transposed
330
 
331
   Input/Output parameter:
332
.  V      - set of vectors
333
 
334
   Notes:
335
   This function computes V(:,s:e-1) = V*Q(:,s:e-1), that is, given a set of
336
   vectors V, columns from s to e-1 are overwritten with columns from s to
337
   e-1 of the matrix-matrix product V*Q.
338
 
339
   Matrix V is represented as an array of Vec, whereas Q is represented as
340
   a column-major dense array of leading dimension ldq. Only columns s to e-1
341
   of Q are referenced.
342
 
343
   If qtrans=PETSC_TRUE, the operation is V*Q'.
344
 
345
   Level: developer
346
 
347
@*/
1601 slepc 348
PetscErrorCode SlepcUpdateVectors(PetscInt n_,Vec *V,PetscInt s,PetscInt e,const PetscScalar *Q,PetscInt ldq_,PetscTruth qtrans)
349
{
350
  PetscErrorCode ierr;
1641 slepc 351
  PetscInt       l;
352
  PetscBLASInt   i,j,k,bs=64,m,n,ldq,ls;
1601 slepc 353
  PetscScalar    *pv,*pw,*pq,*work,*pwork,one=1.0,zero=0.0;
354
  const char     *qt;
877 dsic.upv.es!jroman 355
 
1601 slepc 356
  PetscFunctionBegin;
1641 slepc 357
  n = PetscBLASIntCast(n_);
358
  ldq = PetscBLASIntCast(ldq_);
1604 slepc 359
  m = e-s;
360
  if (m==0) PetscFunctionReturn(0);
361
  PetscValidIntPointer(Q,5);
362
  if (m<0 || n<0 || s<0 || e>n) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Index argument out of range");
1601 slepc 363
  ierr = PetscLogEventBegin(SLEPC_UpdateVectors,0,0,0,0);CHKERRQ(ierr);
1641 slepc 364
  ierr = VecGetLocalSize(V[0],&l);CHKERRQ(ierr);
365
  ls = PetscBLASIntCast(l);
1601 slepc 366
  ierr = VecGetArray(V[0],&pv);CHKERRQ(ierr);
367
  if (qtrans) {
368
    pq = (PetscScalar*)Q+s;
369
    qt = "T";
370
  } else {
371
    pq = (PetscScalar*)Q+s*ldq;
372
    qt = "N";
373
  }
374
  ierr = PetscMalloc(sizeof(PetscScalar)*bs*m,&work);CHKERRQ(ierr);
375
  k = ls % bs;
376
  if (k) {
377
    BLASgemm_("N",qt,&k,&m,&n,&one,pv,&ls,pq,&ldq,&zero,work,&k);
378
    for (j=0;j<m;j++) {
379
      pw = pv+(s+j)*ls;
380
      pwork = work+j*k;
381
      for (i=0;i<k;i++) {
382
        *pw++ = *pwork++;
383
      }
384
    }        
385
  }
386
  for (;k<ls;k+=bs) {
387
    BLASgemm_("N",qt,&bs,&m,&n,&one,pv+k,&ls,pq,&ldq,&zero,work,&bs);
388
    for (j=0;j<m;j++) {
389
      pw = pv+(s+j)*ls+k;
390
      pwork = work+j*bs;
391
      for (i=0;i<bs;i++) {
392
        *pw++ = *pwork++;
393
      }
394
    }
395
  }
396
  ierr = VecRestoreArray(V[0],&pv);CHKERRQ(ierr);
397
  ierr = PetscFree(work);CHKERRQ(ierr);
398
  ierr = PetscLogFlops(m*n*2*ls);CHKERRQ(ierr);
399
  ierr = PetscLogEventEnd(SLEPC_UpdateVectors,0,0,0,0);CHKERRQ(ierr);
400
  PetscFunctionReturn(0);
401
}