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
1249 slepc 1
/*
2
      SVD routines related to the solution process.
1376 slepc 3
 
4
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 5
   SLEPc - Scalable Library for Eigenvalue Problem Computations
6
   Copyright (c) 2002-2009, Universidad Politecnica de Valencia, Spain
1376 slepc 7
 
1672 slepc 8
   This file is part of SLEPc.
9
 
10
   SLEPc is free software: you can redistribute it and/or modify it under  the
11
   terms of version 3 of the GNU Lesser General Public License as published by
12
   the Free Software Foundation.
13
 
14
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
15
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
16
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
17
   more details.
18
 
19
   You  should have received a copy of the GNU Lesser General  Public  License
20
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
1376 slepc 21
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1249 slepc 22
*/
1376 slepc 23
 
1521 slepc 24
#include "private/svdimpl.h"   /*I "slepcsvd.h" I*/
1249 slepc 25
 
26
#undef __FUNCT__  
27
#define __FUNCT__ "SVDSolve"
28
/*@
29
   SVDSolve - Solves the singular value problem.
30
 
31
   Collective on SVD
32
 
33
   Input Parameter:
34
.  svd - singular value solver context obtained from SVDCreate()
35
 
36
   Options Database:
37
.   -svd_view - print information about the solver used
38
 
39
   Level: beginner
40
 
41
.seealso: SVDCreate(), SVDSetUp(), SVDDestroy()
42
@*/
43
PetscErrorCode SVDSolve(SVD svd)
44
{
45
  PetscErrorCode ierr;
46
  PetscTruth     flg;
1603 slepc 47
  PetscInt       i,*workperm;
1713 antodo 48
  char           filename[PETSC_MAX_PATH_LEN];
49
  PetscViewer    viewer;
1249 slepc 50
 
51
  PetscFunctionBegin;
52
  PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
53
 
54
  if (!svd->setupcalled) { ierr = SVDSetUp(svd);CHKERRQ(ierr); }
1288 slepc 55
  svd->its = 0;
1305 slepc 56
  svd->matvecs = 0;
1288 slepc 57
  svd->nconv = 0;
1283 slepc 58
  svd->reason = SVD_CONVERGED_ITERATING;
1329 slepc 59
  ierr = IPResetOperationCounters(svd->ip);CHKERRQ(ierr);
1288 slepc 60
  for (i=0;i<svd->ncv;i++) svd->sigma[i]=svd->errest[i]=0.0;
61
  SVDMonitor(svd,svd->its,svd->nconv,svd->sigma,svd->errest,svd->ncv);
1249 slepc 62
 
63
  ierr = PetscLogEventBegin(SVD_Solve,svd,0,0,0);CHKERRQ(ierr);
64
  ierr = (*svd->ops->solve)(svd);CHKERRQ(ierr);
65
  ierr = PetscLogEventEnd(SVD_Solve,svd,0,0,0);CHKERRQ(ierr);
66
 
1603 slepc 67
  /* sort singular triplets */
68
  if (svd->which == SVD_SMALLEST) {
69
    for (i=0;i<svd->nconv;i++) svd->perm[i] = i;
70
    ierr = PetscSortRealWithPermutation(svd->nconv,svd->sigma,svd->perm);CHKERRQ(ierr);
71
  } else {
72
    ierr = PetscMalloc(sizeof(PetscInt)*svd->nconv,&workperm);CHKERRQ(ierr);
73
    for (i=0;i<svd->nconv;i++) workperm[i] = i;
74
    ierr = PetscSortRealWithPermutation(svd->nconv,svd->sigma,workperm);CHKERRQ(ierr);
75
    for (i=0;i<svd->nconv;i++) svd->perm[i] = workperm[svd->nconv-i-1];
76
    ierr = PetscFree(workperm);CHKERRQ(ierr);
77
  }
78
 
1713 antodo 79
  ierr = PetscOptionsGetString(((PetscObject)svd)->prefix,"-svd_view",filename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr);
80
  if (flg && !PetscPreLoadingOn) {
81
    ierr = PetscViewerASCIIOpen(((PetscObject)svd)->comm,filename,&viewer);CHKERRQ(ierr);
82
    ierr = SVDView(svd,viewer);CHKERRQ(ierr);
83
    ierr = PetscViewerDestroy(viewer);CHKERRQ(ierr);
84
  }
1249 slepc 85
 
86
  PetscFunctionReturn(0);
87
}
88
 
