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