Actual source code: nepbasic.c

slepc-3.16.0 2021-09-30
Report Typos and Errors
  1: /*
  2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  4:    Copyright (c) 2002-2021, 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 NEP routines
 12: */

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

 16: /* Logging support */
 17: PetscClassId      NEP_CLASSID = 0;
 18: PetscLogEvent     NEP_SetUp = 0,NEP_Solve = 0,NEP_Refine = 0,NEP_FunctionEval = 0,NEP_JacobianEval = 0,NEP_Resolvent = 0,NEP_CISS_SVD = 0;

 20: /* List of registered NEP routines */
 21: PetscFunctionList NEPList = 0;
 22: PetscBool         NEPRegisterAllCalled = PETSC_FALSE;

 24: /* List of registered NEP monitors */
 25: PetscFunctionList NEPMonitorList              = NULL;
 26: PetscFunctionList NEPMonitorCreateList        = NULL;
 27: PetscFunctionList NEPMonitorDestroyList       = NULL;
 28: PetscBool         NEPMonitorRegisterAllCalled = PETSC_FALSE;

 30: /*@
 31:    NEPCreate - Creates the default NEP context.

 33:    Collective

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

 38:    Output Parameter:
 39: .  nep - location to put the NEP context

 41:    Level: beginner

 43: .seealso: NEPSetUp(), NEPSolve(), NEPDestroy(), NEP
 44: @*/
 45: PetscErrorCode NEPCreate(MPI_Comm comm,NEP *outnep)
 46: {
 48:   NEP            nep;

 52:   *outnep = 0;
 53:   NEPInitializePackage();
 54:   SlepcHeaderCreate(nep,NEP_CLASSID,"NEP","Nonlinear Eigenvalue Problem","NEP",comm,NEPDestroy,NEPView);

 56:   nep->max_it          = PETSC_DEFAULT;
 57:   nep->nev             = 1;
 58:   nep->ncv             = PETSC_DEFAULT;
 59:   nep->mpd             = PETSC_DEFAULT;
 60:   nep->nini            = 0;
 61:   nep->target          = 0.0;
 62:   nep->tol             = PETSC_DEFAULT;
 63:   nep->conv            = NEP_CONV_NORM;
 64:   nep->stop            = NEP_STOP_BASIC;
 65:   nep->which           = (NEPWhich)0;
 66:   nep->problem_type    = (NEPProblemType)0;
 67:   nep->refine          = NEP_REFINE_NONE;
 68:   nep->npart           = 1;
 69:   nep->rtol            = PETSC_DEFAULT;
 70:   nep->rits            = PETSC_DEFAULT;
 71:   nep->scheme          = (NEPRefineScheme)0;
 72:   nep->trackall        = PETSC_FALSE;
 73:   nep->twosided        = PETSC_FALSE;

 75:   nep->computefunction = NULL;
 76:   nep->computejacobian = NULL;
 77:   nep->functionctx     = NULL;
 78:   nep->jacobianctx     = NULL;
 79:   nep->converged       = NEPConvergedRelative;
 80:   nep->convergeduser   = NULL;
 81:   nep->convergeddestroy= NULL;
 82:   nep->stopping        = NEPStoppingBasic;
 83:   nep->stoppinguser    = NULL;
 84:   nep->stoppingdestroy = NULL;
 85:   nep->convergedctx    = NULL;
 86:   nep->stoppingctx     = NULL;
 87:   nep->numbermonitors  = 0;

 89:   nep->ds              = NULL;
 90:   nep->V               = NULL;
 91:   nep->W               = NULL;
 92:   nep->rg              = NULL;
 93:   nep->function        = NULL;
 94:   nep->function_pre    = NULL;
 95:   nep->jacobian        = NULL;
 96:   nep->A               = NULL;
 97:   nep->f               = NULL;
 98:   nep->nt              = 0;
 99:   nep->mstr            = UNKNOWN_NONZERO_PATTERN;
100:   nep->IS              = NULL;
101:   nep->eigr            = NULL;
102:   nep->eigi            = NULL;
103:   nep->errest          = NULL;
104:   nep->perm            = NULL;
105:   nep->nwork           = 0;
106:   nep->work            = NULL;
107:   nep->data            = NULL;

109:   nep->state           = NEP_STATE_INITIAL;
110:   nep->nconv           = 0;
111:   nep->its             = 0;
112:   nep->n               = 0;
113:   nep->nloc            = 0;
114:   nep->nrma            = NULL;
115:   nep->fui             = (NEPUserInterface)0;
116:   nep->useds           = PETSC_FALSE;
117:   nep->resolvent       = NULL;
118:   nep->reason          = NEP_CONVERGED_ITERATING;

120:   PetscNewLog(nep,&nep->sc);
121:   *outnep = nep;
122:   return(0);
123: }

125: /*@C
126:    NEPSetType - Selects the particular solver to be used in the NEP object.

128:    Logically Collective on nep

130:    Input Parameters:
131: +  nep      - the nonlinear eigensolver context
132: -  type     - a known method

134:    Options Database Key:
135: .  -nep_type <method> - Sets the method; use -help for a list
136:     of available methods

138:    Notes:
139:    See "slepc/include/slepcnep.h" for available methods.

141:    Normally, it is best to use the NEPSetFromOptions() command and
142:    then set the NEP type from the options database rather than by using
143:    this routine.  Using the options database provides the user with
144:    maximum flexibility in evaluating the different available methods.
145:    The NEPSetType() routine is provided for those situations where it
146:    is necessary to set the iterative solver independently of the command
147:    line or options database.

149:    Level: intermediate

151: .seealso: NEPType
152: @*/
153: PetscErrorCode NEPSetType(NEP nep,NEPType type)
154: {
155:   PetscErrorCode ierr,(*r)(NEP);
156:   PetscBool      match;


162:   PetscObjectTypeCompare((PetscObject)nep,type,&match);
163:   if (match) return(0);

165:   PetscFunctionListFind(NEPList,type,&r);
166:   if (!r) SETERRQ1(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown NEP type given: %s",type);

168:   if (nep->ops->destroy) { (*nep->ops->destroy)(nep); }
169:   PetscMemzero(nep->ops,sizeof(struct _NEPOps));

171:   nep->state = NEP_STATE_INITIAL;
172:   PetscObjectChangeTypeName((PetscObject)nep,type);
173:   (*r)(nep);
174:   return(0);
175: }

177: /*@C
178:    NEPGetType - Gets the NEP type as a string from the NEP object.

180:    Not Collective

182:    Input Parameter:
183: .  nep - the eigensolver context

185:    Output Parameter:
186: .  name - name of NEP method

188:    Level: intermediate

190: .seealso: NEPSetType()
191: @*/
192: PetscErrorCode NEPGetType(NEP nep,NEPType *type)
193: {
197:   *type = ((PetscObject)nep)->type_name;
198:   return(0);
199: }

201: /*@C
202:    NEPRegister - Adds a method to the nonlinear eigenproblem solver package.

204:    Not Collective

206:    Input Parameters:
207: +  name - name of a new user-defined solver
208: -  function - routine to create the solver context

210:    Notes:
211:    NEPRegister() may be called multiple times to add several user-defined solvers.

213:    Sample usage:
214: .vb
215:     NEPRegister("my_solver",MySolverCreate);
216: .ve

218:    Then, your solver can be chosen with the procedural interface via
219: $     NEPSetType(nep,"my_solver")
220:    or at runtime via the option
221: $     -nep_type my_solver

223:    Level: advanced

225: .seealso: NEPRegisterAll()
226: @*/
227: PetscErrorCode NEPRegister(const char *name,PetscErrorCode (*function)(NEP))
228: {

232:   NEPInitializePackage();
233:   PetscFunctionListAdd(&NEPList,name,function);
234:   return(0);
235: }

237: /*@C
238:    NEPMonitorRegister - Adds NEP monitor routine.

240:    Not Collective

242:    Input Parameters:
243: +  name    - name of a new monitor routine
244: .  vtype   - a PetscViewerType for the output
245: .  format  - a PetscViewerFormat for the output
246: .  monitor - monitor routine
247: .  create  - creation routine, or NULL
248: -  destroy - destruction routine, or NULL

250:    Notes:
251:    NEPMonitorRegister() may be called multiple times to add several user-defined monitors.

253:    Sample usage:
254: .vb
255:    NEPMonitorRegister("my_monitor",PETSCVIEWERASCII,PETSC_VIEWER_ASCII_INFO_DETAIL,MyMonitor,NULL,NULL);
256: .ve

258:    Then, your monitor can be chosen with the procedural interface via
259: $      NEPMonitorSetFromOptions(nep,"-nep_monitor_my_monitor","my_monitor",NULL)
260:    or at runtime via the option
261: $      -nep_monitor_my_monitor

263:    Level: advanced

265: .seealso: NEPMonitorRegisterAll()
266: @*/
267: PetscErrorCode NEPMonitorRegister(const char name[],PetscViewerType vtype,PetscViewerFormat format,PetscErrorCode (*monitor)(NEP,PetscInt,PetscInt,PetscScalar*,PetscScalar*,PetscReal*,PetscInt,PetscViewerAndFormat*),PetscErrorCode (*create)(PetscViewer,PetscViewerFormat,void*,PetscViewerAndFormat**),PetscErrorCode (*destroy)(PetscViewerAndFormat**))
268: {
269:   char           key[PETSC_MAX_PATH_LEN];

273:   NEPInitializePackage();
274:   SlepcMonitorMakeKey_Internal(name,vtype,format,key);
275:   PetscFunctionListAdd(&NEPMonitorList,key,monitor);
276:   if (create)  { PetscFunctionListAdd(&NEPMonitorCreateList,key,create); }
277:   if (destroy) { PetscFunctionListAdd(&NEPMonitorDestroyList,key,destroy); }
278:   return(0);
279: }

281: /*
282:    NEPReset_Problem - Destroys the problem matrices.
283: @*/
284: PetscErrorCode NEPReset_Problem(NEP nep)
285: {
287:   PetscInt       i;

291:   MatDestroy(&nep->function);
292:   MatDestroy(&nep->function_pre);
293:   MatDestroy(&nep->jacobian);
294:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
295:     MatDestroyMatrices(nep->nt,&nep->A);
296:     for (i=0;i<nep->nt;i++) {
297:       FNDestroy(&nep->f[i]);
298:     }
299:     PetscFree(nep->f);
300:     PetscFree(nep->nrma);
301:     nep->nt = 0;
302:   }
303:   return(0);
304: }
305: /*@
306:    NEPReset - Resets the NEP context to the initial state (prior to setup)
307:    and destroys any allocated Vecs and Mats.

309:    Collective on nep

311:    Input Parameter:
312: .  nep - eigensolver context obtained from NEPCreate()

314:    Level: advanced

316: .seealso: NEPDestroy()
317: @*/
318: PetscErrorCode NEPReset(NEP nep)
319: {

324:   if (!nep) return(0);
325:   if (nep->ops->reset) { (nep->ops->reset)(nep); }
326:   if (nep->refineksp) { KSPReset(nep->refineksp); }
327:   NEPReset_Problem(nep);
328:   BVDestroy(&nep->V);
329:   BVDestroy(&nep->W);
330:   VecDestroyVecs(nep->nwork,&nep->work);
331:   MatDestroy(&nep->resolvent);
332:   nep->nwork = 0;
333:   nep->state = NEP_STATE_INITIAL;
334:   return(0);
335: }

337: /*@C
338:    NEPDestroy - Destroys the NEP context.

340:    Collective on nep

342:    Input Parameter:
343: .  nep - eigensolver context obtained from NEPCreate()

345:    Level: beginner

347: .seealso: NEPCreate(), NEPSetUp(), NEPSolve()
348: @*/
349: PetscErrorCode NEPDestroy(NEP *nep)
350: {

354:   if (!*nep) return(0);
356:   if (--((PetscObject)(*nep))->refct > 0) { *nep = 0; return(0); }
357:   NEPReset(*nep);
358:   if ((*nep)->ops->destroy) { (*(*nep)->ops->destroy)(*nep); }
359:   if ((*nep)->eigr) {
360:     PetscFree4((*nep)->eigr,(*nep)->eigi,(*nep)->errest,(*nep)->perm);
361:   }
362:   RGDestroy(&(*nep)->rg);
363:   DSDestroy(&(*nep)->ds);
364:   KSPDestroy(&(*nep)->refineksp);
365:   PetscSubcommDestroy(&(*nep)->refinesubc);
366:   PetscFree((*nep)->sc);
367:   /* just in case the initial vectors have not been used */
368:   SlepcBasisDestroy_Private(&(*nep)->nini,&(*nep)->IS);
369:   if ((*nep)->convergeddestroy) {
370:     (*(*nep)->convergeddestroy)((*nep)->convergedctx);
371:   }
372:   NEPMonitorCancel(*nep);
373:   PetscHeaderDestroy(nep);
374:   return(0);
375: }

377: /*@
378:    NEPSetBV - Associates a basis vectors object to the nonlinear eigensolver.

380:    Collective on nep

382:    Input Parameters:
383: +  nep - eigensolver context obtained from NEPCreate()
384: -  bv  - the basis vectors object

386:    Note:
387:    Use NEPGetBV() to retrieve the basis vectors context (for example,
388:    to free it at the end of the computations).

390:    Level: advanced

392: .seealso: NEPGetBV()
393: @*/
394: PetscErrorCode NEPSetBV(NEP nep,BV bv)
395: {

402:   PetscObjectReference((PetscObject)bv);
403:   BVDestroy(&nep->V);
404:   nep->V = bv;
405:   PetscLogObjectParent((PetscObject)nep,(PetscObject)nep->V);
406:   return(0);
407: }

409: /*@
410:    NEPGetBV - Obtain the basis vectors object associated to the nonlinear
411:    eigensolver object.

413:    Not Collective

415:    Input Parameters:
416: .  nep - eigensolver context obtained from NEPCreate()

418:    Output Parameter:
419: .  bv - basis vectors context

421:    Level: advanced

423: .seealso: NEPSetBV()
424: @*/
425: PetscErrorCode NEPGetBV(NEP nep,BV *bv)
426: {

432:   if (!nep->V) {
433:     BVCreate(PetscObjectComm((PetscObject)nep),&nep->V);
434:     PetscObjectIncrementTabLevel((PetscObject)nep->V,(PetscObject)nep,0);
435:     PetscLogObjectParent((PetscObject)nep,(PetscObject)nep->V);
436:     PetscObjectSetOptions((PetscObject)nep->V,((PetscObject)nep)->options);
437:   }
438:   *bv = nep->V;
439:   return(0);
440: }

442: /*@
443:    NEPSetRG - Associates a region object to the nonlinear eigensolver.

445:    Collective on nep

447:    Input Parameters:
448: +  nep - eigensolver context obtained from NEPCreate()
449: -  rg  - the region object

451:    Note:
452:    Use NEPGetRG() to retrieve the region context (for example,
453:    to free it at the end of the computations).

455:    Level: advanced

457: .seealso: NEPGetRG()
458: @*/
459: PetscErrorCode NEPSetRG(NEP nep,RG rg)
460: {

465:   if (rg) {
468:   }
469:   PetscObjectReference((PetscObject)rg);
470:   RGDestroy(&nep->rg);
471:   nep->rg = rg;
472:   PetscLogObjectParent((PetscObject)nep,(PetscObject)nep->rg);
473:   return(0);
474: }

476: /*@
477:    NEPGetRG - Obtain the region object associated to the
478:    nonlinear eigensolver object.

480:    Not Collective

482:    Input Parameters:
483: .  nep - eigensolver context obtained from NEPCreate()

485:    Output Parameter:
486: .  rg - region context

488:    Level: advanced

490: .seealso: NEPSetRG()
491: @*/
492: PetscErrorCode NEPGetRG(NEP nep,RG *rg)
493: {

499:   if (!nep->rg) {
500:     RGCreate(PetscObjectComm((PetscObject)nep),&nep->rg);
501:     PetscObjectIncrementTabLevel((PetscObject)nep->rg,(PetscObject)nep,0);
502:     PetscLogObjectParent((PetscObject)nep,(PetscObject)nep->rg);
503:     PetscObjectSetOptions((PetscObject)nep->rg,((PetscObject)nep)->options);
504:   }
505:   *rg = nep->rg;
506:   return(0);
507: }

509: /*@
510:    NEPSetDS - Associates a direct solver object to the nonlinear eigensolver.

512:    Collective on nep

514:    Input Parameters:
515: +  nep - eigensolver context obtained from NEPCreate()
516: -  ds  - the direct solver object

518:    Note:
519:    Use NEPGetDS() to retrieve the direct solver context (for example,
520:    to free it at the end of the computations).

522:    Level: advanced

524: .seealso: NEPGetDS()
525: @*/
526: PetscErrorCode NEPSetDS(NEP nep,DS ds)
527: {

534:   PetscObjectReference((PetscObject)ds);
535:   DSDestroy(&nep->ds);
536:   nep->ds = ds;
537:   PetscLogObjectParent((PetscObject)nep,(PetscObject)nep->ds);
538:   return(0);
539: }

541: /*@
542:    NEPGetDS - Obtain the direct solver object associated to the
543:    nonlinear eigensolver object.

545:    Not Collective

547:    Input Parameters:
548: .  nep - eigensolver context obtained from NEPCreate()

550:    Output Parameter:
551: .  ds - direct solver context

553:    Level: advanced

555: .seealso: NEPSetDS()
556: @*/
557: PetscErrorCode NEPGetDS(NEP nep,DS *ds)
558: {

564:   if (!nep->ds) {
565:     DSCreate(PetscObjectComm((PetscObject)nep),&nep->ds);
566:     PetscObjectIncrementTabLevel((PetscObject)nep->ds,(PetscObject)nep,0);
567:     PetscLogObjectParent((PetscObject)nep,(PetscObject)nep->ds);
568:     PetscObjectSetOptions((PetscObject)nep->ds,((PetscObject)nep)->options);
569:   }
570:   *ds = nep->ds;
571:   return(0);
572: }

574: /*@
575:    NEPRefineGetKSP - Obtain the ksp object used by the eigensolver
576:    object in the refinement phase.

578:    Not Collective

580:    Input Parameters:
581: .  nep - eigensolver context obtained from NEPCreate()

583:    Output Parameter:
584: .  ksp - ksp context

586:    Level: advanced

588: .seealso: NEPSetRefine()
589: @*/
590: PetscErrorCode NEPRefineGetKSP(NEP nep,KSP *ksp)
591: {

597:   if (!nep->refineksp) {
598:     if (nep->npart>1) {
599:       /* Split in subcomunicators */
600:       PetscSubcommCreate(PetscObjectComm((PetscObject)nep),&nep->refinesubc);
601:       PetscSubcommSetNumber(nep->refinesubc,nep->npart);
602:       PetscSubcommSetType(nep->refinesubc,PETSC_SUBCOMM_CONTIGUOUS);
603:       PetscLogObjectMemory((PetscObject)nep,sizeof(PetscSubcomm));
604:     }
605:     KSPCreate((nep->npart==1)?PetscObjectComm((PetscObject)nep):PetscSubcommChild(nep->refinesubc),&nep->refineksp);
606:     PetscObjectIncrementTabLevel((PetscObject)nep->refineksp,(PetscObject)nep,0);
607:     PetscLogObjectParent((PetscObject)nep,(PetscObject)nep->refineksp);
608:     PetscObjectSetOptions((PetscObject)nep->refineksp,((PetscObject)nep)->options);
609:     KSPSetOptionsPrefix(*ksp,((PetscObject)nep)->prefix);
610:     KSPAppendOptionsPrefix(*ksp,"nep_refine_");
611:     KSPSetTolerances(nep->refineksp,SlepcDefaultTol(nep->rtol),PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
612:   }
613:   *ksp = nep->refineksp;
614:   return(0);
615: }

617: /*@
618:    NEPSetTarget - Sets the value of the target.

620:    Logically Collective on nep

622:    Input Parameters:
623: +  nep    - eigensolver context
624: -  target - the value of the target

626:    Options Database Key:
627: .  -nep_target <scalar> - the value of the target

629:    Notes:
630:    The target is a scalar value used to determine the portion of the spectrum
631:    of interest. It is used in combination with NEPSetWhichEigenpairs().

633:    In the case of complex scalars, a complex value can be provided in the
634:    command line with [+/-][realnumber][+/-]realnumberi with no spaces, e.g.
635:    -nep_target 1.0+2.0i

637:    Level: intermediate

639: .seealso: NEPGetTarget(), NEPSetWhichEigenpairs()
640: @*/
641: PetscErrorCode NEPSetTarget(NEP nep,PetscScalar target)
642: {
646:   nep->target = target;
647:   return(0);
648: }

650: /*@
651:    NEPGetTarget - Gets the value of the target.

653:    Not Collective

655:    Input Parameter:
656: .  nep - eigensolver context

658:    Output Parameter:
659: .  target - the value of the target

661:    Note:
662:    If the target was not set by the user, then zero is returned.

664:    Level: intermediate

666: .seealso: NEPSetTarget()
667: @*/
668: PetscErrorCode NEPGetTarget(NEP nep,PetscScalar* target)
669: {
673:   *target = nep->target;
674:   return(0);
675: }

677: /*@C
678:    NEPSetFunction - Sets the function to compute the nonlinear Function T(lambda)
679:    as well as the location to store the matrix.

681:    Logically Collective on nep

683:    Input Parameters:
684: +  nep - the NEP context
685: .  A   - Function matrix
686: .  B   - preconditioner matrix (usually same as A)
687: .  fun - Function evaluation routine (if NULL then NEP retains any
688:          previously set value)
689: -  ctx - [optional] user-defined context for private data for the Function
690:          evaluation routine (may be NULL) (if NULL then NEP retains any
691:          previously set value)

693:    Calling Sequence of fun:
694: $   fun(NEP nep,PetscScalar lambda,Mat F,Mat P,void *ctx)

696: +  nep    - the NEP context
697: .  lambda - the scalar argument where T(.) must be evaluated
698: .  T      - matrix that will contain T(lambda)
699: .  P      - (optional) different matrix to build the preconditioner
700: -  ctx    - (optional) user-defined context, as set by NEPSetFunction()

702:    Level: beginner

704: .seealso: NEPGetFunction(), NEPSetJacobian()
705: @*/
706: PetscErrorCode NEPSetFunction(NEP nep,Mat A,Mat B,PetscErrorCode (*fun)(NEP,PetscScalar,Mat,Mat,void*),void *ctx)
707: {


717:   if (nep->state) { NEPReset(nep); }
718:   else if (nep->fui && nep->fui!=NEP_USER_INTERFACE_CALLBACK) { NEPReset_Problem(nep); }

720:   if (fun) nep->computefunction = fun;
721:   if (ctx) nep->functionctx     = ctx;
722:   if (A) {
723:     PetscObjectReference((PetscObject)A);
724:     MatDestroy(&nep->function);
725:     nep->function = A;
726:   }
727:   if (B) {
728:     PetscObjectReference((PetscObject)B);
729:     MatDestroy(&nep->function_pre);
730:     nep->function_pre = B;
731:   }
732:   nep->fui   = NEP_USER_INTERFACE_CALLBACK;
733:   nep->state = NEP_STATE_INITIAL;
734:   return(0);
735: }

737: /*@C
738:    NEPGetFunction - Returns the Function matrix and optionally the user
739:    provided context for evaluating the Function.

741:    Not Collective, but Mat object will be parallel if NEP object is

743:    Input Parameter:
744: .  nep - the nonlinear eigensolver context

746:    Output Parameters:
747: +  A   - location to stash Function matrix (or NULL)
748: .  B   - location to stash preconditioner matrix (or NULL)
749: .  fun - location to put Function function (or NULL)
750: -  ctx - location to stash Function context (or NULL)

752:    Level: advanced

754: .seealso: NEPSetFunction()
755: @*/
756: PetscErrorCode NEPGetFunction(NEP nep,Mat *A,Mat *B,PetscErrorCode (**fun)(NEP,PetscScalar,Mat,Mat,void*),void **ctx)
757: {
760:   NEPCheckCallback(nep,1);
761:   if (A)   *A   = nep->function;
762:   if (B)   *B   = nep->function_pre;
763:   if (fun) *fun = nep->computefunction;
764:   if (ctx) *ctx = nep->functionctx;
765:   return(0);
766: }

768: /*@C
769:    NEPSetJacobian - Sets the function to compute the Jacobian T'(lambda) as well
770:    as the location to store the matrix.

772:    Logically Collective on nep

774:    Input Parameters:
775: +  nep - the NEP context
776: .  A   - Jacobian matrix
777: .  jac - Jacobian evaluation routine (if NULL then NEP retains any
778:          previously set value)
779: -  ctx - [optional] user-defined context for private data for the Jacobian
780:          evaluation routine (may be NULL) (if NULL then NEP retains any
781:          previously set value)

783:    Calling Sequence of jac:
784: $   jac(NEP nep,PetscScalar lambda,Mat J,void *ctx)

786: +  nep    - the NEP context
787: .  lambda - the scalar argument where T'(.) must be evaluated
788: .  J      - matrix that will contain T'(lambda)
789: -  ctx    - (optional) user-defined context, as set by NEPSetJacobian()

791:    Level: beginner

793: .seealso: NEPSetFunction(), NEPGetJacobian()
794: @*/
795: PetscErrorCode NEPSetJacobian(NEP nep,Mat A,PetscErrorCode (*jac)(NEP,PetscScalar,Mat,void*),void *ctx)
796: {


804:   if (nep->state) { NEPReset(nep); }
805:   else if (nep->fui && nep->fui!=NEP_USER_INTERFACE_CALLBACK) { NEPReset_Problem(nep); }

807:   if (jac) nep->computejacobian = jac;
808:   if (ctx) nep->jacobianctx     = ctx;
809:   if (A) {
810:     PetscObjectReference((PetscObject)A);
811:     MatDestroy(&nep->jacobian);
812:     nep->jacobian = A;
813:   }
814:   nep->fui   = NEP_USER_INTERFACE_CALLBACK;
815:   nep->state = NEP_STATE_INITIAL;
816:   return(0);
817: }

819: /*@C
820:    NEPGetJacobian - Returns the Jacobian matrix and optionally the user
821:    provided routine and context for evaluating the Jacobian.

823:    Not Collective, but Mat object will be parallel if NEP object is

825:    Input Parameter:
826: .  nep - the nonlinear eigensolver context

828:    Output Parameters:
829: +  A   - location to stash Jacobian matrix (or NULL)
830: .  jac - location to put Jacobian function (or NULL)
831: -  ctx - location to stash Jacobian context (or NULL)

833:    Level: advanced

835: .seealso: NEPSetJacobian()
836: @*/
837: PetscErrorCode NEPGetJacobian(NEP nep,Mat *A,PetscErrorCode (**jac)(NEP,PetscScalar,Mat,void*),void **ctx)
838: {
841:   NEPCheckCallback(nep,1);
842:   if (A)   *A   = nep->jacobian;
843:   if (jac) *jac = nep->computejacobian;
844:   if (ctx) *ctx = nep->jacobianctx;
845:   return(0);
846: }

848: /*@
849:    NEPSetSplitOperator - Sets the operator of the nonlinear eigenvalue problem
850:    in split form.

852:    Collective on nep

854:    Input Parameters:
855: +  nep - the nonlinear eigensolver context
856: .  n   - number of terms in the split form
857: .  A   - array of matrices
858: .  f   - array of functions
859: -  str - structure flag for matrices

861:    Notes:
862:    The nonlinear operator is written as T(lambda) = sum_i A_i*f_i(lambda),
863:    for i=1,...,n. The derivative T'(lambda) can be obtained using the
864:    derivatives of f_i.

866:    The structure flag provides information about A_i's nonzero pattern
867:    (see MatStructure enum). If all matrices have the same pattern, then
868:    use SAME_NONZERO_PATTERN. If the patterns are different but contained
869:    in the pattern of the first one, then use SUBSET_NONZERO_PATTERN. If
870:    patterns are known to be different, use DIFFERENT_NONZERO_PATTERN.
871:    If set to UNKNOWN_NONZERO_PATTERN, the patterns will be compared to
872:    determine if they are equal.

874:    This function must be called before NEPSetUp(). If it is called again
875:    after NEPSetUp() then the NEP object is reset.

877:    Level: beginner

879: .seealso: NEPGetSplitOperatorTerm(), NEPGetSplitOperatorInfo()
880:  @*/
881: PetscErrorCode NEPSetSplitOperator(NEP nep,PetscInt nt,Mat A[],FN f[],MatStructure str)
882: {
883:   PetscInt       i,n=0,m,m0=0,mloc,nloc,mloc0=0;

889:   if (nt <= 0) SETERRQ1(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more terms, you have %D",nt);

893:   for (i=0;i<nt;i++) {
898:     MatGetSize(A[i],&m,&n);
899:     MatGetLocalSize(A[i],&mloc,&nloc);
900:     if (m!=n) SETERRQ3(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONG,"A[%D] is a non-square matrix (%D rows, %D cols)",i,m,n);
901:     if (mloc!=nloc) SETERRQ3(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONG,"A[%D] does not have equal row and column local sizes (%D, %D)",i,mloc,nloc);
902:     if (!i) { m0 = m; mloc0 = mloc; }
903:     if (m!=m0) SETERRQ3(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_INCOMP,"Dimensions of A[%D] do not match with previous matrices (%D, %D)",i,m,m0);
904:     if (mloc!=mloc0) SETERRQ3(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_INCOMP,"Local dimensions of A[%D] do not match with previous matrices (%D, %D)",i,mloc,mloc0);
905:     PetscObjectReference((PetscObject)A[i]);
906:     PetscObjectReference((PetscObject)f[i]);
907:   }

909:   if (nep->state && (n!=nep->n || nloc!=nep->nloc)) { NEPReset(nep); }
910:   else { NEPReset_Problem(nep); }

912:   /* allocate space and copy matrices and functions */
913:   PetscMalloc1(nt,&nep->A);
914:   PetscLogObjectMemory((PetscObject)nep,nt*sizeof(Mat));
915:   for (i=0;i<nt;i++) nep->A[i] = A[i];
916:   PetscMalloc1(nt,&nep->f);
917:   PetscLogObjectMemory((PetscObject)nep,nt*sizeof(FN));
918:   for (i=0;i<nt;i++) nep->f[i] = f[i];
919:   PetscCalloc1(nt,&nep->nrma);
920:   PetscLogObjectMemory((PetscObject)nep,nt*sizeof(PetscReal));
921:   nep->nt    = nt;
922:   nep->mstr  = str;
923:   nep->fui   = NEP_USER_INTERFACE_SPLIT;
924:   nep->state = NEP_STATE_INITIAL;
925:   return(0);
926: }

928: /*@
929:    NEPGetSplitOperatorTerm - Gets the matrices and functions associated with
930:    the nonlinear operator in split form.

932:    Not collective, though parallel Mats and FNs are returned if the NEP is parallel

934:    Input Parameters:
935: +  nep - the nonlinear eigensolver context
936: -  k   - the index of the requested term (starting in 0)

938:    Output Parameters:
939: +  A - the matrix of the requested term
940: -  f - the function of the requested term

942:    Level: intermediate

944: .seealso: NEPSetSplitOperator(), NEPGetSplitOperatorInfo()
945: @*/
946: PetscErrorCode NEPGetSplitOperatorTerm(NEP nep,PetscInt k,Mat *A,FN *f)
947: {
950:   NEPCheckSplit(nep,1);
951:   if (k<0 || k>=nep->nt) SETERRQ1(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %D",nep->nt-1);
952:   if (A) *A = nep->A[k];
953:   if (f) *f = nep->f[k];
954:   return(0);
955: }

957: /*@
958:    NEPGetSplitOperatorInfo - Returns the number of terms of the split form of
959:    the nonlinear operator, as well as the structure flag for matrices.

961:    Not collective

963:    Input Parameter:
964: .  nep - the nonlinear eigensolver context

966:    Output Parameters:
967: +  n   - the number of terms passed in NEPSetSplitOperator()
968: -  str - the matrix structure flag passed in NEPSetSplitOperator()

970:    Level: intermediate

972: .seealso: NEPSetSplitOperator(), NEPGetSplitOperatorTerm()
973: @*/
974: PetscErrorCode NEPGetSplitOperatorInfo(NEP nep,PetscInt *n,MatStructure *str)
975: {
978:   NEPCheckSplit(nep,1);
979:   if (n)   *n = nep->nt;
980:   if (str) *str = nep->mstr;
981:   return(0);
982: }