Actual source code: filter.c
slepc-3.8.0 2017-10-20
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-2017, 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: Filter spectral transformation, to encapsulate polynomial filters
12: */
14: #include <slepc/private/stimpl.h> /*I "slepcst.h" I*/
15: #include "./filter.h"
17: PetscErrorCode STApply_Filter(ST st,Vec x,Vec y)
18: {
22: STFilter_FILTLAN_Apply(st,x,y);
23: return(0);
24: }
26: PetscErrorCode STSetUp_Filter(ST st)
27: {
29: ST_FILTER *ctx = (ST_FILTER*)st->data;
32: STSetWorkVecs(st,4);
33: if (st->nmat>1) SETERRQ(PetscObjectComm((PetscObject)st),1,"Only implemented for standard eigenvalue problem");
34: if (ctx->intb >= PETSC_MAX_REAL && ctx->inta <= PETSC_MIN_REAL) SETERRQ(PetscObjectComm((PetscObject)st),1,"Must pass an interval with STFilterSetInterval()");
35: if (ctx->right >= PETSC_MAX_REAL && ctx->left <= PETSC_MIN_REAL) SETERRQ(PetscObjectComm((PetscObject)st),1,"Must pass an approximate numerical range with STFilterSetRange()");
36: if (ctx->left > ctx->inta || ctx->right < ctx->intb) SETERRQ4(PetscObjectComm((PetscObject)st),1,"The requested interval [%g,%g] must be contained in the numerical range [%g,%g]",(double)ctx->inta,(double)ctx->intb,(double)ctx->left,(double)ctx->right);
37: if (!ctx->polyDegree) ctx->polyDegree = 100;
38: ctx->frame[0] = ctx->left;
39: ctx->frame[1] = ctx->inta;
40: ctx->frame[2] = ctx->intb;
41: ctx->frame[3] = ctx->right;
42: STFilter_FILTLAN_setFilter(st);
43: return(0);
44: }
46: PetscErrorCode STSetFromOptions_Filter(PetscOptionItems *PetscOptionsObject,ST st)
47: {
49: PetscReal array[2]={0,0};
50: PetscInt k;
51: PetscBool flg;
54: PetscOptionsHead(PetscOptionsObject,"ST Filter Options");
56: k = 2;
57: PetscOptionsRealArray("-st_filter_interval","Interval containing the desired eigenvalues (two real values separated with a comma without spaces)","STFilterSetInterval",array,&k,&flg);
58: if (flg) {
59: if (k<2) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_SIZ,"Must pass two values in -st_filter_interval (comma-separated without spaces)");
60: STFilterSetInterval(st,array[0],array[1]);
61: }
62: k = 2;
63: PetscOptionsRealArray("-st_filter_range","Interval containing all eigenvalues (two real values separated with a comma without spaces)","STFilterSetRange",array,&k,&flg);
64: if (flg) {
65: if (k<2) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_SIZ,"Must pass two values in -st_filter_range (comma-separated without spaces)");
66: STFilterSetRange(st,array[0],array[1]);
67: }
68: PetscOptionsInt("-st_filter_degree","Degree of filter polynomial","STFilterSetDegree",100,&k,&flg);
69: if (flg) { STFilterSetDegree(st,k); }
71: PetscOptionsTail();
72: return(0);
73: }
75: static PetscErrorCode STFilterSetInterval_Filter(ST st,PetscReal inta,PetscReal intb)
76: {
77: ST_FILTER *ctx = (ST_FILTER*)st->data;
80: if (inta>intb) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_WRONG,"Badly defined interval, must be inta<intb");
81: if (ctx->inta != inta || ctx->intb != intb) {
82: ctx->inta = inta;
83: ctx->intb = intb;
84: st->state = ST_STATE_INITIAL;
85: }
86: return(0);
87: }
89: /*@
90: STFilterSetInterval - Defines the interval containing the desired eigenvalues.
92: Logically Collective on ST
94: Input Parameters:
95: + st - the spectral transformation context
96: . inta - left end of the interval
97: - intb - right end of the interval
99: Options Database Key:
100: . -st_filter_interval <a,b> - set [a,b] as the interval of interest
102: Level: intermediate
104: Notes:
105: The filter will be configured to emphasize eigenvalues contained in the given
106: interval, and damp out eigenvalues outside it. If the interval is open, then
107: the filter is low- or high-pass, otherwise it is mid-pass.
109: Common usage is to set the interval in EPS with EPSSetInterval().
111: The interval must be contained within the numerical range of the matrix, see
112: STFilterSetRange().
114: .seealso: STFilterGetInterval(), STFilterSetRange(), EPSSetInterval()
115: @*/
116: PetscErrorCode STFilterSetInterval(ST st,PetscReal inta,PetscReal intb)
117: {
124: PetscTryMethod(st,"STFilterSetInterval_C",(ST,PetscReal,PetscReal),(st,inta,intb));
125: return(0);
126: }
128: static PetscErrorCode STFilterGetInterval_Filter(ST st,PetscReal *inta,PetscReal *intb)
129: {
130: ST_FILTER *ctx = (ST_FILTER*)st->data;
133: if (inta) *inta = ctx->inta;
134: if (intb) *intb = ctx->intb;
135: return(0);
136: }
138: /*@
139: STFilterGetInterval - Gets the interval containing the desired eigenvalues.
141: Not Collective
143: Input Parameter:
144: . st - the spectral transformation context
146: Output Parameter:
147: + inta - left end of the interval
148: - intb - right end of the interval
150: Level: intermediate
152: .seealso: STFilterSetInterval()
153: @*/
154: PetscErrorCode STFilterGetInterval(ST st,PetscReal *inta,PetscReal *intb)
155: {
160: PetscUseMethod(st,"STFilterGetInterval_C",(ST,PetscReal*,PetscReal*),(st,inta,intb));
161: return(0);
162: }
164: static PetscErrorCode STFilterSetRange_Filter(ST st,PetscReal left,PetscReal right)
165: {
166: ST_FILTER *ctx = (ST_FILTER*)st->data;
169: if (left>right) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_WRONG,"Badly defined interval, must be left<right");
170: if (ctx->left != left || ctx->right != right) {
171: ctx->left = left;
172: ctx->right = right;
173: st->state = ST_STATE_INITIAL;
174: }
175: return(0);
176: }
178: /*@
179: STFilterSetRange - Defines the numerical range (or field of values) of the matrix, that is,
180: the interval containing all eigenvalues.
182: Logically Collective on ST
184: Input Parameters:
185: + st - the spectral transformation context
186: . left - left end of the interval
187: - right - right end of the interval
189: Options Database Key:
190: . -st_filter_range <a,b> - set [a,b] as the numerical range
192: Level: intermediate
194: Notes:
195: The filter will be most effective if the numerical range is tight, that is, left and right
196: are good approximations to the leftmost and rightmost eigenvalues, respectively.
198: .seealso: STFilterGetRange(), STFilterSetInterval()
199: @*/
200: PetscErrorCode STFilterSetRange(ST st,PetscReal left,PetscReal right)
201: {
208: PetscTryMethod(st,"STFilterSetRange_C",(ST,PetscReal,PetscReal),(st,left,right));
209: return(0);
210: }
212: static PetscErrorCode STFilterGetRange_Filter(ST st,PetscReal *left,PetscReal *right)
213: {
214: ST_FILTER *ctx = (ST_FILTER*)st->data;
217: if (left) *left = ctx->left;
218: if (right) *right = ctx->right;
219: return(0);
220: }
222: /*@
223: STFilterGetRange - Gets the interval containing all eigenvalues.
225: Not Collective
227: Input Parameter:
228: . st - the spectral transformation context
230: Output Parameter:
231: + left - left end of the interval
232: - right - right end of the interval
234: Level: intermediate
236: .seealso: STFilterSetRange()
237: @*/
238: PetscErrorCode STFilterGetRange(ST st,PetscReal *left,PetscReal *right)
239: {
244: PetscUseMethod(st,"STFilterGetRange_C",(ST,PetscReal*,PetscReal*),(st,left,right));
245: return(0);
246: }
248: static PetscErrorCode STFilterSetDegree_Filter(ST st,PetscInt deg)
249: {
250: ST_FILTER *ctx = (ST_FILTER*)st->data;
253: if (deg == PETSC_DEFAULT || deg == PETSC_DECIDE) {
254: ctx->polyDegree = 0;
255: st->state = ST_STATE_INITIAL;
256: } else {
257: if (deg<=0) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of degree. Must be > 0");
258: if (ctx->polyDegree != deg) {
259: ctx->polyDegree = deg;
260: st->state = ST_STATE_INITIAL;
261: }
262: }
263: return(0);
264: }
266: /*@
267: STFilterSetDegree - Sets the degree of the filter polynomial.
269: Logically Collective on ST
271: Input Parameters:
272: + st - the spectral transformation context
273: - deg - polynomial degree
275: Options Database Key:
276: . -st_filter_degree <deg> - sets the degree of the filter polynomial
278: Level: intermediate
280: .seealso: STFilterGetDegree()
281: @*/
282: PetscErrorCode STFilterSetDegree(ST st,PetscInt deg)
283: {
289: PetscTryMethod(st,"STFilterSetDegree_C",(ST,PetscInt),(st,deg));
290: return(0);
291: }
293: static PetscErrorCode STFilterGetDegree_Filter(ST st,PetscInt *deg)
294: {
295: ST_FILTER *ctx = (ST_FILTER*)st->data;
298: *deg = ctx->polyDegree;
299: return(0);
300: }
302: /*@
303: STFilterGetDegree - Gets the degree of the filter polynomial.
305: Not Collective
307: Input Parameter:
308: . st - the spectral transformation context
310: Output Parameter:
311: . deg - polynomial degree
313: Level: intermediate
315: .seealso: STFilterSetDegree()
316: @*/
317: PetscErrorCode STFilterGetDegree(ST st,PetscInt *deg)
318: {
324: PetscUseMethod(st,"STFilterGetDegree_C",(ST,PetscInt*),(st,deg));
325: return(0);
326: }
328: static PetscErrorCode STFilterGetThreshold_Filter(ST st,PetscReal *gamma)
329: {
330: ST_FILTER *ctx = (ST_FILTER*)st->data;
333: *gamma = ctx->filterInfo->yLimit;
334: return(0);
335: }
337: /*@
338: STFilterGetThreshold - Gets the threshold value gamma such that rho(lambda)>=gamma for
339: eigenvalues lambda inside the wanted interval and rho(lambda)<gamma for those outside.
341: Not Collective
343: Input Parameter:
344: . st - the spectral transformation context
346: Output Parameter:
347: . gamma - the threshold value
349: Level: developer
350: @*/
351: PetscErrorCode STFilterGetThreshold(ST st,PetscReal *gamma)
352: {
358: PetscUseMethod(st,"STFilterGetThreshold_C",(ST,PetscReal*),(st,gamma));
359: return(0);
360: }
362: PetscErrorCode STView_Filter(ST st,PetscViewer viewer)
363: {
365: ST_FILTER *ctx = (ST_FILTER*)st->data;
366: PetscBool isascii;
369: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
370: if (isascii) {
371: PetscViewerASCIIPrintf(viewer," Filter: interval of desired eigenvalues is [%g,%g]\n",(double)ctx->inta,(double)ctx->intb);
372: PetscViewerASCIIPrintf(viewer," Filter: numerical range is [%g,%g]\n",(double)ctx->left,(double)ctx->right);
373: PetscViewerASCIIPrintf(viewer," Filter: degree of filter polynomial is %D\n",ctx->polyDegree);
374: if (st->state>=ST_STATE_SETUP) {
375: PetscViewerASCIIPrintf(viewer," Filter: limit to accept eigenvalues: theta=%g\n",ctx->filterInfo->yLimit);
376: }
377: }
378: return(0);
379: }
381: PetscErrorCode STDestroy_Filter(ST st)
382: {
384: ST_FILTER *ctx = (ST_FILTER*)st->data;
387: PetscFree(ctx->opts);
388: PetscFree(ctx->filterInfo);
389: PetscFree(ctx->baseFilter);
390: PetscFree(st->data);
391: PetscObjectComposeFunction((PetscObject)st,"STFilterSetInterval_C",NULL);
392: PetscObjectComposeFunction((PetscObject)st,"STFilterGetInterval_C",NULL);
393: PetscObjectComposeFunction((PetscObject)st,"STFilterSetRange_C",NULL);
394: PetscObjectComposeFunction((PetscObject)st,"STFilterGetRange_C",NULL);
395: PetscObjectComposeFunction((PetscObject)st,"STFilterSetDegree_C",NULL);
396: PetscObjectComposeFunction((PetscObject)st,"STFilterGetDegree_C",NULL);
397: PetscObjectComposeFunction((PetscObject)st,"STFilterGetThreshold_C",NULL);
398: return(0);
399: }
401: PETSC_EXTERN PetscErrorCode STCreate_Filter(ST st)
402: {
404: ST_FILTER *ctx;
405: FILTLAN_IOP iop;
406: FILTLAN_PFI pfi;
408: PetscNewLog(st,&ctx);
409: st->data = (void*)ctx;
411: ctx->inta = PETSC_MIN_REAL;
412: ctx->intb = PETSC_MAX_REAL;
413: ctx->left = PETSC_MIN_REAL;
414: ctx->right = PETSC_MAX_REAL;
415: ctx->polyDegree = 0;
416: ctx->baseDegree = 10;
418: PetscNewLog(st,&iop);
419: ctx->opts = iop;
420: iop->intervalWeights[0] = 100.0;
421: iop->intervalWeights[1] = 1.0;
422: iop->intervalWeights[2] = 1.0;
423: iop->intervalWeights[3] = 1.0;
424: iop->intervalWeights[4] = 100.0;
425: iop->transIntervalRatio = 0.6;
426: iop->reverseInterval = PETSC_FALSE;
427: iop->initialPlateau = 0.1;
428: iop->plateauShrinkRate = 1.5;
429: iop->initialShiftStep = 0.01;
430: iop->shiftStepExpanRate = 1.5;
431: iop->maxInnerIter = 30;
432: iop->yLimitTol = 0.0001;
433: iop->maxOuterIter = 50;
434: iop->numGridPoints = 200;
435: iop->yBottomLine = 0.001;
436: iop->yRippleLimit = 0.8;
438: PetscNewLog(st,&pfi);
439: ctx->filterInfo = pfi;
441: st->ops->apply = STApply_Filter;
442: st->ops->setfromoptions = STSetFromOptions_Filter;
443: st->ops->setup = STSetUp_Filter;
444: st->ops->destroy = STDestroy_Filter;
445: st->ops->view = STView_Filter;
447: PetscObjectComposeFunction((PetscObject)st,"STFilterSetInterval_C",STFilterSetInterval_Filter);
448: PetscObjectComposeFunction((PetscObject)st,"STFilterGetInterval_C",STFilterGetInterval_Filter);
449: PetscObjectComposeFunction((PetscObject)st,"STFilterSetRange_C",STFilterSetRange_Filter);
450: PetscObjectComposeFunction((PetscObject)st,"STFilterGetRange_C",STFilterGetRange_Filter);
451: PetscObjectComposeFunction((PetscObject)st,"STFilterSetDegree_C",STFilterSetDegree_Filter);
452: PetscObjectComposeFunction((PetscObject)st,"STFilterGetDegree_C",STFilterGetDegree_Filter);
453: PetscObjectComposeFunction((PetscObject)st,"STFilterGetThreshold_C",STFilterGetThreshold_Filter);
454: return(0);
455: }