Actual source code: svdbasic.c

slepc-main 2024-11-09
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:    Basic SVD routines
 12: */

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

 16: /* Logging support */
 17: PetscClassId      SVD_CLASSID = 0;
 18: PetscLogEvent     SVD_SetUp = 0,SVD_Solve = 0;

 20: /* List of registered SVD routines */
 21: PetscFunctionList SVDList = NULL;
 22: PetscBool         SVDRegisterAllCalled = PETSC_FALSE;

 24: /* List of registered SVD monitors */
 25: PetscFunctionList SVDMonitorList              = NULL;
 26: PetscFunctionList SVDMonitorCreateList        = NULL;
 27: PetscFunctionList SVDMonitorDestroyList       = NULL;
 28: PetscBool         SVDMonitorRegisterAllCalled = PETSC_FALSE;

 30: /*@
 31:    SVDCreate - Creates the default SVD context.

 33:    Collective

 35:    Input Parameter:
 36: .  comm - MPI communicator

 38:    Output Parameter:
 39: .  outsvd - location to put the SVD context

 41:    Note:
 42:    The default SVD type is SVDCROSS

 44:    Level: beginner

 46: .seealso: SVDSetUp(), SVDSolve(), SVDDestroy(), SVD
 47: @*/
 48: PetscErrorCode SVDCreate(MPI_Comm comm,SVD *outsvd)
 49: {
 50:   SVD            svd;

 52:   PetscFunctionBegin;
 53:   PetscAssertPointer(outsvd,2);
 54:   PetscCall(SVDInitializePackage());
 55:   PetscCall(SlepcHeaderCreate(svd,SVD_CLASSID,"SVD","Singular Value Decomposition","SVD",comm,SVDDestroy,SVDView));

 57:   svd->OP               = NULL;
 58:   svd->OPb              = NULL;
 59:   svd->omega            = NULL;
 60:   svd->max_it           = PETSC_DETERMINE;
 61:   svd->nsv              = 1;
 62:   svd->ncv              = PETSC_DETERMINE;
 63:   svd->mpd              = PETSC_DETERMINE;
 64:   svd->nini             = 0;
 65:   svd->ninil            = 0;
 66:   svd->tol              = PETSC_DETERMINE;
 67:   svd->conv             = (SVDConv)-1;
 68:   svd->stop             = SVD_STOP_BASIC;
 69:   svd->which            = SVD_LARGEST;
 70:   svd->problem_type     = (SVDProblemType)0;
 71:   svd->impltrans        = PETSC_FALSE;
 72:   svd->trackall         = PETSC_FALSE;

 74:   svd->converged        = NULL;
 75:   svd->convergeduser    = NULL;
 76:   svd->convergeddestroy = NULL;
 77:   svd->stopping         = SVDStoppingBasic;
 78:   svd->stoppinguser     = NULL;
 79:   svd->stoppingdestroy  = NULL;
 80:   svd->convergedctx     = NULL;
 81:   svd->stoppingctx      = NULL;
 82:   svd->numbermonitors   = 0;

 84:   svd->ds               = NULL;
 85:   svd->U                = NULL;
 86:   svd->V                = NULL;
 87:   svd->A                = NULL;
 88:   svd->B                = NULL;
 89:   svd->AT               = NULL;
 90:   svd->BT               = NULL;
 91:   svd->IS               = NULL;
 92:   svd->ISL              = NULL;
 93:   svd->sigma            = NULL;
 94:   svd->errest           = NULL;
 95:   svd->sign             = NULL;
 96:   svd->perm             = NULL;
 97:   svd->nworkl           = 0;
 98:   svd->nworkr           = 0;
 99:   svd->workl            = NULL;
100:   svd->workr            = NULL;
101:   svd->data             = NULL;

103:   svd->state            = SVD_STATE_INITIAL;
104:   svd->nconv            = 0;
105:   svd->its              = 0;
106:   svd->leftbasis        = PETSC_FALSE;
107:   svd->swapped          = PETSC_FALSE;
108:   svd->expltrans        = PETSC_FALSE;
109:   svd->nrma             = 0.0;
110:   svd->nrmb             = 0.0;
111:   svd->isgeneralized    = PETSC_FALSE;
112:   svd->reason           = SVD_CONVERGED_ITERATING;

114:   PetscCall(PetscNew(&svd->sc));
115:   *outsvd = svd;
116:   PetscFunctionReturn(PETSC_SUCCESS);
117: }

119: /*@
120:    SVDReset - Resets the SVD context to the initial state (prior to setup)
121:    and destroys any allocated Vecs and Mats.

123:    Collective

125:    Input Parameter:
126: .  svd - singular value solver context obtained from SVDCreate()

128:    Level: advanced

130: .seealso: SVDDestroy()
131: @*/
132: PetscErrorCode SVDReset(SVD svd)
133: {
134:   PetscFunctionBegin;
136:   if (!svd) PetscFunctionReturn(PETSC_SUCCESS);
137:   PetscTryTypeMethod(svd,reset);
138:   PetscCall(MatDestroy(&svd->OP));
139:   PetscCall(MatDestroy(&svd->OPb));
140:   PetscCall(VecDestroy(&svd->omega));
141:   PetscCall(MatDestroy(&svd->A));
142:   PetscCall(MatDestroy(&svd->B));
143:   PetscCall(MatDestroy(&svd->AT));
144:   PetscCall(MatDestroy(&svd->BT));
145:   PetscCall(BVDestroy(&svd->U));
146:   PetscCall(BVDestroy(&svd->V));
147:   PetscCall(VecDestroyVecs(svd->nworkl,&svd->workl));
148:   svd->nworkl = 0;
149:   PetscCall(VecDestroyVecs(svd->nworkr,&svd->workr));
150:   svd->nworkr = 0;
151:   svd->swapped = PETSC_FALSE;
152:   svd->state = SVD_STATE_INITIAL;
153:   PetscFunctionReturn(PETSC_SUCCESS);
154: }

156: /*@
157:    SVDDestroy - Destroys the SVD context.

159:    Collective

161:    Input Parameter:
162: .  svd - singular value solver context obtained from SVDCreate()

164:    Level: beginner

166: .seealso: SVDCreate(), SVDSetUp(), SVDSolve()
167: @*/
168: PetscErrorCode SVDDestroy(SVD *svd)
169: {
170:   PetscFunctionBegin;
171:   if (!*svd) PetscFunctionReturn(PETSC_SUCCESS);
173:   if (--((PetscObject)*svd)->refct > 0) { *svd = NULL; PetscFunctionReturn(PETSC_SUCCESS); }
174:   PetscCall(SVDReset(*svd));
175:   PetscTryTypeMethod(*svd,destroy);
176:   if ((*svd)->sigma) PetscCall(PetscFree3((*svd)->sigma,(*svd)->perm,(*svd)->errest));
177:   if ((*svd)->sign) PetscCall(PetscFree((*svd)->sign));
178:   PetscCall(DSDestroy(&(*svd)->ds));
179:   PetscCall(PetscFree((*svd)->sc));
180:   /* just in case the initial vectors have not been used */
181:   PetscCall(SlepcBasisDestroy_Private(&(*svd)->nini,&(*svd)->IS));
182:   PetscCall(SlepcBasisDestroy_Private(&(*svd)->ninil,&(*svd)->ISL));
183:   if ((*svd)->convergeddestroy) PetscCall((*(*svd)->convergeddestroy)(&(*svd)->convergedctx));
184:   if ((*svd)->stoppingdestroy) PetscCall((*(*svd)->stoppingdestroy)(&(*svd)->stoppingctx));
185:   PetscCall(SVDMonitorCancel(*svd));
186:   PetscCall(PetscHeaderDestroy(svd));
187:   PetscFunctionReturn(PETSC_SUCCESS);
188: }

190: /*@
191:    SVDSetType - Selects the particular solver to be used in the SVD object.

193:    Logically Collective

195:    Input Parameters:
196: +  svd      - the singular value solver context
197: -  type     - a known method

199:    Options Database Key:
200: .  -svd_type <method> - Sets the method; use -help for a list
201:     of available methods

203:    Notes:
204:    See "slepc/include/slepcsvd.h" for available methods. The default
205:    is SVDCROSS.

207:    Normally, it is best to use the SVDSetFromOptions() command and
208:    then set the SVD type from the options database rather than by using
209:    this routine.  Using the options database provides the user with
210:    maximum flexibility in evaluating the different available methods.
211:    The SVDSetType() routine is provided for those situations where it
212:    is necessary to set the iterative solver independently of the command
213:    line or options database.

215:    Level: intermediate

217: .seealso: SVDType
218: @*/
219: PetscErrorCode SVDSetType(SVD svd,SVDType type)
220: {
221:   PetscErrorCode (*r)(SVD);
222:   PetscBool      match;

224:   PetscFunctionBegin;
226:   PetscAssertPointer(type,2);

228:   PetscCall(PetscObjectTypeCompare((PetscObject)svd,type,&match));
229:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

231:   PetscCall(PetscFunctionListFind(SVDList,type,&r));
232:   PetscCheck(r,PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown SVD type given: %s",type);

234:   PetscTryTypeMethod(svd,destroy);
235:   PetscCall(PetscMemzero(svd->ops,sizeof(struct _SVDOps)));

237:   svd->state = SVD_STATE_INITIAL;
238:   PetscCall(PetscObjectChangeTypeName((PetscObject)svd,type));
239:   PetscCall((*r)(svd));
240:   PetscFunctionReturn(PETSC_SUCCESS);
241: }

243: /*@
244:    SVDGetType - Gets the SVD type as a string from the SVD object.

246:    Not Collective

248:    Input Parameter:
249: .  svd - the singular value solver context

251:    Output Parameter:
252: .  type - name of SVD method

254:    Level: intermediate

256: .seealso: SVDSetType()
257: @*/
258: PetscErrorCode SVDGetType(SVD svd,SVDType *type)
259: {
260:   PetscFunctionBegin;
262:   PetscAssertPointer(type,2);
263:   *type = ((PetscObject)svd)->type_name;
264:   PetscFunctionReturn(PETSC_SUCCESS);
265: }

267: /*@C
268:    SVDRegister - Adds a method to the singular value solver package.

270:    Not Collective

272:    Input Parameters:
273: +  name - name of a new user-defined solver
274: -  function - routine to create the solver context

276:    Notes:
277:    SVDRegister() may be called multiple times to add several user-defined solvers.

279:    Example Usage:
280: .vb
281:     SVDRegister("my_solver",MySolverCreate);
282: .ve

284:    Then, your solver can be chosen with the procedural interface via
285: $     SVDSetType(svd,"my_solver")
286:    or at runtime via the option
287: $     -svd_type my_solver

289:    Level: advanced

291: .seealso: SVDRegisterAll()
292: @*/
293: PetscErrorCode SVDRegister(const char *name,PetscErrorCode (*function)(SVD))
294: {
295:   PetscFunctionBegin;
296:   PetscCall(SVDInitializePackage());
297:   PetscCall(PetscFunctionListAdd(&SVDList,name,function));
298:   PetscFunctionReturn(PETSC_SUCCESS);
299: }

301: /*@C
302:    SVDMonitorRegister - Adds SVD monitor routine.

304:    Not Collective

306:    Input Parameters:
307: +  name    - name of a new monitor routine
308: .  vtype   - a PetscViewerType for the output
309: .  format  - a PetscViewerFormat for the output
310: .  monitor - monitor routine
311: .  create  - creation routine, or NULL
312: -  destroy - destruction routine, or NULL

314:    Notes:
315:    SVDMonitorRegister() may be called multiple times to add several user-defined monitors.

317:    Example Usage:
318: .vb
319:    SVDMonitorRegister("my_monitor",PETSCVIEWERASCII,PETSC_VIEWER_ASCII_INFO_DETAIL,MyMonitor,NULL,NULL);
320: .ve

322:    Then, your monitor can be chosen with the procedural interface via
323: $      SVDMonitorSetFromOptions(svd,"-svd_monitor_my_monitor","my_monitor",NULL)
324:    or at runtime via the option
325: $      -svd_monitor_my_monitor

327:    Level: advanced

329: .seealso: SVDMonitorRegisterAll()
330: @*/
331: PetscErrorCode SVDMonitorRegister(const char name[],PetscViewerType vtype,PetscViewerFormat format,PetscErrorCode (*monitor)(SVD,PetscInt,PetscInt,PetscReal*,PetscReal*,PetscInt,PetscViewerAndFormat*),PetscErrorCode (*create)(PetscViewer,PetscViewerFormat,void*,PetscViewerAndFormat**),PetscErrorCode (*destroy)(PetscViewerAndFormat**))
332: {
333:   char           key[PETSC_MAX_PATH_LEN];

335:   PetscFunctionBegin;
336:   PetscCall(SVDInitializePackage());
337:   PetscCall(SlepcMonitorMakeKey_Internal(name,vtype,format,key));
338:   PetscCall(PetscFunctionListAdd(&SVDMonitorList,key,monitor));
339:   if (create)  PetscCall(PetscFunctionListAdd(&SVDMonitorCreateList,key,create));
340:   if (destroy) PetscCall(PetscFunctionListAdd(&SVDMonitorDestroyList,key,destroy));
341:   PetscFunctionReturn(PETSC_SUCCESS);
342: }

344: /*@
345:    SVDSetBV - Associates basis vectors objects to the singular value solver.

347:    Collective

349:    Input Parameters:
350: +  svd - singular value solver context obtained from SVDCreate()
351: .  V   - the basis vectors object for right singular vectors
352: -  U   - the basis vectors object for left singular vectors

354:    Note:
355:    Use SVDGetBV() to retrieve the basis vectors contexts (for example,
356:    to free them at the end of the computations).

358:    Level: advanced

360: .seealso: SVDGetBV()
361: @*/
362: PetscErrorCode SVDSetBV(SVD svd,BV V,BV U)
363: {
364:   PetscFunctionBegin;
366:   if (V) {
368:     PetscCheckSameComm(svd,1,V,2);
369:     PetscCall(PetscObjectReference((PetscObject)V));
370:     PetscCall(BVDestroy(&svd->V));
371:     svd->V = V;
372:   }
373:   if (U) {
375:     PetscCheckSameComm(svd,1,U,3);
376:     PetscCall(PetscObjectReference((PetscObject)U));
377:     PetscCall(BVDestroy(&svd->U));
378:     svd->U = U;
379:   }
380:   PetscFunctionReturn(PETSC_SUCCESS);
381: }

383: /*@
384:    SVDGetBV - Obtain the basis vectors objects associated to the singular
385:    value solver object.

387:    Not Collective

389:    Input Parameter:
390: .  svd - singular value solver context obtained from SVDCreate()

392:    Output Parameters:
393: +  V - basis vectors context for right singular vectors
394: -  U - basis vectors context for left singular vectors

396:    Level: advanced

398: .seealso: SVDSetBV()
399: @*/
400: PetscErrorCode SVDGetBV(SVD svd,BV *V,BV *U)
401: {
402:   PetscFunctionBegin;
404:   if (V) {
405:     if (!svd->V) {
406:       PetscCall(BVCreate(PetscObjectComm((PetscObject)svd),&svd->V));
407:       PetscCall(PetscObjectIncrementTabLevel((PetscObject)svd->V,(PetscObject)svd,0));
408:       PetscCall(PetscObjectSetOptions((PetscObject)svd->V,((PetscObject)svd)->options));
409:     }
410:     *V = svd->V;
411:   }
412:   if (U) {
413:     if (!svd->U) {
414:       PetscCall(BVCreate(PetscObjectComm((PetscObject)svd),&svd->U));
415:       PetscCall(PetscObjectIncrementTabLevel((PetscObject)svd->U,(PetscObject)svd,0));
416:       PetscCall(PetscObjectSetOptions((PetscObject)svd->U,((PetscObject)svd)->options));
417:     }
418:     *U = svd->U;
419:   }
420:   PetscFunctionReturn(PETSC_SUCCESS);
421: }

423: /*@
424:    SVDSetDS - Associates a direct solver object to the singular value solver.

426:    Collective

428:    Input Parameters:
429: +  svd - singular value solver context obtained from SVDCreate()
430: -  ds  - the direct solver object

432:    Note:
433:    Use SVDGetDS() to retrieve the direct solver context (for example,
434:    to free it at the end of the computations).

436:    Level: advanced

438: .seealso: SVDGetDS()
439: @*/
440: PetscErrorCode SVDSetDS(SVD svd,DS ds)
441: {
442:   PetscFunctionBegin;
445:   PetscCheckSameComm(svd,1,ds,2);
446:   PetscCall(PetscObjectReference((PetscObject)ds));
447:   PetscCall(DSDestroy(&svd->ds));
448:   svd->ds = ds;
449:   PetscFunctionReturn(PETSC_SUCCESS);
450: }

452: /*@
453:    SVDGetDS - Obtain the direct solver object associated to the singular value
454:    solver object.

456:    Not Collective

458:    Input Parameters:
459: .  svd - singular value solver context obtained from SVDCreate()

461:    Output Parameter:
462: .  ds - direct solver context

464:    Level: advanced

466: .seealso: SVDSetDS()
467: @*/
468: PetscErrorCode SVDGetDS(SVD svd,DS *ds)
469: {
470:   PetscFunctionBegin;
472:   PetscAssertPointer(ds,2);
473:   if (!svd->ds) {
474:     PetscCall(DSCreate(PetscObjectComm((PetscObject)svd),&svd->ds));
475:     PetscCall(PetscObjectIncrementTabLevel((PetscObject)svd->ds,(PetscObject)svd,0));
476:     PetscCall(PetscObjectSetOptions((PetscObject)svd->ds,((PetscObject)svd)->options));
477:   }
478:   *ds = svd->ds;
479:   PetscFunctionReturn(PETSC_SUCCESS);
480: }