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: }