89
#undef __FUNCT__  
1283 slepc 90
#define __FUNCT__ "SVDGetIterationNumber"
91
/*@
92
   SVDGetIterationNumber - Gets the current iteration number. If the
93
   call to SVDSolve() is complete, then it returns the number of iterations
94
   carried out by the solution method.
95
 
96
   Not Collective
97
 
98
   Input Parameter:
99
.  svd - the singular value solver context
100
 
101
   Output Parameter:
102
.  its - number of iterations
103
 
104
   Level: intermediate
105
 
106
   Notes:
107
      During the i-th iteration this call returns i-1. If SVDSolve() is
108
      complete, then parameter "its" contains either the iteration number at
109
      which convergence was successfully reached, or failure was detected.  
110
      Call SVDGetConvergedReason() to determine if the solver converged or
111
      failed and why.
112
 
113
@*/
1504 slepc 114
PetscErrorCode SVDGetIterationNumber(SVD svd,PetscInt *its)
1283 slepc 115
{
116
  PetscFunctionBegin;
117
  PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
118
  PetscValidIntPointer(its,2);
119
  *its = svd->its;
120
  PetscFunctionReturn(0);
121
}
122
 
123
#undef __FUNCT__  
124
#define __FUNCT__ "SVDGetConvergedReason"
125
/*@C
126
   SVDGetConvergedReason - Gets the reason why the SVDSolve() iteration was
127
   stopped.
128
 
129
   Not Collective
130
 
131
   Input Parameter:
132
.  svd - the singular value solver context
133
 
134
   Output Parameter:
135
.  reason - negative value indicates diverged, positive value converged
136
   (see SVDConvergedReason)
137
 
138
   Possible values for reason:
139
+  SVD_CONVERGED_TOL - converged up to tolerance
140
.  SVD_DIVERGED_ITS - required more than its to reach convergence
141
-  SVD_DIVERGED_BREAKDOWN - generic breakdown in method
142
 
143
   Level: intermediate
144
 
145
   Notes: Can only be called after the call to SVDSolve() is complete.
146
 
147
.seealso: SVDSetTolerances(), SVDSolve(), SVDConvergedReason
148
@*/
149
PetscErrorCode SVDGetConvergedReason(SVD svd,SVDConvergedReason *reason)
150
{
151
  PetscFunctionBegin;
152
  PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
153
  PetscValidIntPointer(reason,2);
154
  *reason = svd->reason;
155
  PetscFunctionReturn(0);
156
}
157
 
158
#undef __FUNCT__  
1249 slepc 159
#define __FUNCT__ "SVDGetConverged"
160
/*@
161
   SVDGetConverged - Gets the number of converged singular values.
162
 
163
   Not Collective
164
 
165
   Input Parameter:
166
.  svd - the singular value solver context
167
 
168
   Output Parameter:
169
.  nconv - number of converged singular values
170
 
171
   Note:
172
   This function should be called after SVDSolve() has finished.
173
 
174
   Level: beginner
175
 
176
@*/
1504 slepc 177
PetscErrorCode SVDGetConverged(SVD svd,PetscInt *nconv)
1249 slepc 178
{
179
  PetscFunctionBegin;
180
  PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
181
  PetscValidIntPointer(nconv,2);
1283 slepc 182
  if (svd->reason == SVD_CONVERGED_ITERATING) {
1249 slepc 183
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "SVDSolve must be called first");
184
  }
