Actual source code: lmeopts.c

slepc-3.21.0 2024-03-30
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:    LME routines related to options that can be set via the command-line
 12:    or procedurally
 13: */

 15: #include <slepc/private/lmeimpl.h>
 16: #include <petscdraw.h>

 18: /*@C
 19:    LMEMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type
 20:    indicated by the user.

 22:    Collective

 24:    Input Parameters:
 25: +  lme      - the linear matrix equation context
 26: .  opt  - the command line option for this monitor
 27: .  name - the monitor type one is seeking
 28: -  ctx  - an optional user context for the monitor, or NULL

 30:    Level: developer

 32: .seealso: LMEMonitorSet()
 33: @*/
 34: PetscErrorCode LMEMonitorSetFromOptions(LME lme,const char opt[],const char name[],void *ctx)
 35: {
 36:   PetscErrorCode       (*mfunc)(LME,PetscInt,PetscReal,void*);
 37:   PetscErrorCode       (*cfunc)(PetscViewer,PetscViewerFormat,void*,PetscViewerAndFormat**);
 38:   PetscErrorCode       (*dfunc)(PetscViewerAndFormat**);
 39:   PetscViewerAndFormat *vf;
 40:   PetscViewer          viewer;
 41:   PetscViewerFormat    format;
 42:   PetscViewerType      vtype;
 43:   char                 key[PETSC_MAX_PATH_LEN];
 44:   PetscBool            flg;

 46:   PetscFunctionBegin;
 47:   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)lme),((PetscObject)lme)->options,((PetscObject)lme)->prefix,opt,&viewer,&format,&flg));
 48:   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);

 50:   PetscCall(PetscViewerGetType(viewer,&vtype));
 51:   PetscCall(SlepcMonitorMakeKey_Internal(name,vtype,format,key));
 52:   PetscCall(PetscFunctionListFind(LMEMonitorList,key,&mfunc));
 53:   PetscCheck(mfunc,PetscObjectComm((PetscObject)lme),PETSC_ERR_SUP,"Specified viewer and format not supported");
 54:   PetscCall(PetscFunctionListFind(LMEMonitorCreateList,key,&cfunc));
 55:   PetscCall(PetscFunctionListFind(LMEMonitorDestroyList,key,&dfunc));
 56:   if (!cfunc) cfunc = PetscViewerAndFormatCreate_Internal;
 57:   if (!dfunc) dfunc = PetscViewerAndFormatDestroy;

 59:   PetscCall((*cfunc)(viewer,format,ctx,&vf));
 60:   PetscCall(PetscOptionsRestoreViewer(&viewer));
 61:   PetscCall(LMEMonitorSet(lme,mfunc,vf,(PetscErrorCode(*)(void **))dfunc));
 62:   PetscFunctionReturn(PETSC_SUCCESS);
 63: }

 65: /*@
 66:    LMESetFromOptions - Sets LME options from the options database.
 67:    This routine must be called before LMESetUp() if the user is to be
 68:    allowed to set the solver type.

 70:    Collective

 72:    Input Parameters:
 73: .  lme - the linear matrix equation solver context

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

 78:    Level: beginner

 80: .seealso: LMESetOptionsPrefix()
 81: @*/
 82: PetscErrorCode LMESetFromOptions(LME lme)
 83: {
 84:   char           type[256];
 85:   PetscBool      set,flg,flg1,flg2;
 86:   PetscReal      r;
 87:   PetscInt       i;

 89:   PetscFunctionBegin;
 91:   PetscCall(LMERegisterAll());
 92:   PetscObjectOptionsBegin((PetscObject)lme);
 93:     PetscCall(PetscOptionsFList("-lme_type","Linear matrix equation","LMESetType",LMEList,(char*)(((PetscObject)lme)->type_name?((PetscObject)lme)->type_name:LMEKRYLOV),type,sizeof(type),&flg));
 94:     if (flg) PetscCall(LMESetType(lme,type));
 95:     else if (!((PetscObject)lme)->type_name) PetscCall(LMESetType(lme,LMEKRYLOV));

 97:     PetscCall(PetscOptionsBoolGroupBegin("-lme_lyapunov","Continuous-time Lyapunov equation","LMESetProblemType",&flg));
 98:     if (flg) PetscCall(LMESetProblemType(lme,LME_LYAPUNOV));
 99:     PetscCall(PetscOptionsBoolGroup("-lme_sylvester","Continuous-time Sylvester equation","LMESetProblemType",&flg));
100:     if (flg) PetscCall(LMESetProblemType(lme,LME_SYLVESTER));
101:     PetscCall(PetscOptionsBoolGroup("-lme_gen_lyapunov","Generalized Lyapunov equation","LMESetProblemType",&flg));
102:     if (flg) PetscCall(LMESetProblemType(lme,LME_GEN_LYAPUNOV));
103:     PetscCall(PetscOptionsBoolGroup("-lme_gen_sylvester","Generalized Sylvester equation","LMESetProblemType",&flg));
104:     if (flg) PetscCall(LMESetProblemType(lme,LME_GEN_SYLVESTER));
105:     PetscCall(PetscOptionsBoolGroup("-lme_dt_lyapunov","Discrete-time Lyapunov equation","LMESetProblemType",&flg));
106:     if (flg) PetscCall(LMESetProblemType(lme,LME_DT_LYAPUNOV));
107:     PetscCall(PetscOptionsBoolGroupEnd("-lme_stein","Stein equation","LMESetProblemType",&flg));
108:     if (flg) PetscCall(LMESetProblemType(lme,LME_STEIN));

110:     i = lme->max_it;
111:     PetscCall(PetscOptionsInt("-lme_max_it","Maximum number of iterations","LMESetTolerances",lme->max_it,&i,&flg1));
112:     if (!flg1) i = PETSC_DEFAULT;
113:     r = lme->tol;
114:     PetscCall(PetscOptionsReal("-lme_tol","Tolerance","LMESetTolerances",SlepcDefaultTol(lme->tol),&r,&flg2));
115:     if (flg1 || flg2) PetscCall(LMESetTolerances(lme,r,i));

117:     PetscCall(PetscOptionsInt("-lme_ncv","Number of basis vectors","LMESetDimensions",lme->ncv,&i,&flg));
118:     if (flg) PetscCall(LMESetDimensions(lme,i));

120:     PetscCall(PetscOptionsBool("-lme_error_if_not_converged","Generate error if solver does not converge","LMESetErrorIfNotConverged",lme->errorifnotconverged,&lme->errorifnotconverged,NULL));

122:     /* -----------------------------------------------------------------------*/
123:     /*
124:       Cancels all monitors hardwired into code before call to LMESetFromOptions()
125:     */
126:     PetscCall(PetscOptionsBool("-lme_monitor_cancel","Remove any hardwired monitor routines","LMEMonitorCancel",PETSC_FALSE,&flg,&set));
127:     if (set && flg) PetscCall(LMEMonitorCancel(lme));
128:     PetscCall(LMEMonitorSetFromOptions(lme,"-lme_monitor","error_estimate",NULL));

130:     /* -----------------------------------------------------------------------*/
131:     PetscCall(PetscOptionsName("-lme_view","Print detailed information on solver used","LMEView",&set));

133:     PetscTryTypeMethod(lme,setfromoptions,PetscOptionsObject);
134:     PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)lme,PetscOptionsObject));
135:   PetscOptionsEnd();

137:   if (!lme->V) PetscCall(LMEGetBV(lme,&lme->V));
138:   PetscCall(BVSetFromOptions(lme->V));
139:   PetscFunctionReturn(PETSC_SUCCESS);
140: }

142: /*@
143:    LMESetProblemType - Specifies the type of matrix equation to be solved.

145:    Logically Collective

147:    Input Parameters:
148: +  lme  - the linear matrix equation solver context
149: -  type - a known type of matrix equation

151:    Options Database Keys:
152: +  -lme_lyapunov - continuous-time Lyapunov equation A*X+X*A'=-C
153: .  -lme_sylvester - continuous-time Sylvester equation A*X+X*B=C
154: .  -lme_gen_lyapunov - generalized Lyapunov equation A*X*D'+D*X*A'=-C
155: .  -lme_gen_sylvester - generalized Sylvester equation A*X*E+D*X*B=C
156: .  -lme_dt_lyapunov - discrete-time Lyapunov equation A*X*A'-X=-C
157: -  -lme_stein - Stein equation A*X*E+X=C

159:    Notes:
160:    The coefficient matrices A, B, D, E must be provided via LMESetCoefficients(),
161:    but some of them are optional depending on the matrix equation.

163: .vb
164:                             equation              A    B    D    E
165:                           -----------------      ---  ---  ---  ---
166:        LME_LYAPUNOV        A*X+X*A'=-C           yes (A-t)  -    -
167:        LME_SYLVESTER       A*X+X*B=C             yes  yes   -    -
168:        LME_GEN_LYAPUNOV    A*X*D'+D*X*A'=-C      yes (A-t) yes (D-t)
169:        LME_GEN_SYLVESTER   A*X*E+D*X*B=C         yes  yes  yes  yes
170:        LME_DT_LYAPUNOV     A*X*A'-X=-C           yes   -    -  (A-t)
171:        LME_STEIN           A*X*E+X=C             yes   -    -   yes
172: .ve

174:    In the above table, the notation (A-t) means that this matrix need
175:    not be passed, but the user may choose to pass an explicit transpose
176:    of matrix A (for improved efficiency).

178:    Also note that some of the equation types impose restrictions on the
179:    properties of the coefficient matrices and possibly on the right-hand
180:    side C.

182:    Level: beginner

184: .seealso: LMESetCoefficients(), LMESetType(), LMEGetProblemType(), LMEProblemType
185: @*/
186: PetscErrorCode LMESetProblemType(LME lme,LMEProblemType type)
187: {
188:   PetscFunctionBegin;
191:   if (type == lme->problem_type) PetscFunctionReturn(PETSC_SUCCESS);
192:   switch (type) {
193:     case LME_LYAPUNOV:
194:     case LME_SYLVESTER:
195:     case LME_GEN_LYAPUNOV:
196:     case LME_GEN_SYLVESTER:
197:     case LME_DT_LYAPUNOV:
198:     case LME_STEIN:
199:       break;
200:     default:
201:       SETERRQ(PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_WRONG,"Unknown matrix equation type");
202:   }
203:   lme->problem_type = type;
204:   lme->setupcalled  = PETSC_FALSE;
205:   PetscFunctionReturn(PETSC_SUCCESS);
206: }

208: /*@
209:    LMEGetProblemType - Gets the matrix equation type from the LME object.

211:    Not Collective

213:    Input Parameter:
214: .  lme - the linear matrix equation solver context

216:    Output Parameter:
217: .  type - name of LME problem type

219:    Level: intermediate

221: .seealso: LMESetProblemType(), LMEProblemType
222: @*/
223: PetscErrorCode LMEGetProblemType(LME lme,LMEProblemType *type)
224: {
225:   PetscFunctionBegin;
227:   PetscAssertPointer(type,2);
228:   *type = lme->problem_type;
229:   PetscFunctionReturn(PETSC_SUCCESS);
230: }

232: /*@C
233:    LMEGetTolerances - Gets the tolerance and maximum iteration count used
234:    by the LME convergence tests.

236:    Not Collective

238:    Input Parameter:
239: .  lme - the linear matrix equation solver context

241:    Output Parameters:
242: +  tol - the convergence tolerance
243: -  maxits - maximum number of iterations

245:    Notes:
246:    The user can specify NULL for any parameter that is not needed.

248:    Level: intermediate

250: .seealso: LMESetTolerances()
251: @*/
252: PetscErrorCode LMEGetTolerances(LME lme,PetscReal *tol,PetscInt *maxits)
253: {
254:   PetscFunctionBegin;
256:   if (tol)    *tol    = lme->tol;
257:   if (maxits) *maxits = lme->max_it;
258:   PetscFunctionReturn(PETSC_SUCCESS);
259: }

261: /*@
262:    LMESetTolerances - Sets the tolerance and maximum iteration count used
263:    by the LME convergence tests.

265:    Logically Collective

267:    Input Parameters:
268: +  lme - the linear matrix equation solver context
269: .  tol - the convergence tolerance
270: -  maxits - maximum number of iterations to use

272:    Options Database Keys:
273: +  -lme_tol <tol> - Sets the convergence tolerance
274: -  -lme_max_it <maxits> - Sets the maximum number of iterations allowed

276:    Notes:
277:    Use PETSC_DEFAULT for either argument to assign a reasonably good value.

279:    Level: intermediate

281: .seealso: LMEGetTolerances()
282: @*/
283: PetscErrorCode LMESetTolerances(LME lme,PetscReal tol,PetscInt maxits)
284: {
285:   PetscFunctionBegin;
289:   if (tol == (PetscReal)PETSC_DEFAULT) {
290:     lme->tol = PETSC_DEFAULT;
291:     lme->setupcalled = 0;
292:   } else {
293:     PetscCheck(tol>0.0,PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of tol. Must be > 0");
294:     lme->tol = tol;
295:   }
296:   if (maxits == PETSC_DEFAULT || maxits == PETSC_DECIDE) {
297:     lme->max_it = PETSC_DEFAULT;
298:     lme->setupcalled = 0;
299:   } else {
300:     PetscCheck(maxits>0,PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of maxits. Must be > 0");
301:     lme->max_it = maxits;
302:   }
303:   PetscFunctionReturn(PETSC_SUCCESS);
304: }

306: /*@
307:    LMEGetDimensions - Gets the dimension of the subspace used by the solver.

309:    Not Collective

311:    Input Parameter:
312: .  lme - the linear matrix equation solver context

314:    Output Parameter:
315: .  ncv - the maximum dimension of the subspace to be used by the solver

317:    Level: intermediate

319: .seealso: LMESetDimensions()
320: @*/
321: PetscErrorCode LMEGetDimensions(LME lme,PetscInt *ncv)
322: {
323:   PetscFunctionBegin;
325:   PetscAssertPointer(ncv,2);
326:   *ncv = lme->ncv;
327:   PetscFunctionReturn(PETSC_SUCCESS);
328: }

330: /*@
331:    LMESetDimensions - Sets the dimension of the subspace to be used by the solver.

333:    Logically Collective

335:    Input Parameters:
336: +  lme - the linear matrix equation solver context
337: -  ncv - the maximum dimension of the subspace to be used by the solver

339:    Options Database Keys:
340: .  -lme_ncv <ncv> - Sets the dimension of the subspace

342:    Notes:
343:    Use PETSC_DEFAULT for ncv to assign a reasonably good value, which is
344:    dependent on the solution method.

346:    Level: intermediate

348: .seealso: LMEGetDimensions()
349: @*/
350: PetscErrorCode LMESetDimensions(LME lme,PetscInt ncv)
351: {
352:   PetscFunctionBegin;
355:   if (ncv == PETSC_DECIDE || ncv == PETSC_DEFAULT) {
356:     lme->ncv = PETSC_DEFAULT;
357:   } else {
358:     PetscCheck(ncv>0,PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of ncv. Must be > 0");
359:     lme->ncv = ncv;
360:   }
361:   lme->setupcalled = 0;
362:   PetscFunctionReturn(PETSC_SUCCESS);
363: }

365: /*@
366:    LMESetErrorIfNotConverged - Causes LMESolve() to generate an error if the
367:    solver has not converged.

369:    Logically Collective

371:    Input Parameters:
372: +  lme - the linear matrix equation solver context
373: -  flg - PETSC_TRUE indicates you want the error generated

375:    Options Database Keys:
376: .  -lme_error_if_not_converged - this takes an optional truth value (0/1/no/yes/true/false)

378:    Level: intermediate

380:    Note:
381:    Normally SLEPc continues if the solver fails to converge, you can call
382:    LMEGetConvergedReason() after a LMESolve() to determine if it has converged.

384: .seealso: LMEGetErrorIfNotConverged()
385: @*/
386: PetscErrorCode LMESetErrorIfNotConverged(LME lme,PetscBool flg)
387: {
388:   PetscFunctionBegin;
391:   lme->errorifnotconverged = flg;
392:   PetscFunctionReturn(PETSC_SUCCESS);
393: }

395: /*@
396:    LMEGetErrorIfNotConverged - Return a flag indicating whether LMESolve() will
397:    generate an error if the solver does not converge.

399:    Not Collective

401:    Input Parameter:
402: .  lme - the linear matrix equation solver context

404:    Output Parameter:
405: .  flag - PETSC_TRUE if it will generate an error, else PETSC_FALSE

407:    Level: intermediate

409: .seealso: LMESetErrorIfNotConverged()
410: @*/
411: PetscErrorCode LMEGetErrorIfNotConverged(LME lme,PetscBool *flag)
412: {
413:   PetscFunctionBegin;
415:   PetscAssertPointer(flag,2);
416:   *flag = lme->errorifnotconverged;
417:   PetscFunctionReturn(PETSC_SUCCESS);
418: }

420: /*@C
421:    LMESetOptionsPrefix - Sets the prefix used for searching for all
422:    LME options in the database.

424:    Logically Collective

426:    Input Parameters:
427: +  lme - the linear matrix equation solver context
428: -  prefix - the prefix string to prepend to all LME option requests

430:    Notes:
431:    A hyphen (-) must NOT be given at the beginning of the prefix name.
432:    The first character of all runtime options is AUTOMATICALLY the
433:    hyphen.

435:    For example, to distinguish between the runtime options for two
436:    different LME contexts, one could call
437: .vb
438:       LMESetOptionsPrefix(lme1,"fun1_")
439:       LMESetOptionsPrefix(lme2,"fun2_")
440: .ve

442:    Level: advanced

444: .seealso: LMEAppendOptionsPrefix(), LMEGetOptionsPrefix()
445: @*/
446: PetscErrorCode LMESetOptionsPrefix(LME lme,const char *prefix)
447: {
448:   PetscFunctionBegin;
450:   if (!lme->V) PetscCall(LMEGetBV(lme,&lme->V));
451:   PetscCall(BVSetOptionsPrefix(lme->V,prefix));
452:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lme,prefix));
453:   PetscFunctionReturn(PETSC_SUCCESS);
454: }

456: /*@C
457:    LMEAppendOptionsPrefix - Appends to the prefix used for searching for all
458:    LME options in the database.

460:    Logically Collective

462:    Input Parameters:
463: +  lme - the linear matrix equation solver context
464: -  prefix - the prefix string to prepend to all LME option requests

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

470:    Level: advanced

472: .seealso: LMESetOptionsPrefix(), LMEGetOptionsPrefix()
473: @*/
474: PetscErrorCode LMEAppendOptionsPrefix(LME lme,const char *prefix)
475: {
476:   PetscFunctionBegin;
478:   if (!lme->V) PetscCall(LMEGetBV(lme,&lme->V));
479:   PetscCall(BVAppendOptionsPrefix(lme->V,prefix));
480:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)lme,prefix));
481:   PetscFunctionReturn(PETSC_SUCCESS);
482: }

484: /*@C
485:    LMEGetOptionsPrefix - Gets the prefix used for searching for all
486:    LME options in the database.

488:    Not Collective

490:    Input Parameters:
491: .  lme - the linear matrix equation solver context

493:    Output Parameters:
494: .  prefix - pointer to the prefix string used is returned

496:    Note:
497:    On the Fortran side, the user should pass in a string 'prefix' of
498:    sufficient length to hold the prefix.

500:    Level: advanced

502: .seealso: LMESetOptionsPrefix(), LMEAppendOptionsPrefix()
503: @*/
504: PetscErrorCode LMEGetOptionsPrefix(LME lme,const char *prefix[])
505: {
506:   PetscFunctionBegin;
508:   PetscAssertPointer(prefix,2);
509:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)lme,prefix));
510:   PetscFunctionReturn(PETSC_SUCCESS);
511: }