Subversion Repositories slepc-dev

Rev

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