185
  *nconv = svd->nconv;
186
  PetscFunctionReturn(0);
187
}
188
 
189
#undef __FUNCT__  
190
#define __FUNCT__ "SVDGetSingularTriplet"
191
/*@
192
   SVDGetSingularTriplet - Gets the i-th triplet of the singular value decomposition
193
   as computed by SVDSolve(). The solution consists in the singular value and its left
194
   and right singular vectors.
195
 
196
   Not Collective
197
 
198
   Input Parameters:
199
+  svd - singular value solver context
200
-  i   - index of the solution
201
 
202
   Output Parameters:
203
+  sigma - singular value
1251 slepc 204
.  u     - left singular vector
205
-  v     - right singular vector
1249 slepc 206
 
1267 slepc 207
   Note:
208
   The index i should be a value between 0 and nconv-1 (see SVDGetConverged()).
1249 slepc 209
   Both U or V can be PETSC_NULL if singular vectors are not required.
210
 
211
   Level: beginner
212
 
213
.seealso: SVDSolve(),  SVDGetConverged()
214
@*/
1504 slepc 215
PetscErrorCode SVDGetSingularTriplet(SVD svd, PetscInt i, PetscReal *sigma, Vec u, Vec v)
1249 slepc 216
{
217
  PetscErrorCode ierr;
1489 slepc 218
  PetscReal      norm;
1737 antodo 219
  PetscInt       j,nloc,M,N;
1605 slepc 220
  PetscScalar    *pU;
1737 antodo 221
  Vec            w;
1249 slepc 222
 
223
  PetscFunctionBegin;
224
  PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
225
  PetscValidPointer(sigma,3);
1283 slepc 226
  if (svd->reason == SVD_CONVERGED_ITERATING) {
1249 slepc 227
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "SVDSolve must be called first");
228
  }
229
  if (i<0 || i>=svd->nconv) {
230
    SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Argument 2 out of range");
231
  }
1603 slepc 232
  *sigma = svd->sigma[svd->perm[i]];
1737 antodo 233
  ierr = MatGetSize(svd->OP,&M,&N);CHKERRQ(ierr);
234
  if (M<N) { w = u; u = v; v = w; }
1251 slepc 235
  if (u) {
236
    PetscValidHeaderSpecific(u,VEC_COOKIE,4);
1489 slepc 237
    if (!svd->U) {
238
      ierr = PetscMalloc(sizeof(Vec)*svd->ncv,&svd->U);CHKERRQ(ierr);
1605 slepc 239
      ierr = SVDMatGetLocalSize(svd,&nloc,PETSC_NULL);CHKERRQ(ierr);
240
      ierr = PetscMalloc(svd->ncv*nloc*sizeof(PetscScalar),&pU);CHKERRQ(ierr);
1727 antodo 241
      for (j=0;j<svd->ncv;j++) {
242
        ierr = VecCreateMPIWithArray(((PetscObject)svd)->comm,nloc,PETSC_DECIDE,pU+j*nloc,&svd->U[j]);CHKERRQ(ierr);
1605 slepc 243
      }
1489 slepc 244
      for (j=0;j<svd->nconv;j++) {
245
        ierr = SVDMatMult(svd,PETSC_FALSE,svd->V[j],svd->U[j]);CHKERRQ(ierr);
1755 antodo 246
        ierr = IPOrthogonalize(svd->ip,0,PETSC_NULL,j,PETSC_NULL,svd->U,svd->U[j],PETSC_NULL,&norm,PETSC_NULL);CHKERRQ(ierr);
1489 slepc 247
        ierr = VecScale(svd->U[j],1.0/norm);CHKERRQ(ierr);
248
      }
1314 slepc 249
    }
1603 slepc 250
    ierr = VecCopy(svd->U[svd->perm[i]],u);CHKERRQ(ierr);
1249 slepc 251
  }
