Actual source code: lmebasic.c

slepc-3.8.0 2017-10-20
Report Typos and Errors
  1: /*
  2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  4:    Copyright (c) 2002-2017, 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:    Basic LME routines
 12: */

 14: #include <slepc/private/lmeimpl.h>      /*I "slepclme.h" I*/

 16: PetscFunctionList LMEList = 0;
 17: PetscBool         LMERegisterAllCalled = PETSC_FALSE;
 18: PetscClassId      LME_CLASSID = 0;
 19: PetscLogEvent     LME_SetUp = 0,LME_Solve = 0,LME_ComputeError = 0;

 21: /*@C
 22:    LMEView - Prints the LME data structure.

 24:    Collective on LME

 26:    Input Parameters:
 27: +  lme - the linear matrix equation solver context
 28: -  viewer - optional visualization context

 30:    Options Database Key:
 31: .  -lme_view -  Calls LMEView() at end of LMESolve()

 33:    Note:
 34:    The available visualization contexts include
 35: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
 36: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
 37:          output where only the first processor opens
 38:          the file.  All other processors send their
 39:          data to the first processor to print.

 41:    The user can open an alternative visualization context with
 42:    PetscViewerASCIIOpen() - output to a specified file.

 44:    Level: beginner

 46: .seealso: PetscViewerASCIIOpen()
 47: @*/
 48: PetscErrorCode LMEView(LME lme,PetscViewer viewer)
 49: {
 51:   PetscBool      isascii;
 52:   const char     *eqname[] = {
 53:                    "continuous-time Lyapunov",
 54:                    "continuous-time Sylvester",
 55:                    "generalized Lyapunov",
 56:                    "generalized Sylvester",
 57:                    "Stein",
 58:                    "discrete-time Lyapunov"
 59:   };

 63:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)lme));

 67:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
 68:   if (isascii) {
 69:     PetscObjectPrintClassNamePrefixType((PetscObject)lme,viewer);
 70:     if (lme->ops->view) {
 71:       PetscViewerASCIIPushTab(viewer);
 72:       (*lme->ops->view)(lme,viewer);
 73:       PetscViewerASCIIPopTab(viewer);
 74:     }
 75:     PetscViewerASCIIPrintf(viewer,"  equation type: %s\n",eqname[lme->problem_type]);
 76:     PetscViewerASCIIPrintf(viewer,"  number of column vectors (ncv): %D\n",lme->ncv);
 77:     PetscViewerASCIIPrintf(viewer,"  maximum number of iterations: %D\n",lme->max_it);
 78:     PetscViewerASCIIPrintf(viewer,"  tolerance: %g\n",(double)lme->tol);
 79:   } else {
 80:     if (lme->ops->view) {
 81:       (*lme->ops->view)(lme,viewer);
 82:     }
 83:   }
 84:   PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);
 85:   if (!lme->V) { LMEGetBV(lme,&lme->V); }
 86:   BVView(lme->V,viewer);
 87:   PetscViewerPopFormat(viewer);
 88:   return(0);
 89: }

 91: /*@C
 92:    LMEReasonView - Displays the reason an LME solve converged or diverged.

 94:    Collective on LME

 96:    Parameter:
 97: +  lme - the linear matrix equation context
 98: -  viewer - the viewer to display the reason

100:    Options Database Keys:
101: .  -lme_converged_reason - print reason for convergence, and number of iterations

103:    Level: intermediate

105: .seealso: LMESetTolerances(), LMEGetIterationNumber()
106: @*/
107: PetscErrorCode LMEReasonView(LME lme,PetscViewer viewer)
108: {
110:   PetscBool      isAscii;

113:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isAscii);
114:   if (isAscii) {
115:     PetscViewerASCIIAddTab(viewer,((PetscObject)lme)->tablevel);
116:     if (lme->reason > 0) {
117:       PetscViewerASCIIPrintf(viewer,"%s Linear matrix equation solve converged due to %s; iterations %D\n",((PetscObject)lme)->prefix?((PetscObject)lme)->prefix:"",LMEConvergedReasons[lme->reason],lme->its);
118:     } else {
119:       PetscViewerASCIIPrintf(viewer,"%s Linear matrix equation solve did not converge due to %s; iterations %D\n",((PetscObject)lme)->prefix?((PetscObject)lme)->prefix:"",LMEConvergedReasons[lme->reason],lme->its);
120:     }
121:     PetscViewerASCIISubtractTab(viewer,((PetscObject)lme)->tablevel);
122:   }
123:   return(0);
124: }

126: /*@
127:    LMEReasonViewFromOptions - Processes command line options to determine if/how
128:    the LME converged reason is to be viewed.

130:    Collective on LME

132:    Input Parameters:
133: .  lme - the linear matrix equation context

135:    Level: developer
136: @*/
137: PetscErrorCode LMEReasonViewFromOptions(LME lme)
138: {
139:   PetscErrorCode    ierr;
140:   PetscViewer       viewer;
141:   PetscBool         flg;
142:   static PetscBool  incall = PETSC_FALSE;
143:   PetscViewerFormat format;

146:   if (incall) return(0);
147:   incall = PETSC_TRUE;
148:   PetscOptionsGetViewer(PetscObjectComm((PetscObject)lme),((PetscObject)lme)->prefix,"-lme_converged_reason",&viewer,&format,&flg);
149:   if (flg) {
150:     PetscViewerPushFormat(viewer,format);
151:     LMEReasonView(lme,viewer);
152:     PetscViewerPopFormat(viewer);
153:     PetscViewerDestroy(&viewer);
154:   }
155:   incall = PETSC_FALSE;
156:   return(0);
157: }

159: /*@
160:    LMECreate - Creates the default LME context.

162:    Collective on MPI_Comm

164:    Input Parameter:
165: .  comm - MPI communicator

167:    Output Parameter:
168: .  lme - location to put the LME context

170:    Note:
171:    The default LME type is LMEKRYLOV

173:    Level: beginner

175: .seealso: LMESetUp(), LMESolve(), LMEDestroy(), LME
176: @*/
177: PetscErrorCode LMECreate(MPI_Comm comm,LME *outlme)
178: {
180:   LME            lme;

184:   *outlme = 0;
185:   LMEInitializePackage();
186:   SlepcHeaderCreate(lme,LME_CLASSID,"LME","Linear Matrix Equation","LME",comm,LMEDestroy,LMEView);

188:   lme->A               = NULL;
189:   lme->B               = NULL;
190:   lme->D               = NULL;
191:   lme->E               = NULL;
192:   lme->C               = NULL;
193:   lme->X               = NULL;
194:   lme->problem_type    = LME_LYAPUNOV;
195:   lme->max_it          = 0;
196:   lme->ncv             = 0;
197:   lme->tol             = PETSC_DEFAULT;
198:   lme->errorifnotconverged = PETSC_FALSE;

200:   lme->numbermonitors  = 0;

202:   lme->V               = NULL;
203:   lme->nwork           = 0;
204:   lme->work            = NULL;
205:   lme->data            = NULL;

207:   lme->its             = 0;
208:   lme->errest          = 0;
209:   lme->setupcalled     = 0;
210:   lme->reason          = LME_CONVERGED_ITERATING;

212:   *outlme = lme;
213:   return(0);
214: }

216: /*@C
217:    LMESetType - Selects the particular solver to be used in the LME object.

219:    Logically Collective on LME

221:    Input Parameters:
222: +  lme  - the linear matrix equation context
223: -  type - a known method

225:    Options Database Key:
226: .  -lme_type <method> - Sets the method; use -help for a list
227:     of available methods

229:    Notes:
230:    See "slepc/include/slepclme.h" for available methods. The default
231:    is LMEKRYLOV

233:    Normally, it is best to use the LMESetFromOptions() command and
234:    then set the LME type from the options database rather than by using
235:    this routine.  Using the options database provides the user with
236:    maximum flexibility in evaluating the different available methods.
237:    The LMESetType() routine is provided for those situations where it
238:    is necessary to set the iterative solver independently of the command
239:    line or options database.

241:    Level: intermediate

243: .seealso: LMEType
244: @*/
245: PetscErrorCode LMESetType(LME lme,LMEType type)
246: {
247:   PetscErrorCode ierr,(*r)(LME);
248:   PetscBool      match;


254:   PetscObjectTypeCompare((PetscObject)lme,type,&match);
255:   if (match) return(0);

257:   PetscFunctionListFind(LMEList,type,&r);
258:   if (!r) SETERRQ1(PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown LME type given: %s",type);

260:   if (lme->ops->destroy) { (*lme->ops->destroy)(lme); }
261:   PetscMemzero(lme->ops,sizeof(struct _LMEOps));

263:   lme->setupcalled = 0;
264:   PetscObjectChangeTypeName((PetscObject)lme,type);
265:   (*r)(lme);
266:   return(0);
267: }

269: /*@C
270:    LMEGetType - Gets the LME type as a string from the LME object.

272:    Not Collective

274:    Input Parameter:
275: .  lme - the linear matrix equation context

277:    Output Parameter:
278: .  name - name of LME method

280:    Level: intermediate

282: .seealso: LMESetType()
283: @*/
284: PetscErrorCode LMEGetType(LME lme,LMEType *type)
285: {
289:   *type = ((PetscObject)lme)->type_name;
290:   return(0);
291: }

293: /*@C
294:    LMERegister - Adds a method to the linear matrix equation solver package.

296:    Not Collective

298:    Input Parameters:
299: +  name - name of a new user-defined solver
300: -  function - routine to create the solver context

302:    Notes:
303:    LMERegister() may be called multiple times to add several user-defined solvers.

305:    Sample usage:
306: .vb
307:     LMERegister("my_solver",MySolverCreate);
308: .ve

310:    Then, your solver can be chosen with the procedural interface via
311: $     LMESetType(lme,"my_solver")
312:    or at runtime via the option
313: $     -lme_type my_solver

315:    Level: advanced

317: .seealso: LMERegisterAll()
318: @*/
319: PetscErrorCode LMERegister(const char *name,PetscErrorCode (*function)(LME))
320: {

324:   PetscFunctionListAdd(&LMEList,name,function);
325:   return(0);
326: }

328: /*@
329:    LMEReset - Resets the LME context to the initial state (prior to setup)
330:    and destroys any allocated Vecs and Mats.

332:    Collective on LME

334:    Input Parameter:
335: .  lme - linear matrix equation context obtained from LMECreate()

337:    Level: advanced

339: .seealso: LMEDestroy()
340: @*/
341: PetscErrorCode LMEReset(LME lme)
342: {

347:   if (!lme) return(0);
348:   if (lme->ops->reset) { (lme->ops->reset)(lme); }
349:   MatDestroy(&lme->A);
350:   MatDestroy(&lme->B);
351:   MatDestroy(&lme->D);
352:   MatDestroy(&lme->E);
353:   MatDestroy(&lme->C);
354:   MatDestroy(&lme->X);
355:   BVDestroy(&lme->V);
356:   VecDestroyVecs(lme->nwork,&lme->work);
357:   lme->nwork = 0;
358:   lme->setupcalled = 0;
359:   return(0);
360: }

362: /*@
363:    LMEDestroy - Destroys the LME context.

365:    Collective on LME

367:    Input Parameter:
368: .  lme - linear matrix equation context obtained from LMECreate()

370:    Level: beginner

372: .seealso: LMECreate(), LMESetUp(), LMESolve()
373: @*/
374: PetscErrorCode LMEDestroy(LME *lme)
375: {

379:   if (!*lme) return(0);
381:   if (--((PetscObject)(*lme))->refct > 0) { *lme = 0; return(0); }
382:   LMEReset(*lme);
383:   if ((*lme)->ops->destroy) { (*(*lme)->ops->destroy)(*lme); }
384:   LMEMonitorCancel(*lme);
385:   PetscHeaderDestroy(lme);
386:   return(0);
387: }

389: /*@
390:    LMESetBV - Associates a basis vectors object to the linear matrix equation solver.

392:    Collective on LME

394:    Input Parameters:
395: +  lme - linear matrix equation context obtained from LMECreate()
396: -  bv  - the basis vectors object

398:    Note:
399:    Use LMEGetBV() to retrieve the basis vectors context (for example,
400:    to free it at the end of the computations).

402:    Level: advanced

404: .seealso: LMEGetBV()
405: @*/
406: PetscErrorCode LMESetBV(LME lme,BV bv)
407: {

414:   PetscObjectReference((PetscObject)bv);
415:   BVDestroy(&lme->V);
416:   lme->V = bv;
417:   PetscLogObjectParent((PetscObject)lme,(PetscObject)lme->V);
418:   return(0);
419: }

421: /*@
422:    LMEGetBV - Obtain the basis vectors object associated to the matrix
423:    function solver.

425:    Not Collective

427:    Input Parameters:
428: .  lme - linear matrix equation context obtained from LMECreate()

430:    Output Parameter:
431: .  bv - basis vectors context

433:    Level: advanced

435: .seealso: LMESetBV()
436: @*/
437: PetscErrorCode LMEGetBV(LME lme,BV *bv)
438: {

444:   if (!lme->V) {
445:     BVCreate(PetscObjectComm((PetscObject)lme),&lme->V);
446:     PetscLogObjectParent((PetscObject)lme,(PetscObject)lme->V);
447:   }
448:   *bv = lme->V;
449:   return(0);
450: }