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