1251 slepc 252
  if (v) {
253
    PetscValidHeaderSpecific(v,VEC_COOKIE,5);  
1603 slepc 254
    ierr = VecCopy(svd->V[svd->perm[i]],v);CHKERRQ(ierr);
1249 slepc 255
  }
256
  PetscFunctionReturn(0);
257
}
1251 slepc 258
 
259
#undef __FUNCT__  
1257 slepc 260
#define __FUNCT__ "SVDComputeResidualNorms"
1251 slepc 261
/*@
1320 slepc 262
   SVDComputeResidualNorms - Computes the norms of the residual vectors associated with
1251 slepc 263
   the i-th computed singular triplet.
264
 
1320 slepc 265
   Collective on SVD
1251 slepc 266
 
1267 slepc 267
   Input Parameters:
1320 slepc 268
+  svd  - the singular value solver context
1257 slepc 269
-  i    - the solution index
1251 slepc 270
 
1267 slepc 271
   Output Parameters:
1257 slepc 272
+  norm1 - the norm ||A*v-sigma*u||_2 where sigma is the
273
           singular value, u and v are the left and right singular vectors.
1283 slepc 274
-  norm2 - the norm ||A^T*u-sigma*v||_2 with the same sigma, u and v
1251 slepc 275
 
1267 slepc 276
   Note:
277
   The index i should be a value between 0 and nconv-1 (see SVDGetConverged()).
1257 slepc 278
   Both output parameters can be PETSC_NULL on input if not needed.
1251 slepc 279
 
280
   Level: beginner
281
 
1320 slepc 282
.seealso: SVDSolve(), SVDGetConverged(), SVDComputeRelativeError()
1251 slepc 283
@*/
1504 slepc 284
PetscErrorCode SVDComputeResidualNorms(SVD svd, PetscInt i, PetscReal *norm1, PetscReal *norm2)
1251 slepc 285
{
286
  PetscErrorCode ierr;
1257 slepc 287
  Vec            u,v,x = PETSC_NULL,y = PETSC_NULL;
1251 slepc 288
  PetscReal      sigma;
1738 antodo 289
  PetscInt       M,N;
1251 slepc 290
 
291
  PetscFunctionBegin;
292
  PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
1283 slepc 293
  if (svd->reason == SVD_CONVERGED_ITERATING) {
1251 slepc 294
    SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "SVDSolve must be called first");
295
  }
296
  if (i<0 || i>=svd->nconv) {
297
    SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Argument 2 out of range");
298
  }
299
 
1737 antodo 300
  ierr = MatGetVecs(svd->OP,&v,&u);CHKERRQ(ierr);
1283 slepc 301
  ierr = SVDGetSingularTriplet(svd,i,&sigma,u,v);CHKERRQ(ierr);
1257 slepc 302
  if (norm1) {
303
    ierr = VecDuplicate(u,&x);CHKERRQ(ierr);
1737 antodo 304
    ierr = MatMult(svd->OP,v,x);CHKERRQ(ierr);
1257 slepc 305
    ierr = VecAXPY(x,-sigma,u);CHKERRQ(ierr);
306
    ierr = VecNorm(x,NORM_2,norm1);CHKERRQ(ierr);
307
  }
308
  if (norm2) {
309
    ierr = VecDuplicate(v,&y);CHKERRQ(ierr);
1738 antodo 310
    if (svd->A && svd->AT) {
311
      ierr = MatGetSize(svd->OP,&M,&N);CHKERRQ(ierr);
312
      if (M<N) {
313
        ierr = MatMult(svd->A,u,y);CHKERRQ(ierr);
314
      } else {
315
        ierr = MatMult(svd->AT,u,y);CHKERRQ(ierr);
316
      }
317
    } else {
318
      ierr = MatMultTranspose(svd->OP,u,y);CHKERRQ(ierr);
319
    }
1257 slepc 320
    ierr = VecAXPY(y,-sigma,v);CHKERRQ(ierr);
321
    ierr = VecNorm(y,NORM_2,norm2);CHKERRQ(ierr);
322
  }
1251 slepc 323
 
324
  ierr = VecDestroy(v);CHKERRQ(ierr);
325
  ierr = VecDestroy(u);CHKERRQ(ierr);
1257 slepc 326
  if (x) { ierr = VecDestroy(x);CHKERRQ(ierr); }
327
  if (y) { ierr = VecDestroy(y);CHKERRQ(ierr); }
1251 slepc 328
  PetscFunctionReturn(0);
329
}
1305 slepc 330
 
331
#undef __FUNCT__  
1317 slepc 332
#define __FUNCT__ "SVDComputeRelativeError"
1320 slepc 333
/*@
334
   SVDComputeRelativeError - Computes the relative error bound associated
335
   with the i-th singular triplet.
336
 
337
   Collective on SVD
338
 
339
   Input Parameter:
1321 slepc 340
+  svd - the singular value solver context
341
-  i   - the solution index
1320 slepc 342
 
343
   Output Parameter:
1490 slepc 344
.  error - the relative error bound, computed as sqrt(n1^2+n2^2)/sigma
1330 slepc 345
   where n1 = ||A*v-sigma*u||_2 , n2 = ||A^T*u-sigma*v||_2 , sigma is the singular value,
346
   u and v are the left and right singular vectors.
1490 slepc 347
   If sigma is too small the relative error is computed as sqrt(n1^2+n2^2).
1320 slepc 348
 
349
   Level: beginner
350
 
351
.seealso: SVDSolve(), SVDComputeResidualNorms()
352
@*/
1504 slepc 353
PetscErrorCode SVDComputeRelativeError(SVD svd,PetscInt i,PetscReal *error)
1317 slepc 354
{
355
  PetscErrorCode ierr;
1490 slepc 356
  PetscReal      sigma,norm1,norm2;
1317 slepc 357
 
358
  PetscFunctionBegin;
359
  PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
360
  PetscValidPointer(error,2);
1490 slepc 361
  ierr = SVDGetSingularTriplet(svd,i,&sigma,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1317 slepc 362
  ierr = SVDComputeResidualNorms(svd,i,&norm1,&norm2);CHKERRQ(ierr);
1490 slepc 363
  *error = sqrt(norm1*norm1+norm2*norm2);
1330 slepc 364
  if (sigma>*error) *error /= sigma;
1317 slepc 365
  PetscFunctionReturn(0);
366
}
367
 
368
#undef __FUNCT__  
1305 slepc 369
#define __FUNCT__ "SVDGetOperationCounters"
370
/*@
371
   SVDGetOperationCounters - Gets the total number of matrix vector and dot
372
   products used by the SVD object during the last SVDSolve() call.
373
 
374
   Not Collective
375
 
376
   Input Parameter:
377
.  svd - SVD context
378
 
379
   Output Parameter:
380
+  matvecs - number of matrix vector product operations
381
-  dots    - number of dot product operations
382
 
383
   Notes:
384
   These counters are reset to zero at each successive call to SVDSolve().
385
 
386
   Level: intermediate
387
 
388
@*/
1504 slepc 389
PetscErrorCode SVDGetOperationCounters(SVD svd,PetscInt* matvecs,PetscInt* dots)
1305 slepc 390
{
1329 slepc 391
  PetscErrorCode ierr;
392
 
1305 slepc 393
  PetscFunctionBegin;
394
  PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
395
  if (matvecs) *matvecs = svd->matvecs;
1329 slepc 396
  if (dots) {
397
    ierr = IPGetOperationCounters(svd->ip,dots);CHKERRQ(ierr);
398
  }
1305 slepc 399
  PetscFunctionReturn(0);
400
}