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