Actual source code: nepbasic.c
slepc-3.20.0 2023-09-29
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 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 = NULL;
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: . outnep - 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: {
47: NEP nep;
49: PetscFunctionBegin;
50: PetscAssertPointer(outnep,2);
51: *outnep = NULL;
52: PetscCall(NEPInitializePackage());
53: PetscCall(SlepcHeaderCreate(nep,NEP_CLASSID,"NEP","Nonlinear Eigenvalue Problem","NEP",comm,NEPDestroy,NEPView));
55: nep->max_it = PETSC_DEFAULT;
56: nep->nev = 1;
57: nep->ncv = PETSC_DEFAULT;
58: nep->mpd = PETSC_DEFAULT;
59: nep->nini = 0;
60: nep->target = 0.0;
61: nep->tol = PETSC_DEFAULT;
62: nep->conv = NEP_CONV_REL;
63: nep->stop = NEP_STOP_BASIC;
64: nep->which = (NEPWhich)0;
65: nep->problem_type = (NEPProblemType)0;
66: nep->refine = NEP_REFINE_NONE;
67: nep->npart = 1;
68: nep->rtol = PETSC_DEFAULT;
69: nep->rits = PETSC_DEFAULT;
70: nep->scheme = (NEPRefineScheme)0;
71: nep->trackall = PETSC_FALSE;
72: nep->twosided = PETSC_FALSE;
74: nep->computefunction = NULL;
75: nep->computejacobian = NULL;
76: nep->functionctx = NULL;
77: nep->jacobianctx = NULL;
78: nep->converged = NEPConvergedRelative;
79: nep->convergeduser = NULL;
80: nep->convergeddestroy= NULL;
81: nep->stopping = NEPStoppingBasic;
82: nep->stoppinguser = NULL;
83: nep->stoppingdestroy = NULL;
84: nep->convergedctx = NULL;
85: nep->stoppingctx = NULL;
86: nep->numbermonitors = 0;
88: nep->ds = NULL;
89: nep->V = NULL;
90: nep->W = NULL;
91: nep->rg = NULL;
92: nep->function = NULL;
93: nep->function_pre = NULL;
94: nep->jacobian = NULL;
95: nep->A = NULL;
96: nep->f = NULL;
97: nep->nt = 0;
98: nep->mstr = UNKNOWN_NONZERO_PATTERN;
99: nep->P = NULL;
100: nep->mstrp = UNKNOWN_NONZERO_PATTERN;
101: nep->IS = NULL;
102: nep->eigr = NULL;
103: nep->eigi = NULL;
104: nep->errest = NULL;
105: nep->perm = NULL;
106: nep->nwork = 0;
107: nep->work = NULL;
108: nep->data = NULL;
110: nep->state = NEP_STATE_INITIAL;
111: nep->nconv = 0;
112: nep->its = 0;
113: nep->n = 0;
114: nep->nloc = 0;
115: nep->nrma = NULL;
116: nep->fui = (NEPUserInterface)0;
117: nep->useds = PETSC_FALSE;
118: nep->resolvent = NULL;
119: nep->reason = NEP_CONVERGED_ITERATING;
121: PetscCall(PetscNew(&nep->sc));
122: *outnep = nep;
123: PetscFunctionReturn(PETSC_SUCCESS);
124: }
126: /*@C
127: NEPSetType - Selects the particular solver to be used in the NEP object.
129: Logically Collective
131: Input Parameters:
132: + nep - the nonlinear eigensolver context
133: - type - a known method
135: Options Database Key:
136: . -nep_type <method> - Sets the method; use -help for a list
137: of available methods
139: Notes:
140: See "slepc/include/slepcnep.h" for available methods.
142: Normally, it is best to use the NEPSetFromOptions() command and
143: then set the NEP type from the options database rather than by using
144: this routine. Using the options database provides the user with
145: maximum flexibility in evaluating the different available methods.
146: The NEPSetType() routine is provided for those situations where it
147: is necessary to set the iterative solver independently of the command
148: line or options database.
150: Level: intermediate
152: .seealso: NEPType
153: @*/
154: PetscErrorCode NEPSetType(NEP nep,NEPType type)
155: {
156: PetscErrorCode (*r)(NEP);
157: PetscBool match;
159: PetscFunctionBegin;
161: PetscAssertPointer(type,2);
163: PetscCall(PetscObjectTypeCompare((PetscObject)nep,type,&match));
164: if (match) PetscFunctionReturn(PETSC_SUCCESS);
166: PetscCall(PetscFunctionListFind(NEPList,type,&r));
167: PetscCheck(r,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown NEP type given: %s",type);
169: PetscTryTypeMethod(nep,destroy);
170: PetscCall(PetscMemzero(nep->ops,sizeof(struct _NEPOps)));
172: nep->state = NEP_STATE_INITIAL;
173: PetscCall(PetscObjectChangeTypeName((PetscObject)nep,type));
174: PetscCall((*r)(nep));
175: PetscFunctionReturn(PETSC_SUCCESS);
176: }
178: /*@C
179: NEPGetType - Gets the NEP type as a string from the NEP object.
181: Not Collective
183: Input Parameter:
184: . nep - the eigensolver context
186: Output Parameter:
187: . type - name of NEP method
189: Level: intermediate
191: .seealso: NEPSetType()
192: @*/
193: PetscErrorCode NEPGetType(NEP nep,NEPType *type)
194: {
195: PetscFunctionBegin;
197: PetscAssertPointer(type,2);
198: *type = ((PetscObject)nep)->type_name;
199: PetscFunctionReturn(PETSC_SUCCESS);
200: }
202: /*@C
203: NEPRegister - Adds a method to the nonlinear eigenproblem solver package.
205: Not Collective
207: Input Parameters:
208: + name - name of a new user-defined solver
209: - function - routine to create the solver context
211: Notes:
212: NEPRegister() may be called multiple times to add several user-defined solvers.
214: Example Usage:
215: .vb
216: NEPRegister("my_solver",MySolverCreate);
217: .ve
219: Then, your solver can be chosen with the procedural interface via
220: $ NEPSetType(nep,"my_solver")
221: or at runtime via the option
222: $ -nep_type my_solver
224: Level: advanced
226: .seealso: NEPRegisterAll()
227: @*/
228: PetscErrorCode NEPRegister(const char *name,PetscErrorCode (*function)(NEP))
229: {
230: PetscFunctionBegin;
231: PetscCall(NEPInitializePackage());
232: PetscCall(PetscFunctionListAdd(&NEPList,name,function));
233: PetscFunctionReturn(PETSC_SUCCESS);
234: }
236: /*@C
237: NEPMonitorRegister - Adds NEP monitor routine.
239: Not Collective
241: Input Parameters:
242: + name - name of a new monitor routine
243: . vtype - a PetscViewerType for the output
244: . format - a PetscViewerFormat for the output
245: . monitor - monitor routine
246: . create - creation routine, or NULL
247: - destroy - destruction routine, or NULL
249: Notes:
250: NEPMonitorRegister() may be called multiple times to add several user-defined monitors.
252: Example Usage:
253: .vb
254: NEPMonitorRegister("my_monitor",PETSCVIEWERASCII,PETSC_VIEWER_ASCII_INFO_DETAIL,MyMonitor,NULL,NULL);
255: .ve
257: Then, your monitor can be chosen with the procedural interface via
258: $ NEPMonitorSetFromOptions(nep,"-nep_monitor_my_monitor","my_monitor",NULL)
259: or at runtime via the option
260: $ -nep_monitor_my_monitor
262: Level: advanced
264: .seealso: NEPMonitorRegisterAll()
265: @*/
266: 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**))
267: {
268: char key[PETSC_MAX_PATH_LEN];
270: PetscFunctionBegin;
271: PetscCall(NEPInitializePackage());
272: PetscCall(SlepcMonitorMakeKey_Internal(name,vtype,format,key));
273: PetscCall(PetscFunctionListAdd(&NEPMonitorList,key,monitor));
274: if (create) PetscCall(PetscFunctionListAdd(&NEPMonitorCreateList,key,create));
275: if (destroy) PetscCall(PetscFunctionListAdd(&NEPMonitorDestroyList,key,destroy));
276: PetscFunctionReturn(PETSC_SUCCESS);
277: }
279: /*
280: NEPReset_Problem - Destroys the problem matrices.
281: */
282: PetscErrorCode NEPReset_Problem(NEP nep)
283: {
284: PetscInt i;
286: PetscFunctionBegin;
288: PetscCall(MatDestroy(&nep->function));
289: PetscCall(MatDestroy(&nep->function_pre));
290: PetscCall(MatDestroy(&nep->jacobian));
291: if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
292: PetscCall(MatDestroyMatrices(nep->nt,&nep->A));
293: for (i=0;i<nep->nt;i++) PetscCall(FNDestroy(&nep->f[i]));
294: PetscCall(PetscFree(nep->f));
295: PetscCall(PetscFree(nep->nrma));
296: if (nep->P) PetscCall(MatDestroyMatrices(nep->nt,&nep->P));
297: nep->nt = 0;
298: }
299: PetscFunctionReturn(PETSC_SUCCESS);
300: }
301: /*@
302: NEPReset - Resets the NEP context to the initial state (prior to setup)
303: and destroys any allocated Vecs and Mats.
305: Collective
307: Input Parameter:
308: . nep - eigensolver context obtained from NEPCreate()
310: Level: advanced
312: .seealso: NEPDestroy()
313: @*/
314: PetscErrorCode NEPReset(NEP nep)
315: {
316: PetscFunctionBegin;
318: if (!nep) PetscFunctionReturn(PETSC_SUCCESS);
319: PetscTryTypeMethod(nep,reset);
320: if (nep->refineksp) PetscCall(KSPReset(nep->refineksp));
321: PetscCall(NEPReset_Problem(nep));
322: PetscCall(BVDestroy(&nep->V));
323: PetscCall(BVDestroy(&nep->W));
324: PetscCall(VecDestroyVecs(nep->nwork,&nep->work));
325: PetscCall(MatDestroy(&nep->resolvent));
326: nep->nwork = 0;
327: nep->state = NEP_STATE_INITIAL;
328: PetscFunctionReturn(PETSC_SUCCESS);
329: }
331: /*@C
332: NEPDestroy - Destroys the NEP context.
334: Collective
336: Input Parameter:
337: . nep - eigensolver context obtained from NEPCreate()
339: Level: beginner
341: .seealso: NEPCreate(), NEPSetUp(), NEPSolve()
342: @*/
343: PetscErrorCode NEPDestroy(NEP *nep)
344: {
345: PetscFunctionBegin;
346: if (!*nep) PetscFunctionReturn(PETSC_SUCCESS);
348: if (--((PetscObject)(*nep))->refct > 0) { *nep = NULL; PetscFunctionReturn(PETSC_SUCCESS); }
349: PetscCall(NEPReset(*nep));
350: PetscTryTypeMethod(*nep,destroy);
351: if ((*nep)->eigr) PetscCall(PetscFree4((*nep)->eigr,(*nep)->eigi,(*nep)->errest,(*nep)->perm));
352: PetscCall(RGDestroy(&(*nep)->rg));
353: PetscCall(DSDestroy(&(*nep)->ds));
354: PetscCall(KSPDestroy(&(*nep)->refineksp));
355: PetscCall(PetscSubcommDestroy(&(*nep)->refinesubc));
356: PetscCall(PetscFree((*nep)->sc));
357: /* just in case the initial vectors have not been used */
358: PetscCall(SlepcBasisDestroy_Private(&(*nep)->nini,&(*nep)->IS));
359: if ((*nep)->convergeddestroy) PetscCall((*(*nep)->convergeddestroy)((*nep)->convergedctx));
360: PetscCall(NEPMonitorCancel(*nep));
361: PetscCall(PetscHeaderDestroy(nep));
362: PetscFunctionReturn(PETSC_SUCCESS);
363: }
365: /*@
366: NEPSetBV - Associates a basis vectors object to the nonlinear eigensolver.
368: Collective
370: Input Parameters:
371: + nep - eigensolver context obtained from NEPCreate()
372: - bv - the basis vectors object
374: Note:
375: Use NEPGetBV() to retrieve the basis vectors context (for example,
376: to free it at the end of the computations).
378: Level: advanced
380: .seealso: NEPGetBV()
381: @*/
382: PetscErrorCode NEPSetBV(NEP nep,BV bv)
383: {
384: PetscFunctionBegin;
387: PetscCheckSameComm(nep,1,bv,2);
388: PetscCall(PetscObjectReference((PetscObject)bv));
389: PetscCall(BVDestroy(&nep->V));
390: nep->V = bv;
391: PetscFunctionReturn(PETSC_SUCCESS);
392: }
394: /*@
395: NEPGetBV - Obtain the basis vectors object associated to the nonlinear
396: eigensolver object.
398: Not Collective
400: Input Parameters:
401: . nep - eigensolver context obtained from NEPCreate()
403: Output Parameter:
404: . bv - basis vectors context
406: Level: advanced
408: .seealso: NEPSetBV()
409: @*/
410: PetscErrorCode NEPGetBV(NEP nep,BV *bv)
411: {
412: PetscFunctionBegin;
414: PetscAssertPointer(bv,2);
415: if (!nep->V) {
416: PetscCall(BVCreate(PetscObjectComm((PetscObject)nep),&nep->V));
417: PetscCall(PetscObjectIncrementTabLevel((PetscObject)nep->V,(PetscObject)nep,0));
418: PetscCall(PetscObjectSetOptions((PetscObject)nep->V,((PetscObject)nep)->options));
419: }
420: *bv = nep->V;
421: PetscFunctionReturn(PETSC_SUCCESS);
422: }
424: /*@
425: NEPSetRG - Associates a region object to the nonlinear eigensolver.
427: Collective
429: Input Parameters:
430: + nep - eigensolver context obtained from NEPCreate()
431: - rg - the region object
433: Note:
434: Use NEPGetRG() to retrieve the region context (for example,
435: to free it at the end of the computations).
437: Level: advanced
439: .seealso: NEPGetRG()
440: @*/
441: PetscErrorCode NEPSetRG(NEP nep,RG rg)
442: {
443: PetscFunctionBegin;
445: if (rg) {
447: PetscCheckSameComm(nep,1,rg,2);
448: }
449: PetscCall(PetscObjectReference((PetscObject)rg));
450: PetscCall(RGDestroy(&nep->rg));
451: nep->rg = rg;
452: PetscFunctionReturn(PETSC_SUCCESS);
453: }
455: /*@
456: NEPGetRG - Obtain the region object associated to the
457: nonlinear eigensolver object.
459: Not Collective
461: Input Parameters:
462: . nep - eigensolver context obtained from NEPCreate()
464: Output Parameter:
465: . rg - region context
467: Level: advanced
469: .seealso: NEPSetRG()
470: @*/
471: PetscErrorCode NEPGetRG(NEP nep,RG *rg)
472: {
473: PetscFunctionBegin;
475: PetscAssertPointer(rg,2);
476: if (!nep->rg) {
477: PetscCall(RGCreate(PetscObjectComm((PetscObject)nep),&nep->rg));
478: PetscCall(PetscObjectIncrementTabLevel((PetscObject)nep->rg,(PetscObject)nep,0));
479: PetscCall(PetscObjectSetOptions((PetscObject)nep->rg,((PetscObject)nep)->options));
480: }
481: *rg = nep->rg;
482: PetscFunctionReturn(PETSC_SUCCESS);
483: }
485: /*@
486: NEPSetDS - Associates a direct solver object to the nonlinear eigensolver.
488: Collective
490: Input Parameters:
491: + nep - eigensolver context obtained from NEPCreate()
492: - ds - the direct solver object
494: Note:
495: Use NEPGetDS() to retrieve the direct solver context (for example,
496: to free it at the end of the computations).
498: Level: advanced
500: .seealso: NEPGetDS()
501: @*/
502: PetscErrorCode NEPSetDS(NEP nep,DS ds)
503: {
504: PetscFunctionBegin;
507: PetscCheckSameComm(nep,1,ds,2);
508: PetscCall(PetscObjectReference((PetscObject)ds));
509: PetscCall(DSDestroy(&nep->ds));
510: nep->ds = ds;
511: PetscFunctionReturn(PETSC_SUCCESS);
512: }
514: /*@
515: NEPGetDS - Obtain the direct solver object associated to the
516: nonlinear eigensolver object.
518: Not Collective
520: Input Parameters:
521: . nep - eigensolver context obtained from NEPCreate()
523: Output Parameter:
524: . ds - direct solver context
526: Level: advanced
528: .seealso: NEPSetDS()
529: @*/
530: PetscErrorCode NEPGetDS(NEP nep,DS *ds)
531: {
532: PetscFunctionBegin;
534: PetscAssertPointer(ds,2);
535: if (!nep->ds) {
536: PetscCall(DSCreate(PetscObjectComm((PetscObject)nep),&nep->ds));
537: PetscCall(PetscObjectIncrementTabLevel((PetscObject)nep->ds,(PetscObject)nep,0));
538: PetscCall(PetscObjectSetOptions((PetscObject)nep->ds,((PetscObject)nep)->options));
539: }
540: *ds = nep->ds;
541: PetscFunctionReturn(PETSC_SUCCESS);
542: }
544: /*@
545: NEPRefineGetKSP - Obtain the ksp object used by the eigensolver
546: object in the refinement phase.
548: Collective
550: Input Parameters:
551: . nep - eigensolver context obtained from NEPCreate()
553: Output Parameter:
554: . ksp - ksp context
556: Level: advanced
558: .seealso: NEPSetRefine()
559: @*/
560: PetscErrorCode NEPRefineGetKSP(NEP nep,KSP *ksp)
561: {
562: MPI_Comm comm;
564: PetscFunctionBegin;
566: PetscAssertPointer(ksp,2);
567: if (!nep->refineksp) {
568: if (nep->npart>1) {
569: /* Split in subcomunicators */
570: PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)nep),&nep->refinesubc));
571: PetscCall(PetscSubcommSetNumber(nep->refinesubc,nep->npart));
572: PetscCall(PetscSubcommSetType(nep->refinesubc,PETSC_SUBCOMM_CONTIGUOUS));
573: PetscCall(PetscSubcommGetChild(nep->refinesubc,&comm));
574: } else PetscCall(PetscObjectGetComm((PetscObject)nep,&comm));
575: PetscCall(KSPCreate(comm,&nep->refineksp));
576: PetscCall(PetscObjectIncrementTabLevel((PetscObject)nep->refineksp,(PetscObject)nep,0));
577: PetscCall(PetscObjectSetOptions((PetscObject)nep->refineksp,((PetscObject)nep)->options));
578: PetscCall(KSPSetOptionsPrefix(*ksp,((PetscObject)nep)->prefix));
579: PetscCall(KSPAppendOptionsPrefix(*ksp,"nep_refine_"));
580: PetscCall(KSPSetTolerances(nep->refineksp,SlepcDefaultTol(nep->rtol),PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT));
581: }
582: *ksp = nep->refineksp;
583: PetscFunctionReturn(PETSC_SUCCESS);
584: }
586: /*@
587: NEPSetTarget - Sets the value of the target.
589: Logically Collective
591: Input Parameters:
592: + nep - eigensolver context
593: - target - the value of the target
595: Options Database Key:
596: . -nep_target <scalar> - the value of the target
598: Notes:
599: The target is a scalar value used to determine the portion of the spectrum
600: of interest. It is used in combination with NEPSetWhichEigenpairs().
602: In the case of complex scalars, a complex value can be provided in the
603: command line with [+/-][realnumber][+/-]realnumberi with no spaces, e.g.
604: -nep_target 1.0+2.0i
606: Level: intermediate
608: .seealso: NEPGetTarget(), NEPSetWhichEigenpairs()
609: @*/
610: PetscErrorCode NEPSetTarget(NEP nep,PetscScalar target)
611: {
612: PetscFunctionBegin;
615: nep->target = target;
616: PetscFunctionReturn(PETSC_SUCCESS);
617: }
619: /*@
620: NEPGetTarget - Gets the value of the target.
622: Not Collective
624: Input Parameter:
625: . nep - eigensolver context
627: Output Parameter:
628: . target - the value of the target
630: Note:
631: If the target was not set by the user, then zero is returned.
633: Level: intermediate
635: .seealso: NEPSetTarget()
636: @*/
637: PetscErrorCode NEPGetTarget(NEP nep,PetscScalar* target)
638: {
639: PetscFunctionBegin;
641: PetscAssertPointer(target,2);
642: *target = nep->target;
643: PetscFunctionReturn(PETSC_SUCCESS);
644: }
646: /*@C
647: NEPSetFunction - Sets the function to compute the nonlinear Function T(lambda)
648: as well as the location to store the matrix.
650: Collective
652: Input Parameters:
653: + nep - the NEP context
654: . A - Function matrix
655: . B - preconditioner matrix (usually same as A)
656: . fun - Function evaluation routine (if NULL then NEP retains any
657: previously set value)
658: - ctx - [optional] user-defined context for private data for the Function
659: evaluation routine (may be NULL) (if NULL then NEP retains any
660: previously set value)
662: Calling sequence of fun:
663: $ PetscErrorCode fun(NEP nep,PetscScalar lambda,Mat T,Mat P,void *ctx)
664: + nep - the NEP context
665: . lambda - the scalar argument where T(.) must be evaluated
666: . T - matrix that will contain T(lambda)
667: . P - (optional) different matrix to build the preconditioner
668: - ctx - (optional) user-defined context, as set by NEPSetFunction()
670: Level: beginner
672: .seealso: NEPGetFunction(), NEPSetJacobian()
673: @*/
674: PetscErrorCode NEPSetFunction(NEP nep,Mat A,Mat B,PetscErrorCode (*fun)(NEP nep,PetscScalar lambda,Mat T,Mat P,void *ctx),void *ctx)
675: {
676: PetscFunctionBegin;
680: if (A) PetscCheckSameComm(nep,1,A,2);
681: if (B) PetscCheckSameComm(nep,1,B,3);
683: if (nep->state) PetscCall(NEPReset(nep));
684: else if (nep->fui && nep->fui!=NEP_USER_INTERFACE_CALLBACK) PetscCall(NEPReset_Problem(nep));
686: if (fun) nep->computefunction = fun;
687: if (ctx) nep->functionctx = ctx;
688: if (A) {
689: PetscCall(PetscObjectReference((PetscObject)A));
690: PetscCall(MatDestroy(&nep->function));
691: nep->function = A;
692: }
693: if (B) {
694: PetscCall(PetscObjectReference((PetscObject)B));
695: PetscCall(MatDestroy(&nep->function_pre));
696: nep->function_pre = B;
697: }
698: nep->fui = NEP_USER_INTERFACE_CALLBACK;
699: nep->state = NEP_STATE_INITIAL;
700: PetscFunctionReturn(PETSC_SUCCESS);
701: }
703: /*@C
704: NEPGetFunction - Returns the Function matrix and optionally the user
705: provided context for evaluating the Function.
707: Not Collective
709: Input Parameter:
710: . nep - the nonlinear eigensolver context
712: Output Parameters:
713: + A - location to stash Function matrix (or NULL)
714: . B - location to stash preconditioner matrix (or NULL)
715: . fun - location to put Function function (or NULL)
716: - ctx - location to stash Function context (or NULL)
718: Level: advanced
720: .seealso: NEPSetFunction()
721: @*/
722: PetscErrorCode NEPGetFunction(NEP nep,Mat *A,Mat *B,PetscErrorCode (**fun)(NEP,PetscScalar,Mat,Mat,void*),void **ctx)
723: {
724: PetscFunctionBegin;
726: NEPCheckCallback(nep,1);
727: if (A) *A = nep->function;
728: if (B) *B = nep->function_pre;
729: if (fun) *fun = nep->computefunction;
730: if (ctx) *ctx = nep->functionctx;
731: PetscFunctionReturn(PETSC_SUCCESS);
732: }
734: /*@C
735: NEPSetJacobian - Sets the function to compute the Jacobian T'(lambda) as well
736: as the location to store the matrix.
738: Collective
740: Input Parameters:
741: + nep - the NEP context
742: . A - Jacobian matrix
743: . jac - Jacobian evaluation routine (if NULL then NEP retains any
744: previously set value)
745: - ctx - [optional] user-defined context for private data for the Jacobian
746: evaluation routine (may be NULL) (if NULL then NEP retains any
747: previously set value)
749: Calling sequence of jac:
750: $ PetscErrorCode jac(NEP nep,PetscScalar lambda,Mat J,void *ctx)
751: + nep - the NEP context
752: . lambda - the scalar argument where T'(.) must be evaluated
753: . J - matrix that will contain T'(lambda)
754: - ctx - (optional) user-defined context, as set by NEPSetJacobian()
756: Level: beginner
758: .seealso: NEPSetFunction(), NEPGetJacobian()
759: @*/
760: PetscErrorCode NEPSetJacobian(NEP nep,Mat A,PetscErrorCode (*jac)(NEP nep,PetscScalar lambda,Mat J,void *ctx),void *ctx)
761: {
762: PetscFunctionBegin;
765: if (A) PetscCheckSameComm(nep,1,A,2);
767: if (nep->state) PetscCall(NEPReset(nep));
768: else if (nep->fui && nep->fui!=NEP_USER_INTERFACE_CALLBACK) PetscCall(NEPReset_Problem(nep));
770: if (jac) nep->computejacobian = jac;
771: if (ctx) nep->jacobianctx = ctx;
772: if (A) {
773: PetscCall(PetscObjectReference((PetscObject)A));
774: PetscCall(MatDestroy(&nep->jacobian));
775: nep->jacobian = A;
776: }
777: nep->fui = NEP_USER_INTERFACE_CALLBACK;
778: nep->state = NEP_STATE_INITIAL;
779: PetscFunctionReturn(PETSC_SUCCESS);
780: }
782: /*@C
783: NEPGetJacobian - Returns the Jacobian matrix and optionally the user
784: provided routine and context for evaluating the Jacobian.
786: Not Collective
788: Input Parameter:
789: . nep - the nonlinear eigensolver context
791: Output Parameters:
792: + A - location to stash Jacobian matrix (or NULL)
793: . jac - location to put Jacobian function (or NULL)
794: - ctx - location to stash Jacobian context (or NULL)
796: Level: advanced
798: .seealso: NEPSetJacobian()
799: @*/
800: PetscErrorCode NEPGetJacobian(NEP nep,Mat *A,PetscErrorCode (**jac)(NEP,PetscScalar,Mat,void*),void **ctx)
801: {
802: PetscFunctionBegin;
804: NEPCheckCallback(nep,1);
805: if (A) *A = nep->jacobian;
806: if (jac) *jac = nep->computejacobian;
807: if (ctx) *ctx = nep->jacobianctx;
808: PetscFunctionReturn(PETSC_SUCCESS);
809: }
811: /*@
812: NEPSetSplitOperator - Sets the operator of the nonlinear eigenvalue problem
813: in split form.
815: Collective
817: Input Parameters:
818: + nep - the nonlinear eigensolver context
819: . nt - number of terms in the split form
820: . A - array of matrices
821: . f - array of functions
822: - str - structure flag for matrices
824: Notes:
825: The nonlinear operator is written as T(lambda) = sum_i A_i*f_i(lambda),
826: for i=1,...,n. The derivative T'(lambda) can be obtained using the
827: derivatives of f_i.
829: The structure flag provides information about A_i's nonzero pattern
830: (see MatStructure enum). If all matrices have the same pattern, then
831: use SAME_NONZERO_PATTERN. If the patterns are different but contained
832: in the pattern of the first one, then use SUBSET_NONZERO_PATTERN. If
833: patterns are known to be different, use DIFFERENT_NONZERO_PATTERN.
834: If set to UNKNOWN_NONZERO_PATTERN, the patterns will be compared to
835: determine if they are equal.
837: This function must be called before NEPSetUp(). If it is called again
838: after NEPSetUp() then the NEP object is reset.
840: Level: beginner
842: .seealso: NEPGetSplitOperatorTerm(), NEPGetSplitOperatorInfo(), NEPSetSplitPreconditioner()
843: @*/
844: PetscErrorCode NEPSetSplitOperator(NEP nep,PetscInt nt,Mat A[],FN f[],MatStructure str)
845: {
846: PetscInt i,n=0,m,m0=0,mloc,nloc,mloc0=0;
848: PetscFunctionBegin;
851: PetscCheck(nt>0,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more terms, you have %" PetscInt_FMT,nt);
852: PetscAssertPointer(A,3);
853: PetscAssertPointer(f,4);
856: for (i=0;i<nt;i++) {
858: PetscCheckSameComm(nep,1,A[i],3);
860: PetscCheckSameComm(nep,1,f[i],4);
861: PetscCall(MatGetSize(A[i],&m,&n));
862: PetscCall(MatGetLocalSize(A[i],&mloc,&nloc));
863: PetscCheck(m==n,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONG,"A[%" PetscInt_FMT "] is a non-square matrix (%" PetscInt_FMT " rows, %" PetscInt_FMT " cols)",i,m,n);
864: PetscCheck(mloc==nloc,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONG,"A[%" PetscInt_FMT "] does not have equal row and column local sizes (%" PetscInt_FMT ", %" PetscInt_FMT ")",i,mloc,nloc);
865: if (!i) { m0 = m; mloc0 = mloc; }
866: PetscCheck(m==m0,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_INCOMP,"Dimensions of A[%" PetscInt_FMT "] do not match with previous matrices (%" PetscInt_FMT ", %" PetscInt_FMT ")",i,m,m0);
867: PetscCheck(mloc==mloc0,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_INCOMP,"Local dimensions of A[%" PetscInt_FMT "] do not match with previous matrices (%" PetscInt_FMT ", %" PetscInt_FMT ")",i,mloc,mloc0);
868: PetscCall(PetscObjectReference((PetscObject)A[i]));
869: PetscCall(PetscObjectReference((PetscObject)f[i]));
870: }
872: if (nep->state && (n!=nep->n || nloc!=nep->nloc)) PetscCall(NEPReset(nep));
873: else PetscCall(NEPReset_Problem(nep));
875: /* allocate space and copy matrices and functions */
876: PetscCall(PetscMalloc1(nt,&nep->A));
877: for (i=0;i<nt;i++) nep->A[i] = A[i];
878: PetscCall(PetscMalloc1(nt,&nep->f));
879: for (i=0;i<nt;i++) nep->f[i] = f[i];
880: PetscCall(PetscCalloc1(nt,&nep->nrma));
881: nep->nt = nt;
882: nep->mstr = str;
883: nep->fui = NEP_USER_INTERFACE_SPLIT;
884: nep->state = NEP_STATE_INITIAL;
885: PetscFunctionReturn(PETSC_SUCCESS);
886: }
888: /*@
889: NEPGetSplitOperatorTerm - Gets the matrices and functions associated with
890: the nonlinear operator in split form.
892: Not Collective
894: Input Parameters:
895: + nep - the nonlinear eigensolver context
896: - k - the index of the requested term (starting in 0)
898: Output Parameters:
899: + A - the matrix of the requested term
900: - f - the function of the requested term
902: Level: intermediate
904: .seealso: NEPSetSplitOperator(), NEPGetSplitOperatorInfo()
905: @*/
906: PetscErrorCode NEPGetSplitOperatorTerm(NEP nep,PetscInt k,Mat *A,FN *f)
907: {
908: PetscFunctionBegin;
911: NEPCheckSplit(nep,1);
912: PetscCheck(k>=0 && k<nep->nt,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %" PetscInt_FMT,nep->nt-1);
913: if (A) *A = nep->A[k];
914: if (f) *f = nep->f[k];
915: PetscFunctionReturn(PETSC_SUCCESS);
916: }
918: /*@
919: NEPGetSplitOperatorInfo - Returns the number of terms of the split form of
920: the nonlinear operator, as well as the structure flag for matrices.
922: Not Collective
924: Input Parameter:
925: . nep - the nonlinear eigensolver context
927: Output Parameters:
928: + n - the number of terms passed in NEPSetSplitOperator()
929: - str - the matrix structure flag passed in NEPSetSplitOperator()
931: Level: intermediate
933: .seealso: NEPSetSplitOperator(), NEPGetSplitOperatorTerm()
934: @*/
935: PetscErrorCode NEPGetSplitOperatorInfo(NEP nep,PetscInt *n,MatStructure *str)
936: {
937: PetscFunctionBegin;
939: NEPCheckSplit(nep,1);
940: if (n) *n = nep->nt;
941: if (str) *str = nep->mstr;
942: PetscFunctionReturn(PETSC_SUCCESS);
943: }
945: /*@
946: NEPSetSplitPreconditioner - Sets an operator in split form from which
947: to build the preconditioner to be used when solving the nonlinear
948: eigenvalue problem in split form.
950: Collective
952: Input Parameters:
953: + nep - the nonlinear eigensolver context
954: . ntp - number of terms in the split preconditioner
955: . P - array of matrices
956: - strp - structure flag for matrices
958: Notes:
959: The matrix for the preconditioner is expressed as P(lambda) =
960: sum_i P_i*f_i(lambda), for i=1,...,n, where the f_i functions
961: are the same as in NEPSetSplitOperator(). It is not necessary to call
962: this function. If it is not invoked, then the preconditioner is
963: built from T(lambda), i.e., both matrices and functions passed in
964: NEPSetSplitOperator().
966: The structure flag provides information about P_i's nonzero pattern
967: in the same way as in NEPSetSplitOperator().
969: If the functions defining the preconditioner operator were different
970: from the ones given in NEPSetSplitOperator(), then the split form
971: cannot be used. Use the callback interface instead.
973: Use ntp=0 to reset a previously set split preconditioner.
975: Level: advanced
977: .seealso: NEPGetSplitPreconditionerTerm(), NEPGetSplitPreconditionerInfo(), NEPSetSplitOperator()
978: @*/
979: PetscErrorCode NEPSetSplitPreconditioner(NEP nep,PetscInt ntp,Mat P[],MatStructure strp)
980: {
981: PetscInt i,n=0,m,m0=0,mloc,nloc,mloc0=0;
983: PetscFunctionBegin;
986: PetscCheck(ntp>=0,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Negative value of ntp = %" PetscInt_FMT,ntp);
987: PetscCheck(nep->fui==NEP_USER_INTERFACE_SPLIT,PetscObjectComm((PetscObject)nep),PETSC_ERR_ORDER,"Must call NEPSetSplitOperator first");
988: PetscCheck(ntp==0 || nep->nt==ntp,PetscObjectComm((PetscObject)nep),PETSC_ERR_SUP,"The number of terms must be the same as in NEPSetSplitOperator()");
989: if (ntp) PetscAssertPointer(P,3);
992: for (i=0;i<ntp;i++) {
994: PetscCheckSameComm(nep,1,P[i],3);
995: PetscCall(MatGetSize(P[i],&m,&n));
996: PetscCall(MatGetLocalSize(P[i],&mloc,&nloc));
997: PetscCheck(m==n,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONG,"P[%" PetscInt_FMT "] is a non-square matrix (%" PetscInt_FMT " rows, %" PetscInt_FMT " cols)",i,m,n);
998: PetscCheck(mloc==nloc,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONG,"P[%" PetscInt_FMT "] does not have equal row and column local sizes (%" PetscInt_FMT ", %" PetscInt_FMT ")",i,mloc,nloc);
999: if (!i) { m0 = m; mloc0 = mloc; }
1000: PetscCheck(m==m0,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_INCOMP,"Dimensions of P[%" PetscInt_FMT "] do not match with previous matrices (%" PetscInt_FMT ", %" PetscInt_FMT ")",i,m,m0);
1001: PetscCheck(mloc==mloc0,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_INCOMP,"Local dimensions of P[%" PetscInt_FMT "] do not match with previous matrices (%" PetscInt_FMT ", %" PetscInt_FMT ")",i,mloc,mloc0);
1002: PetscCall(PetscObjectReference((PetscObject)P[i]));
1003: }
1005: PetscCheck(!nep->state,PetscObjectComm((PetscObject)nep),PETSC_ERR_ORDER,"To call this function after NEPSetUp(), you must call NEPSetSplitOperator() again");
1006: if (nep->P) PetscCall(MatDestroyMatrices(nep->nt,&nep->P));
1008: /* allocate space and copy matrices */
1009: if (ntp) {
1010: PetscCall(PetscMalloc1(ntp,&nep->P));
1011: for (i=0;i<ntp;i++) nep->P[i] = P[i];
1012: }
1013: nep->mstrp = strp;
1014: nep->state = NEP_STATE_INITIAL;
1015: PetscFunctionReturn(PETSC_SUCCESS);
1016: }
1018: /*@
1019: NEPGetSplitPreconditionerTerm - Gets the matrices associated with
1020: the split preconditioner.
1022: Not Collective
1024: Input Parameters:
1025: + nep - the nonlinear eigensolver context
1026: - k - the index of the requested term (starting in 0)
1028: Output Parameter:
1029: . P - the matrix of the requested term
1031: Level: advanced
1033: .seealso: NEPSetSplitPreconditioner(), NEPGetSplitPreconditionerInfo()
1034: @*/
1035: PetscErrorCode NEPGetSplitPreconditionerTerm(NEP nep,PetscInt k,Mat *P)
1036: {
1037: PetscFunctionBegin;
1040: PetscAssertPointer(P,3);
1041: NEPCheckSplit(nep,1);
1042: PetscCheck(k>=0 && k<nep->nt,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %" PetscInt_FMT,nep->nt-1);
1043: PetscCheck(nep->P,PetscObjectComm((PetscObject)nep),PETSC_ERR_ORDER,"You have not called NEPSetSplitPreconditioner()");
1044: *P = nep->P[k];
1045: PetscFunctionReturn(PETSC_SUCCESS);
1046: }
1048: /*@
1049: NEPGetSplitPreconditionerInfo - Returns the number of terms of the split
1050: preconditioner, as well as the structure flag for matrices.
1052: Not Collective
1054: Input Parameter:
1055: . nep - the nonlinear eigensolver context
1057: Output Parameters:
1058: + n - the number of terms passed in NEPSetSplitPreconditioner()
1059: - strp - the matrix structure flag passed in NEPSetSplitPreconditioner()
1061: Level: advanced
1063: .seealso: NEPSetSplitPreconditioner(), NEPGetSplitPreconditionerTerm()
1064: @*/
1065: PetscErrorCode NEPGetSplitPreconditionerInfo(NEP nep,PetscInt *n,MatStructure *strp)
1066: {
1067: PetscFunctionBegin;
1069: NEPCheckSplit(nep,1);
1070: if (n) *n = nep->P? nep->nt: 0;
1071: if (strp) *strp = nep->mstrp;
1072: PetscFunctionReturn(PETSC_SUCCESS);
1073: }