Actual source code: svdopts.c

  1: /*
  2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  4:    Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain

  6:    This file is part of SLEPc.
  7:    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
  8:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  9: */
 10: /*
 11:    SVD routines for setting solver options
 12: */

 14: #include <slepc/private/svdimpl.h>
 15: #include <petscdraw.h>

 17: /*@
 18:    SVDSetImplicitTranspose - Indicates how to handle the transpose of the matrix
 19:    associated with the singular value problem.

 21:    Logically Collective

 23:    Input Parameters:
 24: +  svd  - the singular value solver context
 25: -  impl - how to handle the transpose (implicitly or not)

 27:    Options Database Key:
 28: .  -svd_implicittranspose (true|false) - enable the implicit transpose mode

 30:    Notes:
 31:    By default, the transpose of the matrix is explicitly built (if the matrix
 32:    has defined the `MatTranspose()` operation, `MATOP_TRANSPOSE`).

 34:    If this flag is set to `PETSC_TRUE`, the solver does not build the transpose, but
 35:    handles it implicitly via `MatMultTranspose()` (or `MatMultHermitianTranspose()`
 36:    in the complex case) operations. This is likely to be more inefficient
 37:    than the default behavior, both sequentially and in parallel, but
 38:    requires less storage.

 40:    Level: advanced

 42: .seealso: [](ch:svd), `SVDGetImplicitTranspose()`, `SVDSolve()`, `SVDSetOperators()`
 43: @*/
 44: PetscErrorCode SVDSetImplicitTranspose(SVD svd,PetscBool impl)
 45: {
 46:   PetscFunctionBegin;
 49:   if (svd->impltrans!=impl) {
 50:     svd->impltrans = impl;
 51:     svd->state     = SVD_STATE_INITIAL;
 52:   }
 53:   PetscFunctionReturn(PETSC_SUCCESS);
 54: }

 56: /*@
 57:    SVDGetImplicitTranspose - Gets the mode used to handle the transpose
 58:    of the matrix associated with the singular value problem.

 60:    Not Collective

 62:    Input Parameter:
 63: .  svd  - the singular value solver context

 65:    Output Parameter:
 66: .  impl - how to handle the transpose (implicitly or not)

 68:    Level: advanced

 70: .seealso: [](ch:svd), `SVDSetImplicitTranspose()`, `SVDSolve()`, `SVDSetOperators()`
 71: @*/
 72: PetscErrorCode SVDGetImplicitTranspose(SVD svd,PetscBool *impl)
 73: {
 74:   PetscFunctionBegin;
 76:   PetscAssertPointer(impl,2);
 77:   *impl = svd->impltrans;
 78:   PetscFunctionReturn(PETSC_SUCCESS);
 79: }

 81: /*@
 82:    SVDSetTolerances - Sets the tolerance and maximum iteration count used
 83:    by the `SVD` convergence tests.

 85:    Logically Collective

 87:    Input Parameters:
 88: +  svd - the singular value solver context
 89: .  tol - the convergence tolerance
 90: -  maxits - maximum number of iterations to use

 92:    Options Database Keys:
 93: +  -svd_tol tol       - sets the convergence tolerance
 94: -  -svd_max_it maxits - sets the maximum number of iterations allowed

 96:    Note:
 97:    Use `PETSC_CURRENT` to retain the current value of any of the parameters.
 98:    Use `PETSC_DETERMINE` for either argument to assign a default value computed
 99:    internally (may be different in each solver).
100:    For `maxits` use `PETSC_UNLIMITED` to indicate there is no upper bound on this value.

102:    Level: intermediate

104: .seealso: [](ch:svd), `SVDGetTolerances()`
105: @*/
106: PetscErrorCode SVDSetTolerances(SVD svd,PetscReal tol,PetscInt maxits)
107: {
108:   PetscFunctionBegin;
112:   if (tol == (PetscReal)PETSC_DETERMINE) {
113:     svd->tol   = PETSC_DETERMINE;
114:     svd->state = SVD_STATE_INITIAL;
115:   } else if (tol != (PetscReal)PETSC_CURRENT) {
116:     PetscCheck(tol>0.0,PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of tol. Must be > 0");
117:     svd->tol = tol;
118:   }
119:   if (maxits == PETSC_DETERMINE) {
120:     svd->max_it = PETSC_DETERMINE;
121:     svd->state  = SVD_STATE_INITIAL;
122:   } else if (maxits == PETSC_UNLIMITED) {
123:     svd->max_it = PETSC_INT_MAX;
124:   } else if (maxits != PETSC_CURRENT) {
125:     PetscCheck(maxits>0,PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of maxits. Must be > 0");
126:     svd->max_it = maxits;
127:   }
128:   PetscFunctionReturn(PETSC_SUCCESS);
129: }

131: /*@
132:    SVDGetTolerances - Gets the tolerance and maximum
133:    iteration count used by the default SVD convergence tests.

135:    Not Collective

137:    Input Parameter:
138: .  svd - the singular value solver context

140:    Output Parameters:
141: +  tol - the convergence tolerance
142: -  maxits - maximum number of iterations

144:    Notes:
145:    The user can specify `NULL` for any parameter that is not needed.

147:    Level: intermediate

149: .seealso: [](ch:svd), `SVDSetTolerances()`
150: @*/
151: PetscErrorCode SVDGetTolerances(SVD svd,PetscReal *tol,PetscInt *maxits)
152: {
153:   PetscFunctionBegin;
155:   if (tol)    *tol    = svd->tol;
156:   if (maxits) *maxits = svd->max_it;
157:   PetscFunctionReturn(PETSC_SUCCESS);
158: }

160: /*@
161:    SVDSetThreshold - Sets the threshold used in the threshold stopping test.

163:    Logically Collective

165:    Input Parameters:
166: +  svd   - the singular value solver context
167: .  thres - the threshold value
168: -  rel   - whether the threshold is relative or not

170:    Options Database Keys:
171: +  -svd_threshold_absolute thres - sets an absolute threshold
172: -  -svd_threshold_relative thres - sets a relative threshold

174:    Notes:
175:    This function internally calls `SVDSetStoppingTest()` to set a special stopping
176:    test based on the threshold, where singular values are computed in sequence
177:    until the next singular value approximation is below the threshold `thres`.

179:    If the solver is configured to compute smallest singular values, then the
180:    threshold must be interpreted in the opposite direction, i.e., the computation
181:    will stop when the next singular value approximation is above the threshold.

183:    In the case of largest singular values, the threshold can be made relative
184:    with respect to the largest singular value (i.e., the matrix norm). Otherwise,
185:    the argument `rel` should be `PETSC_FALSE`.

187:    When the next singular value approximation does not satisfy the threshold criterion,
188:    the solver will carry out an additional iteration/restart. This provides more
189:    guarantees that singular value multiplicity is resolved correctly. As a result,
190:    sometimes the solver will return more converged singular values than strictly
191:    satisfying the criterion.

193:    Since the number of computed singular values is not known a priori, the solver
194:    will need to reallocate the basis of vectors internally, to have enough room
195:    to accommodate all the singular vectors. Hence, this option must be used with
196:    caution to avoid out-of-memory problems. The recommendation is to set the value
197:    of `ncv` to be larger than the estimated number of singular values, to minimize
198:    the number of reallocations.

200:    This functionality is most useful when computing largest singular values. A
201:    typical use case is to compute a low rank approximation of a matrix. Suppose
202:    we know that singular values decay abruptly around a certain index $k$, which
203:    is unknown. Then using a small relative threshold such as 0.2 will guarantee that
204:    the computed singular vectors capture the numerical rank $k$. However, if the matrix
205:    does not have low rank, i.e., singular values decay progressively, then a
206:    value of 0.2 will imply a very high cost, both computationally and in memory.

208:    If a number of wanted singular values has been set with `SVDSetDimensions()`
209:    it is also taken into account and the solver will stop when one of the two
210:    conditions (threshold or number of converged values) is met.

212:    Use `SVDSetStoppingTest()` to return to the usual computation of a fixed number
213:    of singular values.

215:    Level: advanced

217: .seealso: [](ch:svd), `SVDGetThreshold()`, `SVDSetStoppingTest()`, `SVDSetDimensions()`, `SVDSetWhichSingularTriplets()`
218: @*/
219: PetscErrorCode SVDSetThreshold(SVD svd,PetscReal thres,PetscBool rel)
220: {
221:   PetscFunctionBegin;
225:   PetscCheck(thres>0.0,PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of the threshold. Must be > 0");
226:   if (svd->thres != thres || svd->threlative != rel) {
227:     svd->thres = thres;
228:     svd->threlative = rel;
229:     svd->state = SVD_STATE_INITIAL;
230:     PetscCall(SVDSetStoppingTest(svd,SVD_STOP_THRESHOLD));
231:   }
232:   PetscFunctionReturn(PETSC_SUCCESS);
233: }

235: /*@
236:    SVDGetThreshold - Gets the threshold used by the threshold stopping test.

238:    Not Collective

240:    Input Parameter:
241: .  svd - the singular value solver context

243:    Output Parameters:
244: +  thres - the threshold
245: -  rel   - whether the threshold is relative or not

247:    Level: advanced

249: .seealso: [](ch:svd), `SVDSetThreshold()`
250: @*/
251: PetscErrorCode SVDGetThreshold(SVD svd,PetscReal *thres,PetscBool *rel)
252: {
253:   PetscFunctionBegin;
255:   if (thres) *thres = svd->thres;
256:   if (rel)   *rel   = svd->threlative;
257:   PetscFunctionReturn(PETSC_SUCCESS);
258: }

260: /*@
261:    SVDSetDimensions - Sets the number of singular values to compute
262:    and the dimension of the subspace.

264:    Logically Collective

266:    Input Parameters:
267: +  svd - the singular value solver context
268: .  nsv - number of singular values to compute
269: .  ncv - the maximum dimension of the subspace to be used by the solver
270: -  mpd - the maximum dimension allowed for the projected problem

272:    Options Database Keys:
273: +  -svd_nsv nsv - sets the number of singular values
274: .  -svd_ncv ncv - sets the dimension of the subspace
275: -  -svd_mpd mpd - sets the maximum projected dimension

277:    Notes:
278:    Use `PETSC_DETERMINE` for `ncv` and `mpd` to assign a reasonably good value, which is
279:    dependent on the solution method and the number of singular values required. For
280:    any of the arguments, use `PETSC_CURRENT` to preserve the current value.

282:    The parameters `ncv` and `mpd` are intimately related, so that the user is advised
283:    to set one of them at most. Normal usage is\:

285:     1. In cases where `nsv` is small, the user sets `ncv` (a reasonable default is `2*nsv`).
286:     1. In cases where `nsv` is large, the user sets `mpd`.

288:    The value of `ncv` should always be between `nsv` and `(nsv+mpd)`, typically
289:    `ncv=nsv+mpd`. If `nsv` is not too large, `mpd=nsv` is a reasonable choice, otherwise
290:    a smaller value should be used.

292:    Level: intermediate

294: .seealso: [](ch:svd), `SVDGetDimensions()`
295: @*/
296: PetscErrorCode SVDSetDimensions(SVD svd,PetscInt nsv,PetscInt ncv,PetscInt mpd)
297: {
298:   PetscFunctionBegin;
303:   if (nsv != PETSC_CURRENT) {
304:     PetscCheck(nsv>0,PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of nsv. Must be > 0");
305:     svd->nsv = nsv;
306:   }
307:   if (ncv == PETSC_DETERMINE) {
308:     svd->ncv = PETSC_DETERMINE;
309:   } else if (ncv != PETSC_CURRENT) {
310:     PetscCheck(ncv>0,PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of ncv. Must be > 0");
311:     svd->ncv = ncv;
312:   }
313:   if (mpd == PETSC_DETERMINE) {
314:     svd->mpd = PETSC_DETERMINE;
315:   } else if (mpd != PETSC_CURRENT) {
316:     PetscCheck(mpd>0,PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of mpd. Must be > 0");
317:     svd->mpd = mpd;
318:   }
319:   svd->state = SVD_STATE_INITIAL;
320:   PetscFunctionReturn(PETSC_SUCCESS);
321: }

323: /*@
324:    SVDGetDimensions - Gets the number of singular values to compute
325:    and the dimension of the subspace.

327:    Not Collective

329:    Input Parameter:
330: .  svd - the singular value solver context

332:    Output Parameters:
333: +  nsv - number of singular values to compute
334: .  ncv - the maximum dimension of the subspace to be used by the solver
335: -  mpd - the maximum dimension allowed for the projected problem

337:    Notes:
338:    The user can specify `NULL` for any parameter that is not needed.

340:    Level: intermediate

342: .seealso: [](ch:svd), `SVDSetDimensions()`
343: @*/
344: PetscErrorCode SVDGetDimensions(SVD svd,PetscInt *nsv,PetscInt *ncv,PetscInt *mpd)
345: {
346:   PetscFunctionBegin;
348:   if (nsv) *nsv = svd->nsv? svd->nsv: 1;
349:   if (ncv) *ncv = svd->ncv;
350:   if (mpd) *mpd = svd->mpd;
351:   PetscFunctionReturn(PETSC_SUCCESS);
352: }

354: /*@
355:     SVDSetWhichSingularTriplets - Specifies which singular triplets are
356:     to be sought.

358:     Logically Collective

360:     Input Parameter:
361: .   svd - the singular value solver context

363:     Output Parameter:
364: .   which - which singular triplets are to be sought, see `SVDWhich` for possible values

366:     Options Database Keys:
367: +   -svd_largest  - sets largest singular values
368: -   -svd_smallest - sets smallest singular values

370:     Level: intermediate

372: .seealso: [](ch:svd), `SVDGetWhichSingularTriplets()`, `SVDWhich`
373: @*/
374: PetscErrorCode SVDSetWhichSingularTriplets(SVD svd,SVDWhich which)
375: {
376:   PetscFunctionBegin;
379:   switch (which) {
380:     case SVD_LARGEST:
381:     case SVD_SMALLEST:
382:       if (svd->which != which) {
383:         svd->state = SVD_STATE_INITIAL;
384:         svd->which = which;
385:       }
386:       break;
387:   default:
388:     SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Invalid 'which' parameter");
389:   }
390:   PetscFunctionReturn(PETSC_SUCCESS);
391: }

393: /*@
394:     SVDGetWhichSingularTriplets - Returns which singular triplets are
395:     to be sought.

397:     Not Collective

399:     Input Parameter:
400: .   svd - the singular value solver context

402:     Output Parameter:
403: .   which - which singular triplets are to be sought

405:     Level: intermediate

407: .seealso: [](ch:svd), `SVDSetWhichSingularTriplets()`, `SVDWhich`
408: @*/
409: PetscErrorCode SVDGetWhichSingularTriplets(SVD svd,SVDWhich *which)
410: {
411:   PetscFunctionBegin;
413:   PetscAssertPointer(which,2);
414:   *which = svd->which;
415:   PetscFunctionReturn(PETSC_SUCCESS);
416: }

418: /*@
419:    SVDSetConvergenceTestFunction - Sets a function to compute the error estimate
420:    used in the convergence test.

422:    Logically Collective

424:    Input Parameters:
425: +  svd     - the singular value solver context
426: .  conv    - the convergence test function, see `SVDConvergenceTestFn` for the calling sequence
427: .  ctx     - context for private data for the convergence routine (may be `NULL`)
428: -  destroy - a routine for destroying the context (may be `NULL`), see `PetscCtxDestroyFn`
429:              for the calling sequence

431:    Notes:
432:    When this is called with a user-defined function, then the convergence
433:    criterion is set to `SVD_CONV_USER`, see `SVDSetConvergenceTest()`.

435:    If the error estimate returned by the convergence test function is less than
436:    the tolerance, then the singular value is accepted as converged.

438:    Level: advanced

440: .seealso: [](ch:svd), `SVDSetConvergenceTest()`, `SVDSetTolerances()`
441: @*/
442: PetscErrorCode SVDSetConvergenceTestFunction(SVD svd,SVDConvergenceTestFn *conv,PetscCtx ctx,PetscCtxDestroyFn *destroy)
443: {
444:   PetscFunctionBegin;
446:   if (svd->convergeddestroy) PetscCall((*svd->convergeddestroy)(&svd->convergedctx));
447:   svd->convergeduser    = conv;
448:   svd->convergeddestroy = destroy;
449:   svd->convergedctx     = ctx;
450:   if (conv == SVDConvergedAbsolute) svd->conv = SVD_CONV_ABS;
451:   else if (conv == SVDConvergedRelative) svd->conv = SVD_CONV_REL;
452:   else if (conv == SVDConvergedNorm) svd->conv = SVD_CONV_NORM;
453:   else if (conv == SVDConvergedMaxIt) svd->conv = SVD_CONV_MAXIT;
454:   else {
455:     svd->conv      = SVD_CONV_USER;
456:     svd->converged = svd->convergeduser;
457:   }
458:   PetscFunctionReturn(PETSC_SUCCESS);
459: }

461: /*@
462:    SVDSetConvergenceTest - Specifies how to compute the error estimate
463:    used in the convergence test.

465:    Logically Collective

467:    Input Parameters:
468: +  svd  - the singular value solver context
469: -  conv - the type of convergence test, see `SVDConv` for possible values

471:    Options Database Keys:
472: +  -svd_conv_abs   - sets the absolute convergence test
473: .  -svd_conv_rel   - sets the convergence test relative to the singular value
474: .  -svd_conv_norm  - sets the convergence test relative to the matrix norms
475: .  -svd_conv_maxit - forces the maximum number of iterations as set by `-svd_max_it`
476: -  -svd_conv_user  - selects the user-defined convergence test

478:    Note:
479:    The default in standard SVD is `SVD_CONV_REL`, while in GSVD the default is `SVD_CONV_NORM`.

481:    Level: intermediate

483: .seealso: [](ch:svd), `SVDGetConvergenceTest()`, `SVDSetConvergenceTestFunction()`, `SVDSetStoppingTest()`, `SVDConv`
484: @*/
485: PetscErrorCode SVDSetConvergenceTest(SVD svd,SVDConv conv)
486: {
487:   PetscFunctionBegin;
490:   switch (conv) {
491:     case SVD_CONV_ABS:   svd->converged = SVDConvergedAbsolute; break;
492:     case SVD_CONV_REL:   svd->converged = SVDConvergedRelative; break;
493:     case SVD_CONV_NORM:  svd->converged = SVDConvergedNorm; break;
494:     case SVD_CONV_MAXIT: svd->converged = SVDConvergedMaxIt; break;
495:     case SVD_CONV_USER:
496:       PetscCheck(svd->convergeduser,PetscObjectComm((PetscObject)svd),PETSC_ERR_ORDER,"Must call SVDSetConvergenceTestFunction() first");
497:       svd->converged = svd->convergeduser;
498:       break;
499:     default:
500:       SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Invalid 'conv' value");
501:   }
502:   svd->conv = conv;
503:   PetscFunctionReturn(PETSC_SUCCESS);
504: }

506: /*@
507:    SVDGetConvergenceTest - Gets the method used to compute the error estimate
508:    used in the convergence test.

510:    Not Collective

512:    Input Parameter:
513: .  svd   - the singular value solver context

515:    Output Parameter:
516: .  conv  - the type of convergence test

518:    Level: intermediate

520: .seealso: [](ch:svd), `SVDSetConvergenceTest()`, `SVDConv`
521: @*/
522: PetscErrorCode SVDGetConvergenceTest(SVD svd,SVDConv *conv)
523: {
524:   PetscFunctionBegin;
526:   PetscAssertPointer(conv,2);
527:   *conv = svd->conv;
528:   PetscFunctionReturn(PETSC_SUCCESS);
529: }

531: /*@
532:    SVDSetStoppingTestFunction - Sets a function to decide when to stop the outer
533:    iteration of the singular value solver.

535:    Logically Collective

537:    Input Parameters:
538: +  svd     - the singular value solver context
539: .  stop    - the stopping test function, see `SVDStoppingTestFn` for the calling sequence
540: .  ctx     - context for private data for the stopping routine (may be `NULL`)
541: -  destroy - a routine for destroying the context (may be `NULL`), see `PetscCtxDestroyFn`
542:              for the calling sequence

544:    Note:
545:    When implementing a function for this, normal usage is to first call the
546:    default routine `SVDStoppingBasic()` and then set `reason` to `SVD_CONVERGED_USER`
547:    if some user-defined conditions have been met. To let the singular value solver
548:    continue iterating, the result must be left as `SVD_CONVERGED_ITERATING`.

550:    Level: advanced

552: .seealso: [](ch:svd), `SVDSetStoppingTest()`, `SVDStoppingBasic()`
553: @*/
554: PetscErrorCode SVDSetStoppingTestFunction(SVD svd,SVDStoppingTestFn *stop,PetscCtx ctx,PetscCtxDestroyFn *destroy)
555: {
556:   PetscFunctionBegin;
558:   if (svd->stoppingdestroy) PetscCall((*svd->stoppingdestroy)(&svd->stoppingctx));
559:   svd->stoppinguser    = stop;
560:   svd->stoppingdestroy = destroy;
561:   svd->stoppingctx     = ctx;
562:   if (stop == SVDStoppingBasic) PetscCall(SVDSetStoppingTest(svd,SVD_STOP_BASIC));
563:   else if (stop == SVDStoppingThreshold) PetscCall(SVDSetStoppingTest(svd,SVD_STOP_THRESHOLD));
564:   else {
565:     svd->stop     = SVD_STOP_USER;
566:     svd->stopping = svd->stoppinguser;
567:   }
568:   PetscFunctionReturn(PETSC_SUCCESS);
569: }

571: /*@
572:    SVDSetStoppingTest - Specifies how to decide the termination of the outer
573:    loop of the singular value solver.

575:    Logically Collective

577:    Input Parameters:
578: +  svd  - the singular value solver context
579: -  stop - the type of stopping test, see `SVDStop`

581:    Options Database Keys:
582: +  -svd_stop_basic     - sets the default stopping test
583: .  -svd_stop_threshold - sets the threshold stopping test
584: -  -svd_stop_user      - selects the user-defined stopping test

586:    Level: advanced

588: .seealso: [](ch:svd), `SVDGetStoppingTest()`, `SVDSetStoppingTestFunction()`, `SVDSetConvergenceTest()`, `SVDStop`
589: @*/
590: PetscErrorCode SVDSetStoppingTest(SVD svd,SVDStop stop)
591: {
592:   PetscFunctionBegin;
595:   switch (stop) {
596:     case SVD_STOP_BASIC: svd->stopping = SVDStoppingBasic; break;
597:     case SVD_STOP_THRESHOLD: svd->stopping = SVDStoppingThreshold; break;
598:     case SVD_STOP_USER:
599:       PetscCheck(svd->stoppinguser,PetscObjectComm((PetscObject)svd),PETSC_ERR_ORDER,"Must call SVDSetStoppingTestFunction() first");
600:       svd->stopping = svd->stoppinguser;
601:       break;
602:     default:
603:       SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Invalid 'stop' value");
604:   }
605:   svd->stop = stop;
606:   PetscFunctionReturn(PETSC_SUCCESS);
607: }

609: /*@
610:    SVDGetStoppingTest - Gets the method used to decide the termination of the outer
611:    loop of the singular value solver.

613:    Not Collective

615:    Input Parameter:
616: .  svd   - the singular value solver context

618:    Output Parameter:
619: .  stop  - the type of stopping test

621:    Level: advanced

623: .seealso: [](ch:svd), `SVDSetStoppingTest()`, `SVDStop`
624: @*/
625: PetscErrorCode SVDGetStoppingTest(SVD svd,SVDStop *stop)
626: {
627:   PetscFunctionBegin;
629:   PetscAssertPointer(stop,2);
630:   *stop = svd->stop;
631:   PetscFunctionReturn(PETSC_SUCCESS);
632: }

634: /*@
635:    SVDMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type
636:    indicated by the user.

638:    Collective

640:    Input Parameters:
641: +  svd      - the singular value solver context
642: .  opt      - the command line option for this monitor
643: .  name     - the monitor type one is seeking
644: .  ctx      - an optional user context for the monitor, or `NULL`
645: -  trackall - whether this monitor tracks all singular values or not

647:    Level: developer

649: .seealso: [](ch:svd), `SVDMonitorSet()`, `SVDSetTrackAll()`
650: @*/
651: PetscErrorCode SVDMonitorSetFromOptions(SVD svd,const char opt[],const char name[],PetscCtx ctx,PetscBool trackall)
652: {
653:   PetscErrorCode       (*mfunc)(SVD,PetscInt,PetscInt,PetscReal*,PetscReal*,PetscInt,void*);
654:   PetscErrorCode       (*cfunc)(PetscViewer,PetscViewerFormat,void*,PetscViewerAndFormat**);
655:   PetscErrorCode       (*dfunc)(PetscViewerAndFormat**);
656:   PetscViewerAndFormat *vf;
657:   PetscViewer          viewer;
658:   PetscViewerFormat    format;
659:   PetscViewerType      vtype;
660:   char                 key[PETSC_MAX_PATH_LEN];
661:   PetscBool            flg;

663:   PetscFunctionBegin;
664:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)svd),((PetscObject)svd)->options,((PetscObject)svd)->prefix,opt,&viewer,&format,&flg));
665:   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);

667:   PetscCall(PetscViewerGetType(viewer,&vtype));
668:   PetscCall(SlepcMonitorMakeKey_Internal(name,vtype,format,key));
669:   PetscCall(PetscFunctionListFind(SVDMonitorList,key,&mfunc));
670:   PetscCheck(mfunc,PetscObjectComm((PetscObject)svd),PETSC_ERR_SUP,"Specified viewer and format not supported");
671:   PetscCall(PetscFunctionListFind(SVDMonitorCreateList,key,&cfunc));
672:   PetscCall(PetscFunctionListFind(SVDMonitorDestroyList,key,&dfunc));
673:   if (!cfunc) cfunc = PetscViewerAndFormatCreate_Internal;
674:   if (!dfunc) dfunc = PetscViewerAndFormatDestroy;

676:   PetscCall((*cfunc)(viewer,format,ctx,&vf));
677:   PetscCall(PetscViewerDestroy(&viewer));
678:   PetscCall(SVDMonitorSet(svd,mfunc,vf,(PetscCtxDestroyFn*)dfunc));
679:   if (trackall) PetscCall(SVDSetTrackAll(svd,PETSC_TRUE));
680:   PetscFunctionReturn(PETSC_SUCCESS);
681: }

683: /*@
684:    SVDSetFromOptions - Sets `SVD` options from the options database.
685:    This routine must be called before `SVDSetUp()` if the user is to be
686:    allowed to configure the solver.

688:    Collective

690:    Input Parameter:
691: .  svd - the singular value solver context

693:    Note:
694:    To see all options, run your program with the `-help` option.

696:    Level: beginner

698: .seealso: [](ch:svd), `SVDSetOptionsPrefix()`
699: @*/
700: PetscErrorCode SVDSetFromOptions(SVD svd)
701: {
702:   char           type[256];
703:   PetscBool      set,flg,val,flg1,flg2,flg3;
704:   PetscInt       i,j,k;
705:   PetscReal      r;

707:   PetscFunctionBegin;
709:   PetscCall(SVDRegisterAll());
710:   PetscObjectOptionsBegin((PetscObject)svd);
711:     PetscCall(PetscOptionsFList("-svd_type","SVD solver method","SVDSetType",SVDList,(char*)(((PetscObject)svd)->type_name?((PetscObject)svd)->type_name:SVDCROSS),type,sizeof(type),&flg));
712:     if (flg) PetscCall(SVDSetType(svd,type));
713:     else if (!((PetscObject)svd)->type_name) PetscCall(SVDSetType(svd,SVDCROSS));

715:     PetscCall(PetscOptionsBoolGroupBegin("-svd_standard","Singular value decomposition (SVD)","SVDSetProblemType",&flg));
716:     if (flg) PetscCall(SVDSetProblemType(svd,SVD_STANDARD));
717:     PetscCall(PetscOptionsBoolGroup("-svd_generalized","Generalized singular value decomposition (GSVD)","SVDSetProblemType",&flg));
718:     if (flg) PetscCall(SVDSetProblemType(svd,SVD_GENERALIZED));
719:     PetscCall(PetscOptionsBoolGroupEnd("-svd_hyperbolic","Hyperbolic singular value decomposition (HSVD)","SVDSetProblemType",&flg));
720:     if (flg) PetscCall(SVDSetProblemType(svd,SVD_HYPERBOLIC));

722:     PetscCall(PetscOptionsBool("-svd_implicittranspose","Handle matrix transpose implicitly","SVDSetImplicitTranspose",svd->impltrans,&val,&flg));
723:     if (flg) PetscCall(SVDSetImplicitTranspose(svd,val));

725:     i = svd->max_it;
726:     PetscCall(PetscOptionsInt("-svd_max_it","Maximum number of iterations","SVDSetTolerances",svd->max_it,&i,&flg1));
727:     r = svd->tol;
728:     PetscCall(PetscOptionsReal("-svd_tol","Tolerance","SVDSetTolerances",SlepcDefaultTol(svd->tol),&r,&flg2));
729:     if (flg1 || flg2) PetscCall(SVDSetTolerances(svd,r,i));

731:     r = svd->thres;
732:     PetscCall(PetscOptionsReal("-svd_threshold_absolute","Absolute threshold","SVDSetThreshold",r,&r,&flg));
733:     if (flg) PetscCall(SVDSetThreshold(svd,r,PETSC_FALSE));
734:     PetscCall(PetscOptionsReal("-svd_threshold_relative","Relative threshold","SVDSetThreshold",r,&r,&flg));
735:     if (flg) PetscCall(SVDSetThreshold(svd,r,PETSC_TRUE));

737:     PetscCall(PetscOptionsBoolGroupBegin("-svd_conv_abs","Absolute error convergence test","SVDSetConvergenceTest",&flg));
738:     if (flg) PetscCall(SVDSetConvergenceTest(svd,SVD_CONV_ABS));
739:     PetscCall(PetscOptionsBoolGroup("-svd_conv_rel","Relative error convergence test","SVDSetConvergenceTest",&flg));
740:     if (flg) PetscCall(SVDSetConvergenceTest(svd,SVD_CONV_REL));
741:     PetscCall(PetscOptionsBoolGroup("-svd_conv_norm","Convergence test relative to the matrix norms","SVDSetConvergenceTest",&flg));
742:     if (flg) PetscCall(SVDSetConvergenceTest(svd,SVD_CONV_NORM));
743:     PetscCall(PetscOptionsBoolGroup("-svd_conv_maxit","Maximum iterations convergence test","SVDSetConvergenceTest",&flg));
744:     if (flg) PetscCall(SVDSetConvergenceTest(svd,SVD_CONV_MAXIT));
745:     PetscCall(PetscOptionsBoolGroupEnd("-svd_conv_user","User-defined convergence test","SVDSetConvergenceTest",&flg));
746:     if (flg) PetscCall(SVDSetConvergenceTest(svd,SVD_CONV_USER));

748:     PetscCall(PetscOptionsBoolGroupBegin("-svd_stop_basic","Stop iteration if all singular values converged or max_it reached","SVDSetStoppingTest",&flg));
749:     if (flg) PetscCall(SVDSetStoppingTest(svd,SVD_STOP_BASIC));
750:     PetscCall(PetscOptionsBoolGroup("-svd_stop_threshold","Stop iteration if a converged singular value is below/above the threshold","SVDSetStoppingTest",&flg));
751:     if (flg) PetscCall(SVDSetStoppingTest(svd,SVD_STOP_THRESHOLD));
752:     PetscCall(PetscOptionsBoolGroupEnd("-svd_stop_user","User-defined stopping test","SVDSetStoppingTest",&flg));
753:     if (flg) PetscCall(SVDSetStoppingTest(svd,SVD_STOP_USER));

755:     i = svd->nsv;
756:     PetscCall(PetscOptionsInt("-svd_nsv","Number of singular values to compute","SVDSetDimensions",svd->nsv,&i,&flg1));
757:     if (!flg1) i = PETSC_CURRENT;
758:     j = svd->ncv;
759:     PetscCall(PetscOptionsInt("-svd_ncv","Number of basis vectors","SVDSetDimensions",svd->ncv,&j,&flg2));
760:     k = svd->mpd;
761:     PetscCall(PetscOptionsInt("-svd_mpd","Maximum dimension of projected problem","SVDSetDimensions",svd->mpd,&k,&flg3));
762:     if (flg1 || flg2 || flg3) PetscCall(SVDSetDimensions(svd,i,j,k));

764:     PetscCall(PetscOptionsBoolGroupBegin("-svd_largest","Compute largest singular values","SVDSetWhichSingularTriplets",&flg));
765:     if (flg) PetscCall(SVDSetWhichSingularTriplets(svd,SVD_LARGEST));
766:     PetscCall(PetscOptionsBoolGroupEnd("-svd_smallest","Compute smallest singular values","SVDSetWhichSingularTriplets",&flg));
767:     if (flg) PetscCall(SVDSetWhichSingularTriplets(svd,SVD_SMALLEST));

769:     /* -----------------------------------------------------------------------*/
770:     /*
771:       Cancels all monitors hardwired into code before call to SVDSetFromOptions()
772:     */
773:     PetscCall(PetscOptionsBool("-svd_monitor_cancel","Remove any hardwired monitor routines","SVDMonitorCancel",PETSC_FALSE,&flg,&set));
774:     if (set && flg) PetscCall(SVDMonitorCancel(svd));
775:     PetscCall(SVDMonitorSetFromOptions(svd,"-svd_monitor","first_approximation",NULL,PETSC_FALSE));
776:     PetscCall(SVDMonitorSetFromOptions(svd,"-svd_monitor_all","all_approximations",NULL,PETSC_TRUE));
777:     PetscCall(SVDMonitorSetFromOptions(svd,"-svd_monitor_conv","convergence_history",NULL,PETSC_FALSE));
778:     PetscCall(SVDMonitorSetFromOptions(svd,"-svd_monitor_conditioning","conditioning",NULL,PETSC_FALSE));

780:     /* -----------------------------------------------------------------------*/
781:     PetscCall(PetscOptionsName("-svd_view","Print detailed information on solver used","SVDView",&set));
782:     PetscCall(PetscOptionsName("-svd_view_vectors","View computed singular vectors","SVDVectorsView",&set));
783:     PetscCall(PetscOptionsName("-svd_view_values","View computed singular values","SVDValuesView",&set));
784:     PetscCall(PetscOptionsName("-svd_converged_reason","Print reason for convergence, and number of iterations","SVDConvergedReasonView",&set));
785:     PetscCall(PetscOptionsName("-svd_error_absolute","Print absolute errors of each singular triplet","SVDErrorView",&set));
786:     PetscCall(PetscOptionsName("-svd_error_relative","Print relative errors of each singular triplet","SVDErrorView",&set));
787:     PetscCall(PetscOptionsName("-svd_error_norm","Print errors relative to the matrix norms of each singular triplet","SVDErrorView",&set));

789:     PetscTryTypeMethod(svd,setfromoptions,PetscOptionsObject);
790:     PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)svd,PetscOptionsObject));
791:   PetscOptionsEnd();

793:   if (!svd->V) PetscCall(SVDGetBV(svd,&svd->V,NULL));
794:   PetscCall(BVSetFromOptions(svd->V));
795:   if (!svd->U) PetscCall(SVDGetBV(svd,NULL,&svd->U));
796:   PetscCall(BVSetFromOptions(svd->U));
797:   if (!svd->ds) PetscCall(SVDGetDS(svd,&svd->ds));
798:   PetscCall(SVDSetDSType(svd));
799:   PetscCall(DSSetFromOptions(svd->ds));
800:   svd->setfromoptionscalled++;
801:   PetscFunctionReturn(PETSC_SUCCESS);
802: }

804: /*@
805:    SVDSetProblemType - Specifies the type of the singular value problem.

807:    Logically Collective

809:    Input Parameters:
810: +  svd  - the singular value solver context
811: -  type - a known type of singular value problem

813:    Options Database Keys:
814: +  -svd_standard    - standard singular value decomposition (SVD)
815: .  -svd_generalized - generalized singular value problem (GSVD)
816: -  -svd_hyperbolic  - hyperbolic singular value problem (HSVD)

818:    Note:
819:    The GSVD requires that two matrices have been passed via `SVDSetOperators()`.
820:    The HSVD requires that a signature matrix has been passed via `SVDSetSignature()`.

822:    Level: intermediate

824: .seealso: [](ch:svd), `SVDSetOperators()`, `SVDSetSignature()`, `SVDSetType()`, `SVDGetProblemType()`, `SVDProblemType`
825: @*/
826: PetscErrorCode SVDSetProblemType(SVD svd,SVDProblemType type)
827: {
828:   PetscFunctionBegin;
831:   if (type == svd->problem_type) PetscFunctionReturn(PETSC_SUCCESS);
832:   switch (type) {
833:     case SVD_STANDARD:
834:       svd->isgeneralized = PETSC_FALSE;
835:       svd->ishyperbolic  = PETSC_FALSE;
836:       break;
837:     case SVD_GENERALIZED:
838:       svd->isgeneralized = PETSC_TRUE;
839:       svd->ishyperbolic  = PETSC_FALSE;
840:       break;
841:     case SVD_HYPERBOLIC:
842:       svd->isgeneralized = PETSC_FALSE;
843:       svd->ishyperbolic  = PETSC_TRUE;
844:       break;
845:     default:
846:       SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_WRONG,"Unknown singular value problem type");
847:   }
848:   svd->problem_type = type;
849:   svd->state = SVD_STATE_INITIAL;
850:   PetscFunctionReturn(PETSC_SUCCESS);
851: }

853: /*@
854:    SVDGetProblemType - Gets the problem type from the SVD object.

856:    Not Collective

858:    Input Parameter:
859: .  svd - the singular value solver context

861:    Output Parameter:
862: .  type - the problem type

864:    Level: intermediate

866: .seealso: [](ch:svd), `SVDSetProblemType()`, `SVDProblemType`
867: @*/
868: PetscErrorCode SVDGetProblemType(SVD svd,SVDProblemType *type)
869: {
870:   PetscFunctionBegin;
872:   PetscAssertPointer(type,2);
873:   *type = svd->problem_type;
874:   PetscFunctionReturn(PETSC_SUCCESS);
875: }

877: /*@
878:    SVDIsGeneralized - Ask if the SVD object corresponds to a generalized
879:    singular value problem.

881:    Not Collective

883:    Input Parameter:
884: .  svd - the singular value solver context

886:    Output Parameter:
887: .  is - the answer

889:    Level: intermediate

891: .seealso: [](ch:svd), `SVDIsHyperbolic()`
892: @*/
893: PetscErrorCode SVDIsGeneralized(SVD svd,PetscBool* is)
894: {
895:   PetscFunctionBegin;
897:   PetscAssertPointer(is,2);
898:   *is = svd->isgeneralized;
899:   PetscFunctionReturn(PETSC_SUCCESS);
900: }

902: /*@
903:    SVDIsHyperbolic - Ask if the SVD object corresponds to a hyperbolic
904:    singular value problem.

906:    Not Collective

908:    Input Parameter:
909: .  svd - the singular value solver context

911:    Output Parameter:
912: .  is - the answer

914:    Level: intermediate

916: .seealso: [](ch:svd), `SVDIsGeneralized()`
917: @*/
918: PetscErrorCode SVDIsHyperbolic(SVD svd,PetscBool* is)
919: {
920:   PetscFunctionBegin;
922:   PetscAssertPointer(is,2);
923:   *is = svd->ishyperbolic;
924:   PetscFunctionReturn(PETSC_SUCCESS);
925: }

927: /*@
928:    SVDSetTrackAll - Specifies if the solver must compute the residual norm of all
929:    approximate singular value or not.

931:    Logically Collective

933:    Input Parameters:
934: +  svd      - the singular value solver context
935: -  trackall - whether to compute all residuals or not

937:    Notes:
938:    If the user sets `trackall`=`PETSC_TRUE` then the solver computes (or estimates)
939:    the residual norm for each singular value approximation. Computing the residual is
940:    usually an expensive operation and solvers commonly compute only the residual
941:    associated to the first unconverged singular value.

943:    The option `-svd_monitor_all` automatically activates this option.

945:    Level: developer

947: .seealso: [](ch:svd), `SVDGetTrackAll()`
948: @*/
949: PetscErrorCode SVDSetTrackAll(SVD svd,PetscBool trackall)
950: {
951:   PetscFunctionBegin;
954:   svd->trackall = trackall;
955:   PetscFunctionReturn(PETSC_SUCCESS);
956: }

958: /*@
959:    SVDGetTrackAll - Returns the flag indicating whether all residual norms must
960:    be computed or not.

962:    Not Collective

964:    Input Parameter:
965: .  svd - the singular value solver context

967:    Output Parameter:
968: .  trackall - the returned flag

970:    Level: developer

972: .seealso: [](ch:svd), `SVDSetTrackAll()`
973: @*/
974: PetscErrorCode SVDGetTrackAll(SVD svd,PetscBool *trackall)
975: {
976:   PetscFunctionBegin;
978:   PetscAssertPointer(trackall,2);
979:   *trackall = svd->trackall;
980:   PetscFunctionReturn(PETSC_SUCCESS);
981: }

983: /*@
984:    SVDSetOptionsPrefix - Sets the prefix used for searching for all
985:    `SVD` options in the database.

987:    Logically Collective

989:    Input Parameters:
990: +  svd    - the singular value solver context
991: -  prefix - the prefix string to prepend to all `SVD` option requests

993:    Notes:
994:    A hyphen (-) must NOT be given at the beginning of the prefix name.
995:    The first character of all runtime options is AUTOMATICALLY the
996:    hyphen.

998:    For example, to distinguish between the runtime options for two
999:    different `SVD` contexts, one could call
1000: .vb
1001:    SVDSetOptionsPrefix(svd1,"svd1_")
1002:    SVDSetOptionsPrefix(svd2,"svd2_")
1003: .ve

1005:    Level: advanced

1007: .seealso: [](ch:svd), `SVDAppendOptionsPrefix()`, `SVDGetOptionsPrefix()`
1008: @*/
1009: PetscErrorCode SVDSetOptionsPrefix(SVD svd,const char prefix[])
1010: {
1011:   PetscFunctionBegin;
1013:   if (!svd->V) PetscCall(SVDGetBV(svd,&svd->V,&svd->U));
1014:   PetscCall(BVSetOptionsPrefix(svd->V,prefix));
1015:   PetscCall(BVSetOptionsPrefix(svd->U,prefix));
1016:   if (!svd->ds) PetscCall(SVDGetDS(svd,&svd->ds));
1017:   PetscCall(DSSetOptionsPrefix(svd->ds,prefix));
1018:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)svd,prefix));
1019:   PetscFunctionReturn(PETSC_SUCCESS);
1020: }

1022: /*@
1023:    SVDAppendOptionsPrefix - Appends to the prefix used for searching for all
1024:    `SVD` options in the database.

1026:    Logically Collective

1028:    Input Parameters:
1029: +  svd    - the singular value solver context
1030: -  prefix - the prefix string to prepend to all `SVD` option requests

1032:    Notes:
1033:    A hyphen (-) must NOT be given at the beginning of the prefix name.
1034:    The first character of all runtime options is AUTOMATICALLY the hyphen.

1036:    Level: advanced

1038: .seealso: [](ch:svd), `SVDSetOptionsPrefix()`, `SVDGetOptionsPrefix()`
1039: @*/
1040: PetscErrorCode SVDAppendOptionsPrefix(SVD svd,const char prefix[])
1041: {
1042:   PetscFunctionBegin;
1044:   if (!svd->V) PetscCall(SVDGetBV(svd,&svd->V,&svd->U));
1045:   PetscCall(BVAppendOptionsPrefix(svd->V,prefix));
1046:   PetscCall(BVAppendOptionsPrefix(svd->U,prefix));
1047:   if (!svd->ds) PetscCall(SVDGetDS(svd,&svd->ds));
1048:   PetscCall(DSAppendOptionsPrefix(svd->ds,prefix));
1049:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)svd,prefix));
1050:   PetscFunctionReturn(PETSC_SUCCESS);
1051: }

1053: /*@
1054:    SVDGetOptionsPrefix - Gets the prefix used for searching for all
1055:    `SVD` options in the database.

1057:    Not Collective

1059:    Input Parameter:
1060: .  svd - the singular value solver context

1062:    Output Parameter:
1063: .  prefix - pointer to the prefix string used is returned

1065:    Level: advanced

1067: .seealso: [](ch:svd), `SVDSetOptionsPrefix()`, `SVDAppendOptionsPrefix()`
1068: @*/
1069: PetscErrorCode SVDGetOptionsPrefix(SVD svd,const char *prefix[])
1070: {
1071:   PetscFunctionBegin;
1073:   PetscAssertPointer(prefix,2);
1074:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)svd,prefix));
1075:   PetscFunctionReturn(PETSC_SUCCESS);
1076: }