Date: 2024-04-26T10:22:45+00:00

Actual source code: svdopts.c
slepc-3.21.1 2024-04-26
Report Typos and Errors

      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 - Activate 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).

     34:    If this flag is set to 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 behaviour, both in sequential and in parallel, but
     38:    requires less storage.

     40:    Level: advanced

     42: .seealso: 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: 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
     83:    iteration count used by the default SVD convergence testers.

     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_DEFAULT for either argument to assign a reasonably good value.

     99:    Level: intermediate

    101: .seealso: SVDGetTolerances()
    102: @*/
    103: PetscErrorCode SVDSetTolerances(SVD svd,PetscReal tol,PetscInt maxits)
    104: {
    105:   PetscFunctionBegin;
    109:   if (tol == (PetscReal)PETSC_DEFAULT) {
    110:     svd->tol   = PETSC_DEFAULT;
    111:     svd->state = SVD_STATE_INITIAL;
    112:   } else {
    113:     PetscCheck(tol>0.0,PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of tol. Must be > 0");
    114:     svd->tol = tol;
    115:   }
    116:   if (maxits == PETSC_DEFAULT || maxits == PETSC_DECIDE) {
    117:     svd->max_it = PETSC_DEFAULT;
    118:     svd->state  = SVD_STATE_INITIAL;
    119:   } else {
    120:     PetscCheck(maxits>0,PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of maxits. Must be > 0");
    121:     svd->max_it = maxits;
    122:   }
    123:   PetscFunctionReturn(PETSC_SUCCESS);
    124: }

    126: /*@C
    127:    SVDGetTolerances - Gets the tolerance and maximum
    128:    iteration count used by the default SVD convergence tests.

    130:    Not Collective

    132:    Input Parameter:
    133: .  svd - the singular value solver context

    135:    Output Parameters:
    136: +  tol - the convergence tolerance
    137: -  maxits - maximum number of iterations

    139:    Notes:
    140:    The user can specify NULL for any parameter that is not needed.

    142:    Level: intermediate

    144: .seealso: SVDSetTolerances()
    145: @*/
    146: PetscErrorCode SVDGetTolerances(SVD svd,PetscReal *tol,PetscInt *maxits)
    147: {
    148:   PetscFunctionBegin;
    150:   if (tol)    *tol    = svd->tol;
    151:   if (maxits) *maxits = svd->max_it;
    152:   PetscFunctionReturn(PETSC_SUCCESS);
    153: }

    155: /*@
    156:    SVDSetDimensions - Sets the number of singular values to compute
    157:    and the dimension of the subspace.

    159:    Logically Collective

    161:    Input Parameters:
    162: +  svd - the singular value solver context
    163: .  nsv - number of singular values to compute
    164: .  ncv - the maximum dimension of the subspace to be used by the solver
    165: -  mpd - the maximum dimension allowed for the projected problem

    167:    Options Database Keys:
    168: +  -svd_nsv <nsv> - Sets the number of singular values
    169: .  -svd_ncv <ncv> - Sets the dimension of the subspace
    170: -  -svd_mpd <mpd> - Sets the maximum projected dimension

    172:    Notes:
    173:    Use PETSC_DEFAULT for ncv and mpd to assign a reasonably good value, which is
    174:    dependent on the solution method and the number of singular values required.

    176:    The parameters ncv and mpd are intimately related, so that the user is advised
    177:    to set one of them at most. Normal usage is that
    178:    (a) in cases where nsv is small, the user sets ncv (a reasonable default is 2*nsv); and
    179:    (b) in cases where nsv is large, the user sets mpd.

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

    185:    Level: intermediate

    187: .seealso: SVDGetDimensions()
    188: @*/
    189: PetscErrorCode SVDSetDimensions(SVD svd,PetscInt nsv,PetscInt ncv,PetscInt mpd)
    190: {
    191:   PetscFunctionBegin;
    196:   PetscCheck(nsv>0,PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of nsv. Must be > 0");
    197:   svd->nsv = nsv;
    198:   if (ncv == PETSC_DEFAULT || ncv == PETSC_DECIDE) {
    199:     svd->ncv = PETSC_DEFAULT;
    200:   } else {
    201:     PetscCheck(ncv>0,PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of ncv. Must be > 0");
    202:     svd->ncv = ncv;
    203:   }
    204:   if (mpd == PETSC_DECIDE || mpd == PETSC_DEFAULT) {
    205:     svd->mpd = PETSC_DEFAULT;
    206:   } else {
    207:     PetscCheck(mpd>0,PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of mpd. Must be > 0");
    208:     svd->mpd = mpd;
    209:   }
    210:   svd->state = SVD_STATE_INITIAL;
    211:   PetscFunctionReturn(PETSC_SUCCESS);
    212: }

    214: /*@C
    215:    SVDGetDimensions - Gets the number of singular values to compute
    216:    and the dimension of the subspace.

    218:    Not Collective

    220:    Input Parameter:
    221: .  svd - the singular value context

    223:    Output Parameters:
    224: +  nsv - number of singular values to compute
    225: .  ncv - the maximum dimension of the subspace to be used by the solver
    226: -  mpd - the maximum dimension allowed for the projected problem

    228:    Notes:
    229:    The user can specify NULL for any parameter that is not needed.

    231:    Level: intermediate

    233: .seealso: SVDSetDimensions()
    234: @*/
    235: PetscErrorCode SVDGetDimensions(SVD svd,PetscInt *nsv,PetscInt *ncv,PetscInt *mpd)
    236: {
    237:   PetscFunctionBegin;
    239:   if (nsv) *nsv = svd->nsv;
    240:   if (ncv) *ncv = svd->ncv;
    241:   if (mpd) *mpd = svd->mpd;
    242:   PetscFunctionReturn(PETSC_SUCCESS);
    243: }

    245: /*@
    246:     SVDSetWhichSingularTriplets - Specifies which singular triplets are
    247:     to be sought.

    249:     Logically Collective

    251:     Input Parameter:
    252: .   svd - singular value solver context obtained from SVDCreate()

    254:     Output Parameter:
    255: .   which - which singular triplets are to be sought

    257:     Options Database Keys:
    258: +   -svd_largest  - Sets largest singular values
    259: -   -svd_smallest - Sets smallest singular values

    261:     Notes:
    262:     The parameter 'which' can have one of these values

    264: +     SVD_LARGEST  - largest singular values
    265: -     SVD_SMALLEST - smallest singular values

    267:     Level: intermediate

    269: .seealso: SVDGetWhichSingularTriplets(), SVDWhich
    270: @*/
    271: PetscErrorCode SVDSetWhichSingularTriplets(SVD svd,SVDWhich which)
    272: {
    273:   PetscFunctionBegin;
    276:   switch (which) {
    277:     case SVD_LARGEST:
    278:     case SVD_SMALLEST:
    279:       if (svd->which != which) {
    280:         svd->state = SVD_STATE_INITIAL;
    281:         svd->which = which;
    282:       }
    283:       break;
    284:   default:
    285:     SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Invalid 'which' parameter");
    286:   }
    287:   PetscFunctionReturn(PETSC_SUCCESS);
    288: }

    290: /*@
    291:     SVDGetWhichSingularTriplets - Returns which singular triplets are
    292:     to be sought.

    294:     Not Collective

    296:     Input Parameter:
    297: .   svd - singular value solver context obtained from SVDCreate()

    299:     Output Parameter:
    300: .   which - which singular triplets are to be sought

    302:     Notes:
    303:     See SVDSetWhichSingularTriplets() for possible values of which

    305:     Level: intermediate

    307: .seealso: SVDSetWhichSingularTriplets(), SVDWhich
    308: @*/
    309: PetscErrorCode SVDGetWhichSingularTriplets(SVD svd,SVDWhich *which)
    310: {
    311:   PetscFunctionBegin;
    313:   PetscAssertPointer(which,2);
    314:   *which = svd->which;
    315:   PetscFunctionReturn(PETSC_SUCCESS);
    316: }

    318: /*@C
    319:    SVDSetConvergenceTestFunction - Sets a function to compute the error estimate
    320:    used in the convergence test.

    322:    Logically Collective

    324:    Input Parameters:
    325: +  svd     - singular value solver context obtained from SVDCreate()
    326: .  conv    - a pointer to the convergence test function
    327: .  ctx     - context for private data for the convergence routine (may be null)
    328: -  destroy - a routine for destroying the context (may be null)

    330:    Calling sequence of conv:
    331: $  PetscErrorCode conv(SVD svd,PetscReal sigma,PetscReal res,PetscReal *errest,void *ctx)
    332: +   svd    - singular value solver context obtained from SVDCreate()
    333: .   sigma  - computed singular value
    334: .   res    - residual norm associated to the singular triplet
    335: .   errest - (output) computed error estimate
    336: -   ctx    - optional context, as set by SVDSetConvergenceTestFunction()

    338:    Note:
    339:    If the error estimate returned by the convergence test function is less than
    340:    the tolerance, then the singular value is accepted as converged.

    342:    Level: advanced

    344: .seealso: SVDSetConvergenceTest(), SVDSetTolerances()
    345: @*/
    346: PetscErrorCode SVDSetConvergenceTestFunction(SVD svd,PetscErrorCode (*conv)(SVD svd,PetscReal sigma,PetscReal res,PetscReal *errest,void *ctx),void* ctx,PetscErrorCode (*destroy)(void*))
    347: {
    348:   PetscFunctionBegin;
    350:   if (svd->convergeddestroy) PetscCall((*svd->convergeddestroy)(svd->convergedctx));
    351:   svd->convergeduser    = conv;
    352:   svd->convergeddestroy = destroy;
    353:   svd->convergedctx     = ctx;
    354:   if (conv == SVDConvergedAbsolute) svd->conv = SVD_CONV_ABS;
    355:   else if (conv == SVDConvergedRelative) svd->conv = SVD_CONV_REL;
    356:   else if (conv == SVDConvergedNorm) svd->conv = SVD_CONV_NORM;
    357:   else if (conv == SVDConvergedMaxIt) svd->conv = SVD_CONV_MAXIT;
    358:   else {
    359:     svd->conv      = SVD_CONV_USER;
    360:     svd->converged = svd->convergeduser;
    361:   }
    362:   PetscFunctionReturn(PETSC_SUCCESS);
    363: }

    365: /*@
    366:    SVDSetConvergenceTest - Specifies how to compute the error estimate
    367:    used in the convergence test.

    369:    Logically Collective

    371:    Input Parameters:
    372: +  svd  - singular value solver context obtained from SVDCreate()
    373: -  conv - the type of convergence test

    375:    Options Database Keys:
    376: +  -svd_conv_abs   - Sets the absolute convergence test
    377: .  -svd_conv_rel   - Sets the convergence test relative to the singular value
    378: .  -svd_conv_norm  - Sets the convergence test relative to the matrix norm
    379: .  -svd_conv_maxit - Forces the maximum number of iterations as set by -svd_max_it
    380: -  -svd_conv_user  - Selects the user-defined convergence test

    382:    Notes:
    383:    The parameter 'conv' can have one of these values
    384: +     SVD_CONV_ABS   - absolute error ||r||
    385: .     SVD_CONV_REL   - error relative to the singular value sigma, ||r||/sigma
    386: .     SVD_CONV_NORM  - error relative to the matrix norms, ||r||/||Z||, with Z=A or Z=[A;B]
    387: .     SVD_CONV_MAXIT - no convergence until maximum number of iterations has been reached
    388: -     SVD_CONV_USER  - function set by SVDSetConvergenceTestFunction()

    390:    The default in standard SVD is SVD_CONV_REL, while in GSVD the default is SVD_CONV_NORM.

    392:    Level: intermediate

    394: .seealso: SVDGetConvergenceTest(), SVDSetConvergenceTestFunction(), SVDSetStoppingTest(), SVDConv
    395: @*/
    396: PetscErrorCode SVDSetConvergenceTest(SVD svd,SVDConv conv)
    397: {
    398:   PetscFunctionBegin;
    401:   switch (conv) {
    402:     case SVD_CONV_ABS:   svd->converged = SVDConvergedAbsolute; break;
    403:     case SVD_CONV_REL:   svd->converged = SVDConvergedRelative; break;
    404:     case SVD_CONV_NORM:  svd->converged = SVDConvergedNorm; break;
    405:     case SVD_CONV_MAXIT: svd->converged = SVDConvergedMaxIt; break;
    406:     case SVD_CONV_USER:
    407:       PetscCheck(svd->convergeduser,PetscObjectComm((PetscObject)svd),PETSC_ERR_ORDER,"Must call SVDSetConvergenceTestFunction() first");
    408:       svd->converged = svd->convergeduser;
    409:       break;
    410:     default:
    411:       SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Invalid 'conv' value");
    412:   }
    413:   svd->conv = conv;
    414:   PetscFunctionReturn(PETSC_SUCCESS);
    415: }

    417: /*@
    418:    SVDGetConvergenceTest - Gets the method used to compute the error estimate
    419:    used in the convergence test.

    421:    Not Collective

    423:    Input Parameters:
    424: .  svd   - singular value solver context obtained from SVDCreate()

    426:    Output Parameters:
    427: .  conv  - the type of convergence test

    429:    Level: intermediate

    431: .seealso: SVDSetConvergenceTest(), SVDConv
    432: @*/
    433: PetscErrorCode SVDGetConvergenceTest(SVD svd,SVDConv *conv)
    434: {
    435:   PetscFunctionBegin;
    437:   PetscAssertPointer(conv,2);
    438:   *conv = svd->conv;
    439:   PetscFunctionReturn(PETSC_SUCCESS);
    440: }

    442: /*@C
    443:    SVDSetStoppingTestFunction - Sets a function to decide when to stop the outer
    444:    iteration of the singular value solver.

    446:    Logically Collective

    448:    Input Parameters:
    449: +  svd     - singular value solver context obtained from SVDCreate()
    450: .  stop    - pointer to the stopping test function
    451: .  ctx     - context for private data for the stopping routine (may be null)
    452: -  destroy - a routine for destroying the context (may be null)

    454:    Calling sequence of stop:
    455: $  PetscErrorCode stop(SVD svd,PetscInt its,PetscInt max_it,PetscInt nconv,PetscInt nsv,SVDConvergedReason *reason,void *ctx)
    456: +   svd    - singular value solver context obtained from SVDCreate()
    457: .   its    - current number of iterations
    458: .   max_it - maximum number of iterations
    459: .   nconv  - number of currently converged singular triplets
    460: .   nsv    - number of requested singular triplets
    461: .   reason - (output) result of the stopping test
    462: -   ctx    - optional context, as set by SVDSetStoppingTestFunction()

    464:    Note:
    465:    Normal usage is to first call the default routine SVDStoppingBasic() and then
    466:    set reason to SVD_CONVERGED_USER if some user-defined conditions have been
    467:    met. To let the singular value solver continue iterating, the result must be
    468:    left as SVD_CONVERGED_ITERATING.

    470:    Level: advanced

    472: .seealso: SVDSetStoppingTest(), SVDStoppingBasic()
    473: @*/
    474: PetscErrorCode SVDSetStoppingTestFunction(SVD svd,PetscErrorCode (*stop)(SVD svd,PetscInt its,PetscInt max_it,PetscInt nconv,PetscInt nsv,SVDConvergedReason *reason,void *ctx),void* ctx,PetscErrorCode (*destroy)(void*))
    475: {
    476:   PetscFunctionBegin;
    478:   if (svd->stoppingdestroy) PetscCall((*svd->stoppingdestroy)(svd->stoppingctx));
    479:   svd->stoppinguser    = stop;
    480:   svd->stoppingdestroy = destroy;
    481:   svd->stoppingctx     = ctx;
    482:   if (stop == SVDStoppingBasic) svd->stop = SVD_STOP_BASIC;
    483:   else {
    484:     svd->stop     = SVD_STOP_USER;
    485:     svd->stopping = svd->stoppinguser;
    486:   }
    487:   PetscFunctionReturn(PETSC_SUCCESS);
    488: }

    490: /*@
    491:    SVDSetStoppingTest - Specifies how to decide the termination of the outer
    492:    loop of the singular value solver.

    494:    Logically Collective

    496:    Input Parameters:
    497: +  svd  - singular value solver context obtained from SVDCreate()
    498: -  stop - the type of stopping test

    500:    Options Database Keys:
    501: +  -svd_stop_basic - Sets the default stopping test
    502: -  -svd_stop_user  - Selects the user-defined stopping test

    504:    Note:
    505:    The parameter 'stop' can have one of these values
    506: +     SVD_STOP_BASIC - default stopping test
    507: -     SVD_STOP_USER  - function set by SVDSetStoppingTestFunction()

    509:    Level: advanced

    511: .seealso: SVDGetStoppingTest(), SVDSetStoppingTestFunction(), SVDSetConvergenceTest(), SVDStop
    512: @*/
    513: PetscErrorCode SVDSetStoppingTest(SVD svd,SVDStop stop)
    514: {
    515:   PetscFunctionBegin;
    518:   switch (stop) {
    519:     case SVD_STOP_BASIC: svd->stopping = SVDStoppingBasic; break;
    520:     case SVD_STOP_USER:
    521:       PetscCheck(svd->stoppinguser,PetscObjectComm((PetscObject)svd),PETSC_ERR_ORDER,"Must call SVDSetStoppingTestFunction() first");
    522:       svd->stopping = svd->stoppinguser;
    523:       break;
    524:     default:
    525:       SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"Invalid 'stop' value");
    526:   }
    527:   svd->stop = stop;
    528:   PetscFunctionReturn(PETSC_SUCCESS);
    529: }

    531: /*@
    532:    SVDGetStoppingTest - Gets the method used to decide the termination of the outer
    533:    loop of the singular value solver.

    535:    Not Collective

    537:    Input Parameters:
    538: .  svd   - singular value solver context obtained from SVDCreate()

    540:    Output Parameters:
    541: .  stop  - the type of stopping test

    543:    Level: advanced

    545: .seealso: SVDSetStoppingTest(), SVDStop
    546: @*/
    547: PetscErrorCode SVDGetStoppingTest(SVD svd,SVDStop *stop)
    548: {
    549:   PetscFunctionBegin;
    551:   PetscAssertPointer(stop,2);
    552:   *stop = svd->stop;
    553:   PetscFunctionReturn(PETSC_SUCCESS);
    554: }

    556: /*@C
    557:    SVDMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type
    558:    indicated by the user.

    560:    Collective

    562:    Input Parameters:
    563: +  svd      - the singular value solver context
    564: .  opt      - the command line option for this monitor
    565: .  name     - the monitor type one is seeking
    566: .  ctx      - an optional user context for the monitor, or NULL
    567: -  trackall - whether this monitor tracks all singular values or not

    569:    Level: developer

    571: .seealso: SVDMonitorSet(), SVDSetTrackAll()
    572: @*/
    573: PetscErrorCode SVDMonitorSetFromOptions(SVD svd,const char opt[],const char name[],void *ctx,PetscBool trackall)
    574: {
    575:   PetscErrorCode       (*mfunc)(SVD,PetscInt,PetscInt,PetscReal*,PetscReal*,PetscInt,void*);
    576:   PetscErrorCode       (*cfunc)(PetscViewer,PetscViewerFormat,void*,PetscViewerAndFormat**);
    577:   PetscErrorCode       (*dfunc)(PetscViewerAndFormat**);
    578:   PetscViewerAndFormat *vf;
    579:   PetscViewer          viewer;
    580:   PetscViewerFormat    format;
    581:   PetscViewerType      vtype;
    582:   char                 key[PETSC_MAX_PATH_LEN];
    583:   PetscBool            flg;

    585:   PetscFunctionBegin;
    586:   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)svd),((PetscObject)svd)->options,((PetscObject)svd)->prefix,opt,&viewer,&format,&flg));
    587:   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);

    589:   PetscCall(PetscViewerGetType(viewer,&vtype));
    590:   PetscCall(SlepcMonitorMakeKey_Internal(name,vtype,format,key));
    591:   PetscCall(PetscFunctionListFind(SVDMonitorList,key,&mfunc));
    592:   PetscCheck(mfunc,PetscObjectComm((PetscObject)svd),PETSC_ERR_SUP,"Specified viewer and format not supported");
    593:   PetscCall(PetscFunctionListFind(SVDMonitorCreateList,key,&cfunc));
    594:   PetscCall(PetscFunctionListFind(SVDMonitorDestroyList,key,&dfunc));
    595:   if (!cfunc) cfunc = PetscViewerAndFormatCreate_Internal;
    596:   if (!dfunc) dfunc = PetscViewerAndFormatDestroy;

    598:   PetscCall((*cfunc)(viewer,format,ctx,&vf));
    599:   PetscCall(PetscOptionsRestoreViewer(&viewer));
    600:   PetscCall(SVDMonitorSet(svd,mfunc,vf,(PetscErrorCode(*)(void **))dfunc));
    601:   if (trackall) PetscCall(SVDSetTrackAll(svd,PETSC_TRUE));
    602:   PetscFunctionReturn(PETSC_SUCCESS);
    603: }

    605: /*@
    606:    SVDSetFromOptions - Sets SVD options from the options database.
    607:    This routine must be called before SVDSetUp() if the user is to be
    608:    allowed to set the solver type.

    610:    Collective

    612:    Input Parameters:
    613: .  svd - the singular value solver context

    615:    Notes:
    616:    To see all options, run your program with the -help option.

    618:    Level: beginner

    620: .seealso: SVDSetOptionsPrefix()
    621: @*/
    622: PetscErrorCode SVDSetFromOptions(SVD svd)
    623: {
    624:   char           type[256];
    625:   PetscBool      set,flg,val,flg1,flg2,flg3;
    626:   PetscInt       i,j,k;
    627:   PetscReal      r;

    629:   PetscFunctionBegin;
    631:   PetscCall(SVDRegisterAll());
    632:   PetscObjectOptionsBegin((PetscObject)svd);
    633:     PetscCall(PetscOptionsFList("-svd_type","SVD solver method","SVDSetType",SVDList,(char*)(((PetscObject)svd)->type_name?((PetscObject)svd)->type_name:SVDCROSS),type,sizeof(type),&flg));
    634:     if (flg) PetscCall(SVDSetType(svd,type));
    635:     else if (!((PetscObject)svd)->type_name) PetscCall(SVDSetType(svd,SVDCROSS));

    637:     PetscCall(PetscOptionsBoolGroupBegin("-svd_standard","Singular value decomposition (SVD)","SVDSetProblemType",&flg));
    638:     if (flg) PetscCall(SVDSetProblemType(svd,SVD_STANDARD));
    639:     PetscCall(PetscOptionsBoolGroup("-svd_generalized","Generalized singular value decomposition (GSVD)","SVDSetProblemType",&flg));
    640:     if (flg) PetscCall(SVDSetProblemType(svd,SVD_GENERALIZED));
    641:     PetscCall(PetscOptionsBoolGroupEnd("-svd_hyperbolic","Hyperbolic singular value decomposition (HSVD)","SVDSetProblemType",&flg));
    642:     if (flg) PetscCall(SVDSetProblemType(svd,SVD_HYPERBOLIC));

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

    647:     i = svd->max_it;
    648:     PetscCall(PetscOptionsInt("-svd_max_it","Maximum number of iterations","SVDSetTolerances",svd->max_it,&i,&flg1));
    649:     r = svd->tol;
    650:     PetscCall(PetscOptionsReal("-svd_tol","Tolerance","SVDSetTolerances",SlepcDefaultTol(svd->tol),&r,&flg2));
    651:     if (flg1 || flg2) PetscCall(SVDSetTolerances(svd,r,i));

    653:     PetscCall(PetscOptionsBoolGroupBegin("-svd_conv_abs","Absolute error convergence test","SVDSetConvergenceTest",&flg));
    654:     if (flg) PetscCall(SVDSetConvergenceTest(svd,SVD_CONV_ABS));
    655:     PetscCall(PetscOptionsBoolGroup("-svd_conv_rel","Relative error convergence test","SVDSetConvergenceTest",&flg));
    656:     if (flg) PetscCall(SVDSetConvergenceTest(svd,SVD_CONV_REL));
    657:     PetscCall(PetscOptionsBoolGroup("-svd_conv_norm","Convergence test relative to the matrix norms","SVDSetConvergenceTest",&flg));
    658:     if (flg) PetscCall(SVDSetConvergenceTest(svd,SVD_CONV_NORM));
    659:     PetscCall(PetscOptionsBoolGroup("-svd_conv_maxit","Maximum iterations convergence test","SVDSetConvergenceTest",&flg));
    660:     if (flg) PetscCall(SVDSetConvergenceTest(svd,SVD_CONV_MAXIT));
    661:     PetscCall(PetscOptionsBoolGroupEnd("-svd_conv_user","User-defined convergence test","SVDSetConvergenceTest",&flg));
    662:     if (flg) PetscCall(SVDSetConvergenceTest(svd,SVD_CONV_USER));

    664:     PetscCall(PetscOptionsBoolGroupBegin("-svd_stop_basic","Stop iteration if all singular values converged or max_it reached","SVDSetStoppingTest",&flg));
    665:     if (flg) PetscCall(SVDSetStoppingTest(svd,SVD_STOP_BASIC));
    666:     PetscCall(PetscOptionsBoolGroupEnd("-svd_stop_user","User-defined stopping test","SVDSetStoppingTest",&flg));
    667:     if (flg) PetscCall(SVDSetStoppingTest(svd,SVD_STOP_USER));

    669:     i = svd->nsv;
    670:     PetscCall(PetscOptionsInt("-svd_nsv","Number of singular values to compute","SVDSetDimensions",svd->nsv,&i,&flg1));
    671:     j = svd->ncv;
    672:     PetscCall(PetscOptionsInt("-svd_ncv","Number of basis vectors","SVDSetDimensions",svd->ncv,&j,&flg2));
    673:     k = svd->mpd;
    674:     PetscCall(PetscOptionsInt("-svd_mpd","Maximum dimension of projected problem","SVDSetDimensions",svd->mpd,&k,&flg3));
    675:     if (flg1 || flg2 || flg3) PetscCall(SVDSetDimensions(svd,i,j,k));

    677:     PetscCall(PetscOptionsBoolGroupBegin("-svd_largest","Compute largest singular values","SVDSetWhichSingularTriplets",&flg));
    678:     if (flg) PetscCall(SVDSetWhichSingularTriplets(svd,SVD_LARGEST));
    679:     PetscCall(PetscOptionsBoolGroupEnd("-svd_smallest","Compute smallest singular values","SVDSetWhichSingularTriplets",&flg));
    680:     if (flg) PetscCall(SVDSetWhichSingularTriplets(svd,SVD_SMALLEST));

    682:     /* -----------------------------------------------------------------------*/
    683:     /*
    684:       Cancels all monitors hardwired into code before call to SVDSetFromOptions()
    685:     */
    686:     PetscCall(PetscOptionsBool("-svd_monitor_cancel","Remove any hardwired monitor routines","SVDMonitorCancel",PETSC_FALSE,&flg,&set));
    687:     if (set && flg) PetscCall(SVDMonitorCancel(svd));
    688:     PetscCall(SVDMonitorSetFromOptions(svd,"-svd_monitor","first_approximation",NULL,PETSC_FALSE));
    689:     PetscCall(SVDMonitorSetFromOptions(svd,"-svd_monitor_all","all_approximations",NULL,PETSC_TRUE));
    690:     PetscCall(SVDMonitorSetFromOptions(svd,"-svd_monitor_conv","convergence_history",NULL,PETSC_FALSE));
    691:     PetscCall(SVDMonitorSetFromOptions(svd,"-svd_monitor_conditioning","conditioning",NULL,PETSC_FALSE));

    693:     /* -----------------------------------------------------------------------*/
    694:     PetscCall(PetscOptionsName("-svd_view","Print detailed information on solver used","SVDView",&set));
    695:     PetscCall(PetscOptionsName("-svd_view_vectors","View computed singular vectors","SVDVectorsView",&set));
    696:     PetscCall(PetscOptionsName("-svd_view_values","View computed singular values","SVDValuesView",&set));
    697:     PetscCall(PetscOptionsName("-svd_converged_reason","Print reason for convergence, and number of iterations","SVDConvergedReasonView",&set));
    698:     PetscCall(PetscOptionsName("-svd_error_absolute","Print absolute errors of each singular triplet","SVDErrorView",&set));
    699:     PetscCall(PetscOptionsName("-svd_error_relative","Print relative errors of each singular triplet","SVDErrorView",&set));
    700:     PetscCall(PetscOptionsName("-svd_error_norm","Print errors relative to the matrix norms of each singular triplet","SVDErrorView",&set));

    702:     PetscTryTypeMethod(svd,setfromoptions,PetscOptionsObject);
    703:     PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)svd,PetscOptionsObject));
    704:   PetscOptionsEnd();

    706:   if (!svd->V) PetscCall(SVDGetBV(svd,&svd->V,NULL));
    707:   PetscCall(BVSetFromOptions(svd->V));
    708:   if (!svd->U) PetscCall(SVDGetBV(svd,NULL,&svd->U));
    709:   PetscCall(BVSetFromOptions(svd->U));
    710:   if (!svd->ds) PetscCall(SVDGetDS(svd,&svd->ds));
    711:   PetscCall(SVDSetDSType(svd));
    712:   PetscCall(DSSetFromOptions(svd->ds));
    713:   PetscFunctionReturn(PETSC_SUCCESS);
    714: }

    716: /*@
    717:    SVDSetProblemType - Specifies the type of the singular value problem.

    719:    Logically Collective

    721:    Input Parameters:
    722: +  svd  - the singular value solver context
    723: -  type - a known type of singular value problem

    725:    Options Database Keys:
    726: +  -svd_standard    - standard singular value decomposition (SVD)
    727: .  -svd_generalized - generalized singular value problem (GSVD)
    728: -  -svd_hyperbolic  - hyperbolic singular value problem (HSVD)

    730:    Notes:
    731:    The GSVD requires that two matrices have been passed via SVDSetOperators().
    732:    The HSVD requires that a signature matrix has been passed via SVDSetSignature().

    734:    Level: intermediate

    736: .seealso: SVDSetOperators(), SVDSetSignature(), SVDSetType(), SVDGetProblemType(), SVDProblemType
    737: @*/
    738: PetscErrorCode SVDSetProblemType(SVD svd,SVDProblemType type)
    739: {
    740:   PetscFunctionBegin;
    743:   if (type == svd->problem_type) PetscFunctionReturn(PETSC_SUCCESS);
    744:   switch (type) {
    745:     case SVD_STANDARD:
    746:       svd->isgeneralized = PETSC_FALSE;
    747:       svd->ishyperbolic  = PETSC_FALSE;
    748:       break;
    749:     case SVD_GENERALIZED:
    750:       svd->isgeneralized = PETSC_TRUE;
    751:       svd->ishyperbolic  = PETSC_FALSE;
    752:       break;
    753:     case SVD_HYPERBOLIC:
    754:       svd->isgeneralized = PETSC_FALSE;
    755:       svd->ishyperbolic  = PETSC_TRUE;
    756:       break;
    757:     default:
    758:       SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_WRONG,"Unknown singular value problem type");
    759:   }
    760:   svd->problem_type = type;
    761:   svd->state = SVD_STATE_INITIAL;
    762:   PetscFunctionReturn(PETSC_SUCCESS);
    763: }

    765: /*@
    766:    SVDGetProblemType - Gets the problem type from the SVD object.

    768:    Not Collective

    770:    Input Parameter:
    771: .  svd - the singular value solver context

    773:    Output Parameter:
    774: .  type - the problem type

    776:    Level: intermediate

    778: .seealso: SVDSetProblemType(), SVDProblemType
    779: @*/
    780: PetscErrorCode SVDGetProblemType(SVD svd,SVDProblemType *type)
    781: {
    782:   PetscFunctionBegin;
    784:   PetscAssertPointer(type,2);
    785:   *type = svd->problem_type;
    786:   PetscFunctionReturn(PETSC_SUCCESS);
    787: }

    789: /*@
    790:    SVDIsGeneralized - Ask if the SVD object corresponds to a generalized
    791:    singular value problem.

    793:    Not Collective

    795:    Input Parameter:
    796: .  svd - the singular value solver context

    798:    Output Parameter:
    799: .  is - the answer

    801:    Level: intermediate

    803: .seealso: SVDIsHyperbolic()
    804: @*/
    805: PetscErrorCode SVDIsGeneralized(SVD svd,PetscBool* is)
    806: {
    807:   PetscFunctionBegin;
    809:   PetscAssertPointer(is,2);
    810:   *is = svd->isgeneralized;
    811:   PetscFunctionReturn(PETSC_SUCCESS);
    812: }

    814: /*@
    815:    SVDIsHyperbolic - Ask if the SVD object corresponds to a hyperbolic
    816:    singular value problem.

    818:    Not Collective

    820:    Input Parameter:
    821: .  svd - the singular value solver context

    823:    Output Parameter:
    824: .  is - the answer

    826:    Level: intermediate

    828: .seealso: SVDIsGeneralized()
    829: @*/
    830: PetscErrorCode SVDIsHyperbolic(SVD svd,PetscBool* is)
    831: {
    832:   PetscFunctionBegin;
    834:   PetscAssertPointer(is,2);
    835:   *is = svd->ishyperbolic;
    836:   PetscFunctionReturn(PETSC_SUCCESS);
    837: }

    839: /*@
    840:    SVDSetTrackAll - Specifies if the solver must compute the residual norm of all
    841:    approximate singular value or not.

    843:    Logically Collective

    845:    Input Parameters:
    846: +  svd      - the singular value solver context
    847: -  trackall - whether to compute all residuals or not

    849:    Notes:
    850:    If the user sets trackall=PETSC_TRUE then the solver computes (or estimates)
    851:    the residual norm for each singular value approximation. Computing the residual is
    852:    usually an expensive operation and solvers commonly compute only the residual
    853:    associated to the first unconverged singular value.

    855:    The option '-svd_monitor_all' automatically activates this option.

    857:    Level: developer

    859: .seealso: SVDGetTrackAll()
    860: @*/
    861: PetscErrorCode SVDSetTrackAll(SVD svd,PetscBool trackall)
    862: {
    863:   PetscFunctionBegin;
    866:   svd->trackall = trackall;
    867:   PetscFunctionReturn(PETSC_SUCCESS);
    868: }

    870: /*@
    871:    SVDGetTrackAll - Returns the flag indicating whether all residual norms must
    872:    be computed or not.

    874:    Not Collective

    876:    Input Parameter:
    877: .  svd - the singular value solver context

    879:    Output Parameter:
    880: .  trackall - the returned flag

    882:    Level: developer

    884: .seealso: SVDSetTrackAll()
    885: @*/
    886: PetscErrorCode SVDGetTrackAll(SVD svd,PetscBool *trackall)
    887: {
    888:   PetscFunctionBegin;
    890:   PetscAssertPointer(trackall,2);
    891:   *trackall = svd->trackall;
    892:   PetscFunctionReturn(PETSC_SUCCESS);
    893: }

    895: /*@C
    896:    SVDSetOptionsPrefix - Sets the prefix used for searching for all
    897:    SVD options in the database.

    899:    Logically Collective

    901:    Input Parameters:
    902: +  svd - the singular value solver context
    903: -  prefix - the prefix string to prepend to all SVD option requests

    905:    Notes:
    906:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    907:    The first character of all runtime options is AUTOMATICALLY the
    908:    hyphen.

    910:    For example, to distinguish between the runtime options for two
    911:    different SVD contexts, one could call
    912: .vb
    913:       SVDSetOptionsPrefix(svd1,"svd1_")
    914:       SVDSetOptionsPrefix(svd2,"svd2_")
    915: .ve

    917:    Level: advanced

    919: .seealso: SVDAppendOptionsPrefix(), SVDGetOptionsPrefix()
    920: @*/
    921: PetscErrorCode SVDSetOptionsPrefix(SVD svd,const char *prefix)
    922: {
    923:   PetscFunctionBegin;
    925:   if (!svd->V) PetscCall(SVDGetBV(svd,&svd->V,&svd->U));
    926:   PetscCall(BVSetOptionsPrefix(svd->V,prefix));
    927:   PetscCall(BVSetOptionsPrefix(svd->U,prefix));
    928:   if (!svd->ds) PetscCall(SVDGetDS(svd,&svd->ds));
    929:   PetscCall(DSSetOptionsPrefix(svd->ds,prefix));
    930:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)svd,prefix));
    931:   PetscFunctionReturn(PETSC_SUCCESS);
    932: }

    934: /*@C
    935:    SVDAppendOptionsPrefix - Appends to the prefix used for searching for all
    936:    SVD options in the database.

    938:    Logically Collective

    940:    Input Parameters:
    941: +  svd - the singular value solver context
    942: -  prefix - the prefix string to prepend to all SVD option requests

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

    948:    Level: advanced

    950: .seealso: SVDSetOptionsPrefix(), SVDGetOptionsPrefix()
    951: @*/
    952: PetscErrorCode SVDAppendOptionsPrefix(SVD svd,const char *prefix)
    953: {
    954:   PetscFunctionBegin;
    956:   if (!svd->V) PetscCall(SVDGetBV(svd,&svd->V,&svd->U));
    957:   PetscCall(BVAppendOptionsPrefix(svd->V,prefix));
    958:   PetscCall(BVAppendOptionsPrefix(svd->U,prefix));
    959:   if (!svd->ds) PetscCall(SVDGetDS(svd,&svd->ds));
    960:   PetscCall(DSAppendOptionsPrefix(svd->ds,prefix));
    961:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)svd,prefix));
    962:   PetscFunctionReturn(PETSC_SUCCESS);
    963: }

    965: /*@C
    966:    SVDGetOptionsPrefix - Gets the prefix used for searching for all
    967:    SVD options in the database.

    969:    Not Collective

    971:    Input Parameters:
    972: .  svd - the singular value solver context

    974:    Output Parameters:
    975: .  prefix - pointer to the prefix string used is returned

    977:    Note:
    978:    On the Fortran side, the user should pass in a string 'prefix' of
    979:    sufficient length to hold the prefix.

    981:    Level: advanced

    983: .seealso: SVDSetOptionsPrefix(), SVDAppendOptionsPrefix()
    984: @*/
    985: PetscErrorCode SVDGetOptionsPrefix(SVD svd,const char *prefix[])
    986: {
    987:   PetscFunctionBegin;
    989:   PetscAssertPointer(prefix,2);
    990:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)svd,prefix));
    991:   PetscFunctionReturn(PETSC_SUCCESS);
    992: }