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: PEP routines related to problem setup
12: */
14: #include <slepc/private/pepimpl.h> 16: /*
17: Let the solver choose the ST type that should be used by default,
18: otherwise set it to SHIFT.
19: This is called at PEPSetFromOptions (before STSetFromOptions)
20: and also at PEPSetUp (in case PEPSetFromOptions was not called).
21: */
22: PetscErrorCode PEPSetDefaultST(PEP pep) 23: {
24: if (pep->ops->setdefaultst) (*pep->ops->setdefaultst)(pep);
25: if (!((PetscObject)pep->st)->type_name) STSetType(pep->st,STSHIFT);
26: PetscFunctionReturn(0);
27: }
29: /*
30: This is used in Q-Arnoldi and STOAR to set the transform flag by
31: default, otherwise the user has to explicitly run with -st_transform
32: */
33: PetscErrorCode PEPSetDefaultST_Transform(PEP pep) 34: {
35: STSetTransform(pep->st,PETSC_TRUE);
36: PetscFunctionReturn(0);
37: }
39: /*@
40: PEPSetUp - Sets up all the internal data structures necessary for the
41: execution of the PEP solver.
43: Collective on pep
45: Input Parameter:
46: . pep - solver context
48: Notes:
49: This function need not be called explicitly in most cases, since PEPSolve()
50: calls it. It can be useful when one wants to measure the set-up time
51: separately from the solve time.
53: Level: developer
55: .seealso: PEPCreate(), PEPSolve(), PEPDestroy()
56: @*/
57: PetscErrorCode PEPSetUp(PEP pep) 58: {
59: SlepcSC sc;
60: PetscBool istrivial,flg;
61: PetscInt k;
62: KSP ksp;
63: PC pc;
64: PetscMPIInt size;
65: MatSolverType stype;
68: if (pep->state) PetscFunctionReturn(0);
69: PetscLogEventBegin(PEP_SetUp,pep,0,0,0);
71: /* reset the convergence flag from the previous solves */
72: pep->reason = PEP_CONVERGED_ITERATING;
74: /* set default solver type (PEPSetFromOptions was not called) */
75: if (!((PetscObject)pep)->type_name) PEPSetType(pep,PEPTOAR);
76: if (!pep->st) PEPGetST(pep,&pep->st);
77: PEPSetDefaultST(pep);
78: if (!pep->ds) PEPGetDS(pep,&pep->ds);
79: if (!pep->rg) PEPGetRG(pep,&pep->rg);
80: if (!((PetscObject)pep->rg)->type_name) RGSetType(pep->rg,RGINTERVAL);
82: /* check matrices, transfer them to ST */
84: STSetMatrices(pep->st,pep->nmat,pep->A);
86: /* set problem dimensions */
87: MatGetSize(pep->A[0],&pep->n,NULL);
88: MatGetLocalSize(pep->A[0],&pep->nloc,NULL);
90: /* set default problem type */
91: if (!pep->problem_type) PEPSetProblemType(pep,PEP_GENERAL);
92: if (pep->nev > (pep->nmat-1)*pep->n) pep->nev = (pep->nmat-1)*pep->n;
93: if (pep->ncv > (pep->nmat-1)*pep->n) pep->ncv = (pep->nmat-1)*pep->n;
95: /* check consistency of refinement options */
96: if (pep->refine) {
97: if (!pep->scheme) { /* set default scheme */
98: PEPRefineGetKSP(pep,&ksp);
99: KSPGetPC(ksp,&pc);
100: PetscObjectTypeCompare((PetscObject)ksp,KSPPREONLY,&flg);
101: if (flg) PetscObjectTypeCompareAny((PetscObject)pc,&flg,PCLU,PCCHOLESKY,"");
102: pep->scheme = flg? PEP_REFINE_SCHEME_MBE: PEP_REFINE_SCHEME_SCHUR;
103: }
104: if (pep->scheme==PEP_REFINE_SCHEME_MBE) {
105: PEPRefineGetKSP(pep,&ksp);
106: KSPGetPC(ksp,&pc);
107: PetscObjectTypeCompare((PetscObject)ksp,KSPPREONLY,&flg);
108: if (flg) PetscObjectTypeCompareAny((PetscObject)pc,&flg,PCLU,PCCHOLESKY,"");
110: MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);
111: if (size>1) { /* currently selected PC is a factorization */
112: PCFactorGetMatSolverType(pc,&stype);
113: PetscStrcmp(stype,MATSOLVERPETSC,&flg);
115: }
116: }
117: if (pep->scheme==PEP_REFINE_SCHEME_SCHUR) {
119: }
120: }
121: /* call specific solver setup */
122: (*pep->ops->setup)(pep);
124: /* set tolerance if not yet set */
125: if (pep->tol==PETSC_DEFAULT) pep->tol = SLEPC_DEFAULT_TOL;
126: if (pep->refine) {
127: if (pep->rtol==PETSC_DEFAULT) pep->rtol = PetscMax(pep->tol/1000,PETSC_MACHINE_EPSILON);
128: if (pep->rits==PETSC_DEFAULT) pep->rits = (pep->refine==PEP_REFINE_SIMPLE)? 10: 1;
129: }
131: /* set default extraction */
132: if (!pep->extract) {
133: pep->extract = (pep->basis==PEP_BASIS_MONOMIAL)? PEP_EXTRACT_NORM: PEP_EXTRACT_NONE;
134: }
136: /* fill sorting criterion context */
137: switch (pep->which) {
138: case PEP_LARGEST_MAGNITUDE:
139: pep->sc->comparison = SlepcCompareLargestMagnitude;
140: pep->sc->comparisonctx = NULL;
141: break;
142: case PEP_SMALLEST_MAGNITUDE:
143: pep->sc->comparison = SlepcCompareSmallestMagnitude;
144: pep->sc->comparisonctx = NULL;
145: break;
146: case PEP_LARGEST_REAL:
147: pep->sc->comparison = SlepcCompareLargestReal;
148: pep->sc->comparisonctx = NULL;
149: break;
150: case PEP_SMALLEST_REAL:
151: pep->sc->comparison = SlepcCompareSmallestReal;
152: pep->sc->comparisonctx = NULL;
153: break;
154: case PEP_LARGEST_IMAGINARY:
155: pep->sc->comparison = SlepcCompareLargestImaginary;
156: pep->sc->comparisonctx = NULL;
157: break;
158: case PEP_SMALLEST_IMAGINARY:
159: pep->sc->comparison = SlepcCompareSmallestImaginary;
160: pep->sc->comparisonctx = NULL;
161: break;
162: case PEP_TARGET_MAGNITUDE:
163: pep->sc->comparison = SlepcCompareTargetMagnitude;
164: pep->sc->comparisonctx = &pep->target;
165: break;
166: case PEP_TARGET_REAL:
167: pep->sc->comparison = SlepcCompareTargetReal;
168: pep->sc->comparisonctx = &pep->target;
169: break;
170: case PEP_TARGET_IMAGINARY:
171: #if defined(PETSC_USE_COMPLEX)
172: pep->sc->comparison = SlepcCompareTargetImaginary;
173: pep->sc->comparisonctx = &pep->target;
174: #endif
175: break;
176: case PEP_ALL:
177: pep->sc->comparison = SlepcCompareSmallestReal;
178: pep->sc->comparisonctx = NULL;
179: break;
180: case PEP_WHICH_USER:
181: break;
182: }
183: pep->sc->map = NULL;
184: pep->sc->mapobj = NULL;
186: /* fill sorting criterion for DS */
187: if (pep->which!=PEP_ALL) {
188: DSGetSlepcSC(pep->ds,&sc);
189: RGIsTrivial(pep->rg,&istrivial);
190: sc->rg = istrivial? NULL: pep->rg;
191: sc->comparison = pep->sc->comparison;
192: sc->comparisonctx = pep->sc->comparisonctx;
193: sc->map = SlepcMap_ST;
194: sc->mapobj = (PetscObject)pep->st;
195: }
196: /* setup ST */
197: STSetUp(pep->st);
199: /* compute matrix coefficients */
200: STGetTransform(pep->st,&flg);
201: if (!flg) {
202: if (pep->which!=PEP_ALL && pep->solvematcoeffs) STMatSetUp(pep->st,1.0,pep->solvematcoeffs);
203: } else {
205: }
207: /* compute scale factor if no set by user */
208: PEPComputeScaleFactor(pep);
210: /* build balancing matrix if required */
211: if (pep->scale==PEP_SCALE_DIAGONAL || pep->scale==PEP_SCALE_BOTH) {
212: if (!pep->Dl) {
213: BVCreateVec(pep->V,&pep->Dl);
214: PetscLogObjectParent((PetscObject)pep,(PetscObject)pep->Dl);
215: }
216: if (!pep->Dr) {
217: BVCreateVec(pep->V,&pep->Dr);
218: PetscLogObjectParent((PetscObject)pep,(PetscObject)pep->Dr);
219: }
220: PEPBuildDiagonalScaling(pep);
221: }
223: /* process initial vectors */
224: if (pep->nini<0) {
225: k = -pep->nini;
227: BVInsertVecs(pep->V,0,&k,pep->IS,PETSC_TRUE);
228: SlepcBasisDestroy_Private(&pep->nini,&pep->IS);
229: pep->nini = k;
230: }
231: PetscLogEventEnd(PEP_SetUp,pep,0,0,0);
232: pep->state = PEP_STATE_SETUP;
233: PetscFunctionReturn(0);
234: }
236: /*@
237: PEPSetOperators - Sets the coefficient matrices associated with the polynomial
238: eigenvalue problem.
240: Collective on pep
242: Input Parameters:
243: + pep - the eigenproblem solver context
244: . nmat - number of matrices in array A
245: - A - the array of matrices associated with the eigenproblem
247: Notes:
248: The polynomial eigenproblem is defined as P(l)*x=0, where l is
249: the eigenvalue, x is the eigenvector, and P(l) is defined as
250: P(l) = A_0 + l*A_1 + ... + l^d*A_d, with d=nmat-1 (the degree of P).
251: For non-monomial bases, this expression is different.
253: Level: beginner
255: .seealso: PEPSolve(), PEPGetOperators(), PEPGetNumMatrices(), PEPSetBasis()
256: @*/
257: PetscErrorCode PEPSetOperators(PEP pep,PetscInt nmat,Mat A[])258: {
259: PetscInt i,n=0,m,m0=0,mloc,nloc,mloc0=0;
267: for (i=0;i<nmat;i++) {
270: MatGetSize(A[i],&m,&n);
271: MatGetLocalSize(A[i],&mloc,&nloc);
274: if (!i) { m0 = m; mloc0 = mloc; }
277: PetscObjectReference((PetscObject)A[i]);
278: }
280: if (pep->state && (n!=pep->n || nloc!=pep->nloc)) PEPReset(pep);
281: else if (pep->nmat) {
282: MatDestroyMatrices(pep->nmat,&pep->A);
283: PetscFree2(pep->pbc,pep->nrma);
284: PetscFree(pep->solvematcoeffs);
285: }
287: PetscMalloc1(nmat,&pep->A);
288: PetscCalloc2(3*nmat,&pep->pbc,nmat,&pep->nrma);
289: PetscLogObjectMemory((PetscObject)pep,nmat*sizeof(Mat)+4*nmat*sizeof(PetscReal));
290: for (i=0;i<nmat;i++) {
291: pep->A[i] = A[i];
292: pep->pbc[i] = 1.0; /* default to monomial basis */
293: }
294: pep->nmat = nmat;
295: pep->state = PEP_STATE_INITIAL;
296: PetscFunctionReturn(0);
297: }
299: /*@
300: PEPGetOperators - Gets the matrices associated with the polynomial eigensystem.
302: Not collective, though parallel Mats are returned if the PEP is parallel
304: Input Parameters:
305: + pep - the PEP context
306: - k - the index of the requested matrix (starting in 0)
308: Output Parameter:
309: . A - the requested matrix
311: Level: intermediate
313: .seealso: PEPSolve(), PEPSetOperators(), PEPGetNumMatrices()
314: @*/
315: PetscErrorCode PEPGetOperators(PEP pep,PetscInt k,Mat *A)316: {
320: *A = pep->A[k];
321: PetscFunctionReturn(0);
322: }
324: /*@
325: PEPGetNumMatrices - Returns the number of matrices stored in the PEP.
327: Not collective
329: Input Parameter:
330: . pep - the PEP context
332: Output Parameters:
333: . nmat - the number of matrices passed in PEPSetOperators()
335: Level: intermediate
337: .seealso: PEPSetOperators()
338: @*/
339: PetscErrorCode PEPGetNumMatrices(PEP pep,PetscInt *nmat)340: {
343: *nmat = pep->nmat;
344: PetscFunctionReturn(0);
345: }
347: /*@C
348: PEPSetInitialSpace - Specify a basis of vectors that constitute the initial
349: space, that is, the subspace from which the solver starts to iterate.
351: Collective on pep
353: Input Parameters:
354: + pep - the polynomial eigensolver context
355: . n - number of vectors
356: - is - set of basis vectors of the initial space
358: Notes:
359: Some solvers start to iterate on a single vector (initial vector). In that case,
360: the other vectors are ignored.
362: These vectors do not persist from one PEPSolve() call to the other, so the
363: initial space should be set every time.
365: The vectors do not need to be mutually orthonormal, since they are explicitly
366: orthonormalized internally.
368: Common usage of this function is when the user can provide a rough approximation
369: of the wanted eigenspace. Then, convergence may be faster.
371: Level: intermediate
373: .seealso: PEPSetUp()
374: @*/
375: PetscErrorCode PEPSetInitialSpace(PEP pep,PetscInt n,Vec is[])376: {
380: if (n>0) {
383: }
384: SlepcBasisReference_Private(n,is,&pep->nini,&pep->IS);
385: if (n>0) pep->state = PEP_STATE_INITIAL;
386: PetscFunctionReturn(0);
387: }
389: /*
390: PEPSetDimensions_Default - Set reasonable values for ncv, mpd if not set
391: by the user. This is called at setup.
392: */
393: PetscErrorCode PEPSetDimensions_Default(PEP pep,PetscInt nev,PetscInt *ncv,PetscInt *mpd)394: {
395: PetscBool krylov;
396: PetscInt dim;
398: PetscObjectTypeCompareAny((PetscObject)pep,&krylov,PEPTOAR,PEPSTOAR,PEPQARNOLDI,"");
399: dim = (pep->nmat-1)*pep->n;
400: if (*ncv!=PETSC_DEFAULT) { /* ncv set */
401: if (krylov) {
403: } else {
405: }
406: } else if (*mpd!=PETSC_DEFAULT) { /* mpd set */
407: *ncv = PetscMin(dim,nev+(*mpd));
408: } else { /* neither set: defaults depend on nev being small or large */
409: if (nev<500) *ncv = PetscMin(dim,PetscMax(2*nev,nev+15));
410: else {
411: *mpd = 500;
412: *ncv = PetscMin(dim,nev+(*mpd));
413: }
414: }
415: if (*mpd==PETSC_DEFAULT) *mpd = *ncv;
416: PetscFunctionReturn(0);
417: }
419: /*@
420: PEPAllocateSolution - Allocate memory storage for common variables such
421: as eigenvalues and eigenvectors.
423: Collective on pep
425: Input Parameters:
426: + pep - eigensolver context
427: - extra - number of additional positions, used for methods that require a
428: working basis slightly larger than ncv
430: Developer Notes:
431: This is SLEPC_EXTERN because it may be required by user plugin PEP432: implementations.
434: Level: developer
436: .seealso: PEPSetUp()
437: @*/
438: PetscErrorCode PEPAllocateSolution(PEP pep,PetscInt extra)439: {
440: PetscInt oldsize,newc,requested,requestedbv;
441: PetscLogDouble cnt;
442: Vec t;
444: requested = (pep->lineariz? pep->ncv: pep->ncv*(pep->nmat-1)) + extra;
445: requestedbv = pep->ncv + extra;
447: /* oldsize is zero if this is the first time setup is called */
448: BVGetSizes(pep->V,NULL,NULL,&oldsize);
450: /* allocate space for eigenvalues and friends */
451: if (requested != oldsize || !pep->eigr) {
452: PetscFree4(pep->eigr,pep->eigi,pep->errest,pep->perm);
453: PetscMalloc4(requested,&pep->eigr,requested,&pep->eigi,requested,&pep->errest,requested,&pep->perm);
454: newc = PetscMax(0,requested-oldsize);
455: cnt = 2*newc*sizeof(PetscScalar) + newc*sizeof(PetscReal) + newc*sizeof(PetscInt);
456: PetscLogObjectMemory((PetscObject)pep,cnt);
457: }
459: /* allocate V */
460: if (!pep->V) PEPGetBV(pep,&pep->V);
461: if (!oldsize) {
462: if (!((PetscObject)(pep->V))->type_name) BVSetType(pep->V,BVSVEC);
463: STMatCreateVecsEmpty(pep->st,&t,NULL);
464: BVSetSizesFromVec(pep->V,t,requestedbv);
465: VecDestroy(&t);
466: } else BVResize(pep->V,requestedbv,PETSC_FALSE);
467: PetscFunctionReturn(0);
468: }