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: NEPType152: @*/
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: }