Line data Source code
1 : /*
2 : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3 : SLEPc - Scalable Library for Eigenvalue Problem Computations
4 : Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
5 :
6 : This file is part of SLEPc.
7 : SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8 : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9 : */
10 : /*
11 : This file implements a wrapper to eigensolvers in EVSL.
12 : */
13 :
14 : #include <slepc/private/epsimpl.h> /*I "slepceps.h" I*/
15 : #include <evsl.h>
16 :
17 : #define PetscCallEVSL(func, ...) do { \
18 : PetscStackPushExternal(PetscStringize(func)); \
19 : int evsl_ierr_ = func(__VA_ARGS__); \
20 : PetscStackPop; \
21 : PetscCheck(!evsl_ierr_,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error calling %s: error code %d",PetscStringize(func(__VA_ARGS__)),evsl_ierr_); \
22 : } while (0)
23 :
24 : typedef struct {
25 : PetscBool initialized;
26 : Mat A; /* problem matrix */
27 : Vec x,y; /* auxiliary vectors */
28 : PetscReal *sli; /* slice bounds */
29 : PetscInt nev; /* approximate number of wanted eigenvalues in each slice */
30 : PetscLayout map; /* used to distribute slices among MPI processes */
31 : PetscBool estimrange; /* the filter range was not set by the user */
32 : /* user parameters */
33 : PetscInt nslices; /* number of slices */
34 : PetscReal lmin,lmax; /* numerical range (min and max eigenvalue) */
35 : EPSEVSLDOSMethod dos; /* DOS method, either KPM or Lanczos */
36 : PetscInt nvec; /* number of sample vectors used for DOS */
37 : PetscInt deg; /* polynomial degree used for DOS (KPM only) */
38 : PetscInt steps; /* number of Lanczos steps used for DOS (Lanczos only) */
39 : PetscInt npoints; /* number of sample points used for DOS (Lanczos only) */
40 : PetscInt max_deg; /* maximum degree allowed for the polynomial */
41 : PetscReal thresh; /* threshold for accepting polynomial */
42 : EPSEVSLDamping damping; /* type of damping (for polynomial and for DOS-KPM) */
43 : } EPS_EVSL;
44 :
45 497050 : static void AMatvec_EVSL(double *xa,double *ya,void *data)
46 : {
47 497050 : EPS_EVSL *ctx = (EPS_EVSL*)data;
48 497050 : Vec x = ctx->x,y = ctx->y;
49 497050 : Mat A = ctx->A;
50 :
51 497050 : PetscFunctionBegin;
52 497050 : PetscCallAbort(PetscObjectComm((PetscObject)A),VecPlaceArray(x,(PetscScalar*)xa));
53 497050 : PetscCallAbort(PetscObjectComm((PetscObject)A),VecPlaceArray(y,(PetscScalar*)ya));
54 497050 : PetscCallAbort(PetscObjectComm((PetscObject)A),MatMult(A,x,y));
55 497050 : PetscCallAbort(PetscObjectComm((PetscObject)A),VecResetArray(x));
56 497050 : PetscCallAbort(PetscObjectComm((PetscObject)A),VecResetArray(y));
57 497050 : PetscFunctionReturnVoid();
58 : }
59 :
60 15 : static PetscErrorCode EPSSetUp_EVSL(EPS eps)
61 : {
62 15 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
63 15 : PetscMPIInt size,rank;
64 15 : PetscBool isshift;
65 15 : PetscScalar *vinit;
66 15 : PetscReal *mu,ecount,xintv[4],*xdos,*ydos;
67 15 : Vec v0;
68 15 : Mat A;
69 15 : PetscRandom rnd;
70 :
71 15 : PetscFunctionBegin;
72 15 : EPSCheckStandard(eps);
73 15 : EPSCheckHermitian(eps);
74 15 : EPSCheckNotStructured(eps);
75 15 : PetscCall(PetscObjectTypeCompare((PetscObject)eps->st,STSHIFT,&isshift));
76 15 : PetscCheck(isshift,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"This solver does not support spectral transformations");
77 :
78 15 : if (ctx->initialized) EVSLFinish();
79 15 : EVSLStart();
80 15 : ctx->initialized=PETSC_TRUE;
81 :
82 : /* get number of slices per process */
83 15 : PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)eps),&size));
84 15 : PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)eps),&rank));
85 15 : if (!ctx->nslices) ctx->nslices = size;
86 15 : PetscCall(PetscLayoutDestroy(&ctx->map));
87 15 : PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)eps),PETSC_DECIDE,ctx->nslices,1,&ctx->map));
88 :
89 : /* get matrix and prepare auxiliary vectors */
90 15 : PetscCall(MatDestroy(&ctx->A));
91 15 : PetscCall(STGetMatrix(eps->st,0,&A));
92 15 : if (size==1) {
93 7 : PetscCall(PetscObjectReference((PetscObject)A));
94 7 : ctx->A = A;
95 8 : } else PetscCall(MatCreateRedundantMatrix(A,0,PETSC_COMM_SELF,MAT_INITIAL_MATRIX,&ctx->A));
96 15 : SetAMatvec(eps->n,&AMatvec_EVSL,(void*)ctx);
97 15 : if (!ctx->x) PetscCall(MatCreateVecsEmpty(ctx->A,&ctx->x,&ctx->y));
98 15 : EPSCheckUnsupported(eps,EPS_FEATURE_ARBITRARY | EPS_FEATURE_REGION | EPS_FEATURE_STOPPING);
99 15 : EPSCheckIgnored(eps,EPS_FEATURE_EXTRACTION | EPS_FEATURE_CONVERGENCE);
100 :
101 15 : if (!eps->which) eps->which=EPS_ALL;
102 15 : PetscCheck(eps->which==EPS_ALL && eps->inta!=eps->intb,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"This solver requires setting an interval with EPSSetInterval()");
103 :
104 : /* estimate numerical range */
105 15 : if (ctx->estimrange || ctx->lmin == PETSC_MIN_REAL || ctx->lmax == PETSC_MAX_REAL) {
106 14 : PetscCall(MatCreateVecs(ctx->A,&v0,NULL));
107 14 : if (!eps->V) PetscCall(EPSGetBV(eps,&eps->V));
108 14 : PetscCall(BVGetRandomContext(eps->V,&rnd));
109 14 : PetscCall(VecSetRandom(v0,rnd));
110 14 : PetscCall(VecGetArray(v0,&vinit));
111 14 : PetscCallEVSL(LanTrbounds,50,200,eps->tol,vinit,1,&ctx->lmin,&ctx->lmax,NULL);
112 14 : PetscCall(VecRestoreArray(v0,&vinit));
113 14 : PetscCall(VecDestroy(&v0));
114 14 : ctx->estimrange = PETSC_TRUE; /* estimate if called again with another matrix */
115 : }
116 15 : PetscCheck(ctx->lmin<=eps->inta && ctx->lmax>=eps->intb,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"The requested interval [%g,%g] must be contained in the numerical range [%g,%g]",(double)eps->inta,(double)eps->intb,(double)ctx->lmin,(double)ctx->lmax);
117 15 : xintv[0] = eps->inta;
118 15 : xintv[1] = eps->intb;
119 15 : xintv[2] = ctx->lmin;
120 15 : xintv[3] = ctx->lmax;
121 :
122 : /* estimate number of eigenvalues in the interval */
123 15 : switch (ctx->dos) {
124 9 : case EPS_EVSL_DOS_KPM:
125 9 : PetscCall(PetscMalloc1(ctx->deg+1,&mu));
126 9 : if (!rank) PetscCallEVSL(kpmdos,ctx->deg,(int)ctx->damping,ctx->nvec,xintv,mu,&ecount);
127 18 : PetscCallMPI(MPI_Bcast(mu,ctx->deg+1,MPIU_REAL,0,PetscObjectComm((PetscObject)eps)));
128 : break;
129 6 : case EPS_EVSL_DOS_LANCZOS:
130 6 : PetscCall(PetscMalloc2(ctx->npoints,&xdos,ctx->npoints,&ydos));
131 6 : if (!rank) PetscCallEVSL(LanDos,ctx->nvec,PetscMin(ctx->steps,eps->n/2),ctx->npoints,xdos,ydos,&ecount,xintv);
132 12 : PetscCallMPI(MPI_Bcast(xdos,ctx->npoints,MPIU_REAL,0,PetscObjectComm((PetscObject)eps)));
133 12 : PetscCallMPI(MPI_Bcast(ydos,ctx->npoints,MPIU_REAL,0,PetscObjectComm((PetscObject)eps)));
134 : break;
135 0 : default:
136 0 : SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Invalid DOS method");
137 : }
138 30 : PetscCallMPI(MPI_Bcast(&ecount,1,MPIU_REAL,0,PetscObjectComm((PetscObject)eps)));
139 :
140 15 : PetscCall(PetscInfo(eps,"Estimated eigenvalue count in the interval: %g\n",ecount));
141 15 : eps->ncv = (PetscInt)PetscCeilReal(1.5*ecount);
142 :
143 : /* slice the spectrum */
144 15 : PetscCall(PetscFree(ctx->sli));
145 15 : PetscCall(PetscMalloc1(ctx->nslices+1,&ctx->sli));
146 15 : if (ctx->dos == EPS_EVSL_DOS_KPM) {
147 9 : PetscCallEVSL(spslicer,ctx->sli,mu,ctx->deg,xintv,ctx->nslices,10*(PetscInt)ecount);
148 9 : PetscCall(PetscFree(mu));
149 6 : } else if (ctx->dos == EPS_EVSL_DOS_LANCZOS) {
150 6 : spslicer2(xdos,ydos,ctx->nslices,ctx->npoints,ctx->sli);
151 6 : PetscCall(PetscFree2(xdos,ydos));
152 : }
153 :
154 : /* approximate number of eigenvalues wanted in each slice */
155 15 : ctx->nev = (PetscInt)(1.0 + ecount/(PetscReal)ctx->nslices) + 2;
156 :
157 15 : if (eps->mpd!=PETSC_DETERMINE) PetscCall(PetscInfo(eps,"Warning: parameter mpd ignored\n"));
158 15 : if (eps->max_it==PETSC_DETERMINE) eps->max_it = 1;
159 15 : PetscCall(EPSAllocateSolution(eps,0));
160 15 : PetscFunctionReturn(PETSC_SUCCESS);
161 : }
162 :
163 15 : static PetscErrorCode EPSSolve_EVSL(EPS eps)
164 : {
165 15 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
166 15 : PetscInt i,j,k=0,sl,mlan,nevout,*ind,nevmax,rstart,rend,*nevloc,*disp,N;
167 15 : PetscReal *res,xintv[4],*errest;
168 15 : PetscScalar *lam,*X,*Y,*vinit,*eigr;
169 15 : PetscMPIInt size,rank;
170 15 : PetscRandom rnd;
171 15 : Vec v,w,v0,x;
172 15 : VecScatter vs;
173 15 : IS is;
174 15 : polparams pol;
175 :
176 15 : PetscFunctionBegin;
177 15 : PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)eps),&size));
178 15 : PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)eps),&rank));
179 15 : PetscCall(PetscLayoutGetRange(ctx->map,&rstart,&rend));
180 15 : nevmax = (rend-rstart)*ctx->nev;
181 15 : PetscCall(MatCreateVecs(ctx->A,&v0,NULL));
182 15 : PetscCall(BVGetRandomContext(eps->V,&rnd));
183 15 : PetscCall(VecSetRandom(v0,rnd));
184 15 : PetscCall(VecGetArray(v0,&vinit));
185 15 : PetscCall(PetscMalloc5(size,&nevloc,size+1,&disp,nevmax,&eigr,nevmax,&errest,nevmax*eps->n,&X));
186 15 : mlan = PetscMin(PetscMax(5*ctx->nev,300),eps->n);
187 37 : for (sl=rstart; sl<rend; sl++) {
188 22 : xintv[0] = ctx->sli[sl];
189 22 : xintv[1] = ctx->sli[sl+1];
190 22 : xintv[2] = ctx->lmin;
191 22 : xintv[3] = ctx->lmax;
192 22 : PetscCall(PetscInfo(ctx->A,"Subinterval %" PetscInt_FMT ": [%.4e, %.4e]\n",sl+1,xintv[0],xintv[1]));
193 22 : set_pol_def(&pol);
194 22 : pol.max_deg = ctx->max_deg;
195 22 : pol.damping = (int)ctx->damping;
196 22 : pol.thresh_int = ctx->thresh;
197 22 : find_pol(xintv,&pol);
198 22 : PetscCall(PetscInfo(ctx->A,"Polynomial [type = %" PetscInt_FMT "], deg %" PetscInt_FMT ", bar %e gam %e\n",pol.type,pol.deg,pol.bar,pol.gam));
199 22 : PetscCallEVSL(ChebLanNr,xintv,mlan,eps->tol,vinit,&pol,&nevout,&lam,&Y,&res,NULL);
200 22 : PetscCheck(k+nevout<=nevmax,PetscObjectComm((PetscObject)eps),PETSC_ERR_LIB,"Too low estimation of eigenvalue count, try modifying the sampling parameters");
201 22 : free_pol(&pol);
202 22 : PetscCall(PetscInfo(ctx->A,"Computed %" PetscInt_FMT " eigenvalues\n",nevout));
203 22 : PetscCall(PetscMalloc1(nevout,&ind));
204 22 : sort_double(nevout,lam,ind);
205 170 : for (i=0;i<nevout;i++) {
206 126 : eigr[i+k] = lam[i];
207 126 : errest[i+k] = res[ind[i]];
208 126 : PetscCall(PetscArraycpy(X+(i+k)*eps->n,Y+ind[i]*eps->n,eps->n));
209 : }
210 22 : k += nevout;
211 22 : if (lam) evsl_Free(lam);
212 22 : if (Y) evsl_Free_device(Y);
213 22 : if (res) evsl_Free(res);
214 22 : PetscCall(PetscFree(ind));
215 : }
216 15 : PetscCall(VecRestoreArray(v0,&vinit));
217 15 : PetscCall(VecDestroy(&v0));
218 :
219 : /* gather eigenvalues computed by each MPI process */
220 30 : PetscCallMPI(MPI_Allgather(&k,1,MPIU_INT,nevloc,1,MPIU_INT,PetscObjectComm((PetscObject)eps)));
221 15 : eps->nev = nevloc[0];
222 15 : disp[0] = 0;
223 23 : for (i=1;i<size;i++) {
224 8 : eps->nev += nevloc[i];
225 8 : disp[i] = disp[i-1]+nevloc[i-1];
226 : }
227 15 : disp[size] = disp[size-1]+nevloc[size-1];
228 15 : PetscCheck(eps->nev<=eps->ncv,PetscObjectComm((PetscObject)eps),PETSC_ERR_LIB,"Too low estimation of eigenvalue count, try modifying the sampling parameters");
229 30 : PetscCallMPI(MPI_Allgatherv(eigr,k,MPIU_SCALAR,eps->eigr,nevloc,disp,MPIU_SCALAR,PetscObjectComm((PetscObject)eps)));
230 30 : PetscCallMPI(MPI_Allgatherv(errest,k,MPIU_REAL,eps->errest,nevloc,disp,MPIU_REAL,PetscObjectComm((PetscObject)eps)));
231 15 : eps->nconv = eps->nev;
232 15 : eps->its = 1;
233 15 : eps->reason = EPS_CONVERGED_TOL;
234 :
235 : /* scatter computed eigenvectors and store them in eps->V */
236 15 : PetscCall(BVCreateVec(eps->V,&w));
237 38 : for (i=0;i<size;i++) {
238 23 : N = (rank==i)? eps->n: 0;
239 23 : PetscCall(VecCreateSeq(PETSC_COMM_SELF,N,&x));
240 23 : PetscCall(VecSetFromOptions(x));
241 23 : PetscCall(ISCreateStride(PETSC_COMM_SELF,N,0,1,&is));
242 23 : PetscCall(VecScatterCreate(x,is,w,is,&vs));
243 23 : PetscCall(ISDestroy(&is));
244 176 : for (j=disp[i];j<disp[i+1];j++) {
245 153 : PetscCall(BVGetColumn(eps->V,j,&v));
246 153 : if (rank==i) PetscCall(VecPlaceArray(x,X+(j-disp[i])*eps->n));
247 153 : PetscCall(VecScatterBegin(vs,x,v,INSERT_VALUES,SCATTER_FORWARD));
248 153 : PetscCall(VecScatterEnd(vs,x,v,INSERT_VALUES,SCATTER_FORWARD));
249 153 : if (rank==i) PetscCall(VecResetArray(x));
250 153 : PetscCall(BVRestoreColumn(eps->V,j,&v));
251 : }
252 23 : PetscCall(VecScatterDestroy(&vs));
253 23 : PetscCall(VecDestroy(&x));
254 : }
255 15 : PetscCall(VecDestroy(&w));
256 15 : PetscCall(PetscFree5(nevloc,disp,eigr,errest,X));
257 15 : PetscFunctionReturn(PETSC_SUCCESS);
258 : }
259 :
260 2 : static PetscErrorCode EPSEVSLSetSlices_EVSL(EPS eps,PetscInt nslices)
261 : {
262 2 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
263 :
264 2 : PetscFunctionBegin;
265 2 : if (nslices == PETSC_DECIDE || nslices == PETSC_DEFAULT) nslices = 0;
266 2 : else PetscCheck(nslices>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Number of slices must be 1 at least");
267 2 : if (ctx->nslices != nslices) {
268 2 : ctx->nslices = nslices;
269 2 : eps->state = EPS_STATE_INITIAL;
270 : }
271 2 : PetscFunctionReturn(PETSC_SUCCESS);
272 : }
273 :
274 : /*@
275 : EPSEVSLSetSlices - Set the number of slices in which the interval must be
276 : subdivided.
277 :
278 : Logically Collective
279 :
280 : Input Parameters:
281 : + eps - the eigensolver context
282 : - nslices - the number of slices
283 :
284 : Options Database Key:
285 : . -eps_evsl_slices <n> - set the number of slices to n
286 :
287 : Notes:
288 : By default, one slice per MPI process is used. Depending on the number of
289 : eigenvalues, using more slices may be beneficial, but very narrow subintervals
290 : imply higher polynomial degree.
291 :
292 : Level: intermediate
293 :
294 : .seealso: EPSEVSLGetSlices()
295 : @*/
296 2 : PetscErrorCode EPSEVSLSetSlices(EPS eps,PetscInt nslices)
297 : {
298 2 : PetscFunctionBegin;
299 2 : PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
300 6 : PetscValidLogicalCollectiveInt(eps,nslices,2);
301 2 : PetscTryMethod(eps,"EPSEVSLSetSlices_C",(EPS,PetscInt),(eps,nslices));
302 2 : PetscFunctionReturn(PETSC_SUCCESS);
303 : }
304 :
305 1 : static PetscErrorCode EPSEVSLGetSlices_EVSL(EPS eps,PetscInt *nslices)
306 : {
307 1 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
308 :
309 1 : PetscFunctionBegin;
310 1 : *nslices = ctx->nslices;
311 1 : PetscFunctionReturn(PETSC_SUCCESS);
312 : }
313 :
314 : /*@
315 : EPSEVSLGetSlices - Gets the number of slices in which the interval must be
316 : subdivided.
317 :
318 : Not Collective
319 :
320 : Input Parameter:
321 : . eps - the eigensolver context
322 :
323 : Output Parameter:
324 : . nslices - the number of slices
325 :
326 : Level: intermediate
327 :
328 : .seealso: EPSEVSLSetSlices()
329 : @*/
330 1 : PetscErrorCode EPSEVSLGetSlices(EPS eps,PetscInt *nslices)
331 : {
332 1 : PetscFunctionBegin;
333 1 : PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
334 1 : PetscAssertPointer(nslices,2);
335 1 : PetscUseMethod(eps,"EPSEVSLGetSlices_C",(EPS,PetscInt*),(eps,nslices));
336 1 : PetscFunctionReturn(PETSC_SUCCESS);
337 : }
338 :
339 1 : static PetscErrorCode EPSEVSLSetRange_EVSL(EPS eps,PetscReal lmin,PetscReal lmax)
340 : {
341 1 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
342 :
343 1 : PetscFunctionBegin;
344 1 : PetscCheck(lmin<lmax,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONG,"Badly defined interval, must be lmin<lmax");
345 1 : if (ctx->lmin != lmin || ctx->lmax != lmax) {
346 1 : ctx->lmin = lmin;
347 1 : ctx->lmax = lmax;
348 1 : eps->state = EPS_STATE_INITIAL;
349 : }
350 1 : PetscFunctionReturn(PETSC_SUCCESS);
351 : }
352 :
353 : /*@
354 : EPSEVSLSetRange - Defines the numerical range (or field of values) of the problem,
355 : that is, the interval containing all eigenvalues.
356 :
357 : Logically Collective
358 :
359 : Input Parameters:
360 : + eps - the eigensolver context
361 : . lmin - left end of the interval
362 : - lmax - right end of the interval
363 :
364 : Options Database Key:
365 : . -eps_evsl_range <a,b> - set [a,b] as the numerical range
366 :
367 : Notes:
368 : The filter will be most effective if the numerical range is tight, that is, lmin
369 : and lmax are good approximations to the leftmost and rightmost eigenvalues,
370 : respectively. If not set by the user, an approximation is computed internally.
371 :
372 : The wanted computational interval specified via EPSSetInterval() must be
373 : contained in the numerical range.
374 :
375 : Level: intermediate
376 :
377 : .seealso: EPSEVSLGetRange(), EPSSetInterval()
378 : @*/
379 1 : PetscErrorCode EPSEVSLSetRange(EPS eps,PetscReal lmin,PetscReal lmax)
380 : {
381 1 : PetscFunctionBegin;
382 1 : PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
383 3 : PetscValidLogicalCollectiveReal(eps,lmin,2);
384 3 : PetscValidLogicalCollectiveReal(eps,lmax,3);
385 1 : PetscTryMethod(eps,"EPSEVSLSetRange_C",(EPS,PetscReal,PetscReal),(eps,lmin,lmax));
386 1 : PetscFunctionReturn(PETSC_SUCCESS);
387 : }
388 :
389 1 : static PetscErrorCode EPSEVSLGetRange_EVSL(EPS eps,PetscReal *lmin,PetscReal *lmax)
390 : {
391 1 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
392 :
393 1 : PetscFunctionBegin;
394 1 : if (lmin) *lmin = ctx->lmin;
395 1 : if (lmax) *lmax = ctx->lmax;
396 1 : PetscFunctionReturn(PETSC_SUCCESS);
397 : }
398 :
399 : /*@
400 : EPSEVSLGetRange - Gets the interval containing all eigenvalues.
401 :
402 : Not Collective
403 :
404 : Input Parameter:
405 : . eps - the eigensolver context
406 :
407 : Output Parameters:
408 : + lmin - left end of the interval
409 : - lmax - right end of the interval
410 :
411 : Level: intermediate
412 :
413 : .seealso: EPSEVSLSetRange()
414 : @*/
415 1 : PetscErrorCode EPSEVSLGetRange(EPS eps,PetscReal *lmin,PetscReal *lmax)
416 : {
417 1 : PetscFunctionBegin;
418 1 : PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
419 1 : PetscUseMethod(eps,"EPSEVSLGetRange_C",(EPS,PetscReal*,PetscReal*),(eps,lmin,lmax));
420 1 : PetscFunctionReturn(PETSC_SUCCESS);
421 : }
422 :
423 4 : static PetscErrorCode EPSEVSLSetDOSParameters_EVSL(EPS eps,EPSEVSLDOSMethod dos,PetscInt nvec,PetscInt deg,PetscInt steps,PetscInt npoints)
424 : {
425 4 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
426 :
427 4 : PetscFunctionBegin;
428 4 : ctx->dos = dos;
429 4 : if (nvec == PETSC_DETERMINE) ctx->nvec = 80;
430 4 : else if (nvec != PETSC_CURRENT) {
431 4 : PetscCheck(nvec>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The nvec argument must be > 0");
432 4 : ctx->nvec = nvec;
433 : }
434 4 : switch (dos) {
435 1 : case EPS_EVSL_DOS_KPM:
436 1 : if (deg == PETSC_DETERMINE) ctx->deg = 300;
437 1 : else if (deg != PETSC_CURRENT) {
438 1 : PetscCheck(deg>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The deg argument must be > 0");
439 1 : ctx->deg = deg;
440 : }
441 : break;
442 3 : case EPS_EVSL_DOS_LANCZOS:
443 3 : if (steps == PETSC_DETERMINE) ctx->steps = 40;
444 3 : else if (steps != PETSC_CURRENT) {
445 3 : PetscCheck(steps>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The steps argument must be > 0");
446 3 : ctx->steps = steps;
447 : }
448 3 : if (npoints == PETSC_DETERMINE) ctx->npoints = 200;
449 3 : else if (npoints != PETSC_CURRENT) {
450 3 : PetscCheck(npoints>0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The npoints argument must be > 0");
451 3 : ctx->npoints = npoints;
452 : }
453 : break;
454 : }
455 4 : eps->state = EPS_STATE_INITIAL;
456 4 : PetscFunctionReturn(PETSC_SUCCESS);
457 : }
458 :
459 : /*@
460 : EPSEVSLSetDOSParameters - Defines the parameters used for computing the
461 : density of states (DOS) in the EVSL solver.
462 :
463 : Logically Collective
464 :
465 : Input Parameters:
466 : + eps - the eigensolver context
467 : . dos - DOS method, either KPM or Lanczos
468 : . nvec - number of sample vectors
469 : . deg - polynomial degree (KPM only)
470 : . steps - number of Lanczos steps (Lanczos only)
471 : - npoints - number of sample points (Lanczos only)
472 :
473 : Options Database Keys:
474 : + -eps_evsl_dos_method <dos> - set the DOS method, either kpm or lanczos
475 : . -eps_evsl_dos_nvec <n> - set the number of sample vectors
476 : . -eps_evsl_dos_degree <n> - set the polynomial degree
477 : . -eps_evsl_dos_steps <n> - set the number of Lanczos steps
478 : - -eps_evsl_dos_npoints <n> - set the number of sample points
479 :
480 : Notes:
481 : The density of states (or spectral density) can be approximated with two
482 : methods, kernel polynomial method (KPM) or Lanczos. Some parameters for
483 : these methods can be set by the user with this function, with some of
484 : them being relevant for one of the methods only.
485 :
486 : For the integer argumens, you can use PETSC_CURRENT to keep the current
487 : value, and PETSC_DETERMINE to set them to a reasonable default.
488 :
489 : Level: intermediate
490 :
491 : .seealso: EPSEVSLGetDOSParameters()
492 : @*/
493 4 : PetscErrorCode EPSEVSLSetDOSParameters(EPS eps,EPSEVSLDOSMethod dos,PetscInt nvec,PetscInt deg,PetscInt steps,PetscInt npoints)
494 : {
495 4 : PetscFunctionBegin;
496 4 : PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
497 12 : PetscValidLogicalCollectiveEnum(eps,dos,2);
498 12 : PetscValidLogicalCollectiveInt(eps,nvec,3);
499 12 : PetscValidLogicalCollectiveInt(eps,deg,4);
500 12 : PetscValidLogicalCollectiveInt(eps,steps,5);
501 12 : PetscValidLogicalCollectiveInt(eps,npoints,6);
502 4 : PetscTryMethod(eps,"EPSEVSLSetDOSParameters_C",(EPS,EPSEVSLDOSMethod,PetscInt,PetscInt,PetscInt,PetscInt),(eps,dos,nvec,deg,steps,npoints));
503 4 : PetscFunctionReturn(PETSC_SUCCESS);
504 : }
505 :
506 9 : static PetscErrorCode EPSEVSLGetDOSParameters_EVSL(EPS eps,EPSEVSLDOSMethod *dos,PetscInt *nvec,PetscInt *deg,PetscInt *steps,PetscInt *npoints)
507 : {
508 9 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
509 :
510 9 : PetscFunctionBegin;
511 9 : if (dos) *dos = ctx->dos;
512 9 : if (nvec) *nvec = ctx->nvec;
513 9 : if (deg) *deg = ctx->deg;
514 9 : if (steps) *steps = ctx->steps;
515 9 : if (npoints) *npoints = ctx->npoints;
516 9 : PetscFunctionReturn(PETSC_SUCCESS);
517 : }
518 :
519 : /*@
520 : EPSEVSLGetDOSParameters - Gets the parameters used for computing the
521 : density of states (DOS) in the EVSL solver.
522 :
523 : Not Collective
524 :
525 : Input Parameter:
526 : . eps - the eigensolver context
527 :
528 : Output Parameters:
529 : + dos - DOS method, either KPM or Lanczos
530 : . nvec - number of sample vectors
531 : . deg - polynomial degree (KPM only)
532 : . steps - number of Lanczos steps (Lanczos only)
533 : - npoints - number of sample points (Lanczos only)
534 :
535 : Level: intermediate
536 :
537 : .seealso: EPSEVSLSetDOSParameters()
538 : @*/
539 9 : PetscErrorCode EPSEVSLGetDOSParameters(EPS eps,EPSEVSLDOSMethod *dos,PetscInt *nvec,PetscInt *deg,PetscInt *steps,PetscInt *npoints)
540 : {
541 9 : PetscFunctionBegin;
542 9 : PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
543 9 : PetscUseMethod(eps,"EPSEVSLGetDOSParameters_C",(EPS,EPSEVSLDOSMethod*,PetscInt*,PetscInt*,PetscInt*,PetscInt*),(eps,dos,nvec,deg,steps,npoints));
544 9 : PetscFunctionReturn(PETSC_SUCCESS);
545 : }
546 :
547 1 : static PetscErrorCode EPSEVSLSetPolParameters_EVSL(EPS eps,PetscInt max_deg,PetscReal thresh)
548 : {
549 1 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
550 :
551 1 : PetscFunctionBegin;
552 1 : if (max_deg == PETSC_DETERMINE) ctx->max_deg = 10000;
553 1 : else if (max_deg != PETSC_CURRENT) {
554 1 : PetscCheck(max_deg>2,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The max_deg argument must be > 2");
555 1 : ctx->max_deg = max_deg;
556 : }
557 1 : if (thresh == (PetscReal)PETSC_DETERMINE) ctx->thresh = 0.8;
558 1 : else if (thresh != (PetscReal)PETSC_CURRENT) {
559 1 : PetscCheck(thresh>0.0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"The thresh argument must be > 0.0");
560 1 : ctx->thresh = thresh;
561 : }
562 1 : eps->state = EPS_STATE_INITIAL;
563 1 : PetscFunctionReturn(PETSC_SUCCESS);
564 : }
565 :
566 : /*@
567 : EPSEVSLSetPolParameters - Defines the parameters used for building the
568 : building the polynomial in the EVSL solver.
569 :
570 : Logically Collective
571 :
572 : Input Parameters:
573 : + eps - the eigensolver context
574 : . max_deg - maximum degree allowed for the polynomial
575 : - thresh - threshold for accepting polynomial
576 :
577 : Options Database Keys:
578 : + -eps_evsl_pol_max_deg <d> - set maximum polynomial degree
579 : - -eps_evsl_pol_thresh <t> - set the threshold
580 :
581 : Note:
582 : PETSC_CURRENT can be used to preserve the current value of any of the
583 : arguments, and PETSC_DETERMINE to set them to a default value.
584 :
585 : Level: intermediate
586 :
587 : .seealso: EPSEVSLGetPolParameters()
588 : @*/
589 1 : PetscErrorCode EPSEVSLSetPolParameters(EPS eps,PetscInt max_deg,PetscReal thresh)
590 : {
591 1 : PetscFunctionBegin;
592 1 : PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
593 3 : PetscValidLogicalCollectiveInt(eps,max_deg,2);
594 3 : PetscValidLogicalCollectiveReal(eps,thresh,3);
595 1 : PetscTryMethod(eps,"EPSEVSLSetPolParameters_C",(EPS,PetscInt,PetscReal),(eps,max_deg,thresh));
596 1 : PetscFunctionReturn(PETSC_SUCCESS);
597 : }
598 :
599 9 : static PetscErrorCode EPSEVSLGetPolParameters_EVSL(EPS eps,PetscInt *max_deg,PetscReal *thresh)
600 : {
601 9 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
602 :
603 9 : PetscFunctionBegin;
604 9 : if (max_deg) *max_deg = ctx->max_deg;
605 9 : if (thresh) *thresh = ctx->thresh;
606 9 : PetscFunctionReturn(PETSC_SUCCESS);
607 : }
608 :
609 : /*@
610 : EPSEVSLGetPolParameters - Gets the parameters used for building the
611 : polynomial in the EVSL solver.
612 :
613 : Not Collective
614 :
615 : Input Parameter:
616 : . eps - the eigensolver context
617 :
618 : Output Parameters:
619 : + max_deg - the maximum degree of the polynomial
620 : - thresh - the threshold
621 :
622 : Level: intermediate
623 :
624 : .seealso: EPSEVSLSetPolParameters()
625 : @*/
626 9 : PetscErrorCode EPSEVSLGetPolParameters(EPS eps,PetscInt *max_deg,PetscReal *thresh)
627 : {
628 9 : PetscFunctionBegin;
629 9 : PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
630 9 : PetscUseMethod(eps,"EPSEVSLGetPolParameters_C",(EPS,PetscInt*,PetscReal*),(eps,max_deg,thresh));
631 9 : PetscFunctionReturn(PETSC_SUCCESS);
632 : }
633 :
634 2 : static PetscErrorCode EPSEVSLSetDamping_EVSL(EPS eps,EPSEVSLDamping damping)
635 : {
636 2 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
637 :
638 2 : PetscFunctionBegin;
639 2 : if (ctx->damping != damping) {
640 1 : ctx->damping = damping;
641 1 : eps->state = EPS_STATE_INITIAL;
642 : }
643 2 : PetscFunctionReturn(PETSC_SUCCESS);
644 : }
645 :
646 : /*@
647 : EPSEVSLSetDamping - Set the type of damping to be used in EVSL.
648 :
649 : Logically Collective
650 :
651 : Input Parameters:
652 : + eps - the eigensolver context
653 : - damping - the type of damping
654 :
655 : Options Database Key:
656 : . -eps_evsl_damping <n> - set the type of damping
657 :
658 : Notes:
659 : Damping is applied when building the polynomial to be used when solving the
660 : eigenproblem, and also during estimation of DOS with the KPM method.
661 :
662 : Level: intermediate
663 :
664 : .seealso: EPSEVSLGetDamping(), EPSEVSLSetDOSParameters()
665 : @*/
666 2 : PetscErrorCode EPSEVSLSetDamping(EPS eps,EPSEVSLDamping damping)
667 : {
668 2 : PetscFunctionBegin;
669 2 : PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
670 6 : PetscValidLogicalCollectiveEnum(eps,damping,2);
671 2 : PetscTryMethod(eps,"EPSEVSLSetDamping_C",(EPS,EPSEVSLDamping),(eps,damping));
672 2 : PetscFunctionReturn(PETSC_SUCCESS);
673 : }
674 :
675 1 : static PetscErrorCode EPSEVSLGetDamping_EVSL(EPS eps,EPSEVSLDamping *damping)
676 : {
677 1 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
678 :
679 1 : PetscFunctionBegin;
680 1 : *damping = ctx->damping;
681 1 : PetscFunctionReturn(PETSC_SUCCESS);
682 : }
683 :
684 : /*@
685 : EPSEVSLGetDamping - Gets the type of damping.
686 :
687 : Not Collective
688 :
689 : Input Parameter:
690 : . eps - the eigensolver context
691 :
692 : Output Parameter:
693 : . damping - the type of damping
694 :
695 : Level: intermediate
696 :
697 : .seealso: EPSEVSLSetDamping()
698 : @*/
699 1 : PetscErrorCode EPSEVSLGetDamping(EPS eps,EPSEVSLDamping *damping)
700 : {
701 1 : PetscFunctionBegin;
702 1 : PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
703 1 : PetscAssertPointer(damping,2);
704 1 : PetscUseMethod(eps,"EPSEVSLGetDamping_C",(EPS,EPSEVSLDamping*),(eps,damping));
705 1 : PetscFunctionReturn(PETSC_SUCCESS);
706 : }
707 :
708 1 : static PetscErrorCode EPSView_EVSL(EPS eps,PetscViewer viewer)
709 : {
710 1 : PetscBool isascii;
711 1 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
712 :
713 1 : PetscFunctionBegin;
714 1 : PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
715 1 : if (isascii) {
716 1 : PetscCall(PetscViewerASCIIPrintf(viewer," numerical range = [%g,%g]\n",(double)ctx->lmin,(double)ctx->lmax));
717 1 : PetscCall(PetscViewerASCIIPrintf(viewer," number of slices = %" PetscInt_FMT "\n",ctx->nslices));
718 1 : PetscCall(PetscViewerASCIIPrintf(viewer," type of damping = %s\n",EPSEVSLDampings[ctx->damping]));
719 1 : PetscCall(PetscViewerASCIIPrintf(viewer," computing DOS with %s: nvec=%" PetscInt_FMT ", ",EPSEVSLDOSMethods[ctx->dos],ctx->nvec));
720 1 : PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
721 1 : switch (ctx->dos) {
722 1 : case EPS_EVSL_DOS_KPM:
723 1 : PetscCall(PetscViewerASCIIPrintf(viewer,"degree=%" PetscInt_FMT "\n",ctx->deg));
724 : break;
725 0 : case EPS_EVSL_DOS_LANCZOS:
726 0 : PetscCall(PetscViewerASCIIPrintf(viewer,"steps=%" PetscInt_FMT ", npoints=%" PetscInt_FMT "\n",ctx->steps,ctx->npoints));
727 : break;
728 : }
729 1 : PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
730 1 : PetscCall(PetscViewerASCIIPrintf(viewer," polynomial parameters: max degree = %" PetscInt_FMT ", threshold = %g\n",ctx->max_deg,(double)ctx->thresh));
731 : }
732 1 : PetscFunctionReturn(PETSC_SUCCESS);
733 : }
734 :
735 9 : static PetscErrorCode EPSSetFromOptions_EVSL(EPS eps,PetscOptionItems *PetscOptionsObject)
736 : {
737 9 : PetscReal array[2]={0,0},th;
738 9 : PetscInt k,i1,i2,i3,i4;
739 9 : PetscBool flg,flg1;
740 9 : EPSEVSLDOSMethod dos;
741 9 : EPSEVSLDamping damping;
742 9 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
743 :
744 9 : PetscFunctionBegin;
745 9 : PetscOptionsHeadBegin(PetscOptionsObject,"EPS EVSL Options");
746 :
747 9 : k = 2;
748 9 : PetscCall(PetscOptionsRealArray("-eps_evsl_range","Interval containing all eigenvalues (two real values separated with a comma without spaces)","EPSEVSLSetRange",array,&k,&flg));
749 9 : if (flg) {
750 0 : PetscCheck(k>1,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_SIZ,"Must pass two values in -eps_evsl_range (comma-separated without spaces)");
751 0 : PetscCall(EPSEVSLSetRange(eps,array[0],array[1]));
752 : }
753 :
754 9 : PetscCall(PetscOptionsInt("-eps_evsl_slices","Number of slices","EPSEVSLSetSlices",ctx->nslices,&i1,&flg));
755 9 : if (flg) PetscCall(EPSEVSLSetSlices(eps,i1));
756 :
757 9 : PetscCall(PetscOptionsEnum("-eps_evsl_damping","Type of damping","EPSEVSLSetDamping",EPSEVSLDampings,(PetscEnum)ctx->damping,(PetscEnum*)&damping,&flg));
758 9 : if (flg) PetscCall(EPSEVSLSetDamping(eps,damping));
759 :
760 9 : PetscCall(EPSEVSLGetDOSParameters(eps,&dos,&i1,&i2,&i3,&i4));
761 9 : PetscCall(PetscOptionsEnum("-eps_evsl_dos_method","Method to compute the DOS","EPSEVSLSetDOSParameters",EPSEVSLDOSMethods,(PetscEnum)ctx->dos,(PetscEnum*)&dos,&flg));
762 9 : PetscCall(PetscOptionsInt("-eps_evsl_dos_nvec","Number of sample vectors for DOS","EPSEVSLSetDOSParameters",i1,&i1,&flg1));
763 9 : if (flg1) flg = PETSC_TRUE;
764 9 : PetscCall(PetscOptionsInt("-eps_evsl_dos_degree","Polynomial degree used for DOS","EPSEVSLSetDOSParameters",i2,&i2,&flg1));
765 9 : if (flg1) flg = PETSC_TRUE;
766 9 : PetscCall(PetscOptionsInt("-eps_evsl_dos_steps","Number of Lanczos steps in DOS","EPSEVSLSetDOSParameters",i3,&i3,&flg1));
767 9 : if (flg1) flg = PETSC_TRUE;
768 9 : PetscCall(PetscOptionsInt("-eps_evsl_dos_npoints","Number of sample points used for DOS","EPSEVSLSetDOSParameters",i4,&i4,&flg1));
769 9 : if (flg || flg1) PetscCall(EPSEVSLSetDOSParameters(eps,dos,i1,i2,i3,i4));
770 :
771 9 : PetscCall(EPSEVSLGetPolParameters(eps,&i1,&th));
772 9 : PetscCall(PetscOptionsInt("-eps_evsl_pol_max_deg","Maximum degree allowed for the polynomial","EPSEVSLSetPolParameters",i1,&i1,&flg));
773 9 : PetscCall(PetscOptionsReal("-eps_evsl_pol_threshold","Threshold for accepting polynomial","EPSEVSLSetPolParameters",th,&th,&flg1));
774 9 : if (flg || flg1) PetscCall(EPSEVSLSetPolParameters(eps,i1,th));
775 :
776 9 : PetscOptionsHeadEnd();
777 9 : PetscFunctionReturn(PETSC_SUCCESS);
778 : }
779 :
780 9 : static PetscErrorCode EPSDestroy_EVSL(EPS eps)
781 : {
782 9 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
783 :
784 9 : PetscFunctionBegin;
785 9 : if (ctx->initialized) EVSLFinish();
786 9 : PetscCall(PetscLayoutDestroy(&ctx->map));
787 9 : PetscCall(PetscFree(ctx->sli));
788 9 : PetscCall(PetscFree(eps->data));
789 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetRange_C",NULL));
790 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetRange_C",NULL));
791 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetSlices_C",NULL));
792 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetSlices_C",NULL));
793 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetDOSParameters_C",NULL));
794 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetDOSParameters_C",NULL));
795 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetPolParameters_C",NULL));
796 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetPolParameters_C",NULL));
797 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetDamping_C",NULL));
798 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetDamping_C",NULL));
799 9 : PetscFunctionReturn(PETSC_SUCCESS);
800 : }
801 :
802 12 : static PetscErrorCode EPSReset_EVSL(EPS eps)
803 : {
804 12 : EPS_EVSL *ctx = (EPS_EVSL*)eps->data;
805 :
806 12 : PetscFunctionBegin;
807 12 : PetscCall(MatDestroy(&ctx->A));
808 12 : PetscCall(VecDestroy(&ctx->x));
809 12 : PetscCall(VecDestroy(&ctx->y));
810 12 : PetscFunctionReturn(PETSC_SUCCESS);
811 : }
812 :
813 9 : SLEPC_EXTERN PetscErrorCode EPSCreate_EVSL(EPS eps)
814 : {
815 9 : EPS_EVSL *ctx;
816 :
817 9 : PetscFunctionBegin;
818 9 : PetscCall(PetscNew(&ctx));
819 9 : eps->data = (void*)ctx;
820 :
821 9 : ctx->nslices = 0;
822 9 : ctx->lmin = PETSC_MIN_REAL;
823 9 : ctx->lmax = PETSC_MAX_REAL;
824 9 : ctx->dos = EPS_EVSL_DOS_KPM;
825 9 : ctx->nvec = 80;
826 9 : ctx->deg = 300;
827 9 : ctx->steps = 40;
828 9 : ctx->npoints = 200;
829 9 : ctx->max_deg = 10000;
830 9 : ctx->thresh = 0.8;
831 9 : ctx->damping = EPS_EVSL_DAMPING_SIGMA;
832 :
833 9 : eps->categ = EPS_CATEGORY_OTHER;
834 :
835 9 : eps->ops->solve = EPSSolve_EVSL;
836 9 : eps->ops->setup = EPSSetUp_EVSL;
837 9 : eps->ops->setupsort = EPSSetUpSort_Basic;
838 9 : eps->ops->setfromoptions = EPSSetFromOptions_EVSL;
839 9 : eps->ops->destroy = EPSDestroy_EVSL;
840 9 : eps->ops->reset = EPSReset_EVSL;
841 9 : eps->ops->view = EPSView_EVSL;
842 9 : eps->ops->backtransform = EPSBackTransform_Default;
843 9 : eps->ops->setdefaultst = EPSSetDefaultST_NoFactor;
844 :
845 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetRange_C",EPSEVSLSetRange_EVSL));
846 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetRange_C",EPSEVSLGetRange_EVSL));
847 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetSlices_C",EPSEVSLSetSlices_EVSL));
848 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetSlices_C",EPSEVSLGetSlices_EVSL));
849 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetDOSParameters_C",EPSEVSLSetDOSParameters_EVSL));
850 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetDOSParameters_C",EPSEVSLGetDOSParameters_EVSL));
851 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetPolParameters_C",EPSEVSLSetPolParameters_EVSL));
852 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetPolParameters_C",EPSEVSLGetPolParameters_EVSL));
853 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLSetDamping_C",EPSEVSLSetDamping_EVSL));
854 9 : PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSEVSLGetDamping_C",EPSEVSLGetDamping_EVSL));
855 9 : PetscFunctionReturn(PETSC_SUCCESS);
856 : }
|