Actual source code: rgring.c
slepc-3.7.3 2016-09-29
1: /*
2: Ring region, similar to the ellipse but with a start and end angle,
3: together with the width.
5: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6: SLEPc - Scalable Library for Eigenvalue Problem Computations
7: Copyright (c) 2002-2016, Universitat Politecnica de Valencia, Spain
9: This file is part of SLEPc.
11: SLEPc is free software: you can redistribute it and/or modify it under the
12: terms of version 3 of the GNU Lesser General Public License as published by
13: the Free Software Foundation.
15: SLEPc is distributed in the hope that it will be useful, but WITHOUT ANY
16: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17: FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
18: more details.
20: You should have received a copy of the GNU Lesser General Public License
21: along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
22: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
23: */
25: #include <slepc/private/rgimpl.h> /*I "slepcrg.h" I*/
27: typedef struct {
28: PetscScalar center; /* center of the ellipse */
29: PetscReal radius; /* radius of the ellipse */
30: PetscReal vscale; /* vertical scale of the ellipse */
31: PetscReal start_ang; /* start angle */
32: PetscReal end_ang; /* end angle */
33: PetscReal width; /* ring width */
34: } RG_RING;
38: static PetscErrorCode RGRingSetParameters_Ring(RG rg,PetscScalar center,PetscReal radius,PetscReal vscale,PetscReal start_ang,PetscReal end_ang,PetscReal width)
39: {
40: RG_RING *ctx = (RG_RING*)rg->data;
43: ctx->center = center;
44: if (radius == PETSC_DEFAULT) {
45: ctx->radius = 1.0;
46: } else {
47: if (radius<=0.0) SETERRQ(PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The radius argument must be > 0.0");
48: ctx->radius = radius;
49: }
50: if (vscale<=0.0) SETERRQ(PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The vscale argument must be > 0.0");
51: ctx->vscale = vscale;
52: if (start_ang == PETSC_DEFAULT) {
53: ctx->start_ang = 0.0;
54: } else {
55: if (start_ang<0.0) SETERRQ(PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The right-hand side angle argument must be >= 0.0");
56: if (start_ang>1.0) SETERRQ(PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The right-hand side angle argument must be <= 1.0");
57: ctx->start_ang = start_ang;
58: }
59: if (end_ang == PETSC_DEFAULT) {
60: ctx->end_ang = 1.0;
61: } else {
62: if (end_ang<0.0) SETERRQ(PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The left-hand side angle argument must be >= 0.0");
63: if (end_ang>1.0) SETERRQ(PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The left-hand side angle argument must be <= 1.0");
64: ctx->end_ang = end_ang;
65: }
66: if (ctx->start_ang>ctx->end_ang) SETERRQ(PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The right-hand side angle argument must be smaller than left one");
67: if (width == PETSC_DEFAULT) {
68: ctx->width = 0.1;
69: } else {
70: if (width<=0.0) SETERRQ(PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The width argument must be > 0.0");
71: ctx->width = width;
72: }
73: return(0);
74: }
78: /*@
79: RGRingSetParameters - Sets the parameters defining the ring region.
81: Logically Collective on RG
83: Input Parameters:
84: + rg - the region context
85: . center - center of the ellipse
86: . radius - radius of the ellipse
87: . vscale - vertical scale of the ellipse
88: . start_ang - the right-hand side angle
89: . end_ang - the left-hand side angle
90: - width - width of the ring
92: Options Database Keys:
93: + -rg_ring_center - Sets the center
94: . -rg_ring_radius - Sets the radius
95: . -rg_ring_vscale - Sets the vertical scale
96: . -rg_ring_startangle - Sets the right-hand side angle
97: . -rg_ring_endangle - Sets the left-hand side angle
98: - -rg_ring_width - Sets the width of the ring
100: Notes:
101: The values of center, radius and vscale have the same meaning as in the
102: ellipse region. The startangle and endangle define the span of the ring
103: (by default it is the whole ring), while the width is the separation
104: between the two concentric ellipses (above and below the radius by
105: width/2). The start and end angles are expressed as a fraction of the
106: circumference: the allowed range is [0..1], with 0 corresponding to 0
107: radians, 0.25 to pi/2 radians, and so on.
109: In the case of complex scalars, a complex center can be provided in the
110: command line with [+/-][realnumber][+/-]realnumberi with no spaces, e.g.
111: -rg_ring_center 1.0+2.0i
113: When PETSc is built with real scalars, the center is restricted to a real value.
115: Level: advanced
117: .seealso: RGRingGetParameters()
118: @*/
119: PetscErrorCode RGRingSetParameters(RG rg,PetscScalar center,PetscReal radius,PetscReal vscale,PetscReal start_ang,PetscReal end_ang,PetscReal width)
120: {
131: PetscTryMethod(rg,"RGRingSetParameters_C",(RG,PetscScalar,PetscReal,PetscReal,PetscReal,PetscReal,PetscReal),(rg,center,radius,vscale,start_ang,end_ang,width));
132: return(0);
133: }
137: static PetscErrorCode RGRingGetParameters_Ring(RG rg,PetscScalar *center,PetscReal *radius,PetscReal *vscale,PetscReal *start_ang,PetscReal *end_ang,PetscReal *width)
138: {
139: RG_RING *ctx = (RG_RING*)rg->data;
142: if (center) *center = ctx->center;
143: if (radius) *radius = ctx->radius;
144: if (vscale) *vscale = ctx->vscale;
145: if (start_ang) *start_ang = ctx->start_ang;
146: if (end_ang) *end_ang = ctx->end_ang;
147: if (width) *width = ctx->width;
148: return(0);
149: }
153: /*@
154: RGRingGetParameters - Gets the parameters that define the ring region.
156: Not Collective
158: Input Parameter:
159: . rg - the region context
161: Output Parameters:
162: + center - center of the region
163: . radius - radius of the region
164: . vscale - vertical scale of the region
165: . start_ang - the right-hand side angle
166: . end_ang - the left-hand side angle
167: - width - width of the ring
169: Level: advanced
171: .seealso: RGRingSetParameters()
172: @*/
173: PetscErrorCode RGRingGetParameters(RG rg,PetscScalar *center,PetscReal *radius,PetscReal *vscale,PetscReal *start_ang,PetscReal *end_ang,PetscReal *width)
174: {
179: PetscUseMethod(rg,"RGRingGetParameters_C",(RG,PetscScalar*,PetscReal*,PetscReal*,PetscReal*,PetscReal*,PetscReal*),(rg,center,radius,vscale,start_ang,end_ang,width));
180: return(0);
181: }
185: PetscErrorCode RGView_Ring(RG rg,PetscViewer viewer)
186: {
188: RG_RING *ctx = (RG_RING*)rg->data;
189: PetscBool isascii;
190: char str[50];
193: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
194: if (isascii) {
195: SlepcSNPrintfScalar(str,50,ctx->center,PETSC_FALSE);
196: PetscViewerASCIIPrintf(viewer,"center: %s, radius: %g, vscale: %g, start angle: %g, end angle: %g, ring width: %g\n",str,RGShowReal(ctx->radius),RGShowReal(ctx->vscale),ctx->start_ang,ctx->end_ang,ctx->width);
197: }
198: return(0);
199: }
203: PetscErrorCode RGIsTrivial_Ring(RG rg,PetscBool *trivial)
204: {
205: RG_RING *ctx = (RG_RING*)rg->data;
208: if (rg->complement) *trivial = PetscNot(ctx->radius);
209: else *trivial = PetscNot(ctx->radius<PETSC_MAX_REAL);
210: return(0);
211: }
215: PetscErrorCode RGComputeContour_Ring(RG rg,PetscInt n,PetscScalar *cr,PetscScalar *ci)
216: {
217: RG_RING *ctx = (RG_RING*)rg->data;
218: PetscReal theta;
219: PetscInt i,n2=n/2;
222: for (i=0;i<n;i++) {
223: if (i < n2) {
224: theta = ((ctx->end_ang-ctx->start_ang)*i/n2 + ctx->start_ang)*2.0*PETSC_PI;
225: #if defined(PETSC_USE_COMPLEX)
226: cr[i] = ctx->center + (ctx->radius+ctx->width/2.0)*(PetscCosReal(theta)+ctx->vscale*PetscSinReal(theta)*PETSC_i);
227: #else
228: cr[i] = ctx->center + (ctx->radius+ctx->width/2.0)*PetscCosReal(theta);
229: ci[i] = (ctx->radius+ctx->width/2.0)*ctx->vscale*PetscSinReal(theta);
230: #endif
231: } else {
232: theta = ((ctx->end_ang-ctx->start_ang)*(n-i)/n2 + ctx->start_ang)*2.0*PETSC_PI;
233: #if defined(PETSC_USE_COMPLEX)
234: cr[i] = ctx->center + (ctx->radius-ctx->width/2.0)*(PetscCosReal(theta)+ctx->vscale*PetscSinReal(theta)*PETSC_i);
235: #else
236: cr[i] = ctx->center + (ctx->radius-ctx->width/2.0)*PetscCosReal(theta);
237: ci[i] = (ctx->radius-ctx->width/2.0)*ctx->vscale*PetscSinReal(theta);
238: #endif
239: }
240: }
241: return(0);
242: }
246: PetscErrorCode RGCheckInside_Ring(RG rg,PetscReal px,PetscReal py,PetscInt *inside)
247: {
248: RG_RING *ctx = (RG_RING*)rg->data;
249: PetscReal dx,dy,r;
252: /* outer ellipse */
253: #if defined(PETSC_USE_COMPLEX)
254: dx = (px-PetscRealPart(ctx->center))/(ctx->radius+ctx->width/2.0);
255: dy = (py-PetscImaginaryPart(ctx->center))/(ctx->radius+ctx->width/2.0);
256: #else
257: dx = (px-ctx->center)/(ctx->radius+ctx->width/2.0);
258: dy = py/(ctx->radius+ctx->width/2.0);
259: #endif
260: r = 1.0-dx*dx-(dy*dy)/(ctx->vscale*ctx->vscale);
261: *inside = PetscSign(r);
262: /* inner ellipse */
263: #if defined(PETSC_USE_COMPLEX)
264: dx = (px-PetscRealPart(ctx->center))/(ctx->radius-ctx->width/2.0);
265: dy = (py-PetscImaginaryPart(ctx->center))/(ctx->radius-ctx->width/2.0);
266: #else
267: dx = (px-ctx->center)/(ctx->radius-ctx->width/2.0);
268: dy = py/(ctx->radius-ctx->width/2.0);
269: #endif
270: r = -1.0+dx*dx+(dy*dy)/(ctx->vscale*ctx->vscale);
271: *inside *= PetscSign(r);
272: /* check angles */
273: #if defined(PETSC_USE_COMPLEX)
274: dx = (px-PetscRealPart(ctx->center));
275: dy = (py-PetscImaginaryPart(ctx->center));
276: #else
277: dx = px-ctx->center;
278: dy = py;
279: #endif
280: if (dx == 0) {
281: if (dy == 0) r = -1;
282: else if (dy > 0) r = 0.25;
283: else r = 0.75;
284: } else if (dx > 0) {
285: r = PetscAtanReal((dy/ctx->vscale)/dx);
286: if (dy >= 0) r /= 2*PETSC_PI;
287: else r = r/(2*PETSC_PI)+1;
288: } else r = PetscAtanReal((dy/ctx->vscale)/dx)/(2*PETSC_PI)+0.5;
289: if (r>=ctx->start_ang && r<=ctx->end_ang && *inside == 1) *inside = 1;
290: else *inside = -1;
291: return(0);
292: }
296: PetscErrorCode RGSetFromOptions_Ring(PetscOptionItems *PetscOptionsObject,RG rg)
297: {
299: PetscScalar s;
300: PetscReal r1,r2,r3,r4,r5;
301: PetscBool flg1,flg2,flg3,flg4,flg5,flg6;
304: PetscOptionsHead(PetscOptionsObject,"RG Ring Options");
306: RGRingGetParameters(rg,&s,&r1,&r2,&r3,&r4,&r5);
307: PetscOptionsScalar("-rg_ring_center","Center of ellipse","RGRingSetParameters",s,&s,&flg1);
308: PetscOptionsReal("-rg_ring_radius","Radius of ellipse","RGRingSetParameters",r1,&r1,&flg2);
309: PetscOptionsReal("-rg_ring_vscale","Vertical scale of ellipse","RGRingSetParameters",r2,&r2,&flg3);
310: PetscOptionsReal("-rg_ring_startangle","Right-hand side angle","RGRingSetParameters",r3,&r3,&flg4);
311: PetscOptionsReal("-rg_ring_endangle","Left-hand side angle","RGRingSetParameters",r4,&r4,&flg5);
312: PetscOptionsReal("-rg_ring_width","Width of ring","RGRingSetParameters",r5,&r5,&flg6);
313: if (flg1 || flg2 || flg3 || flg4 || flg5 || flg6) {
314: RGRingSetParameters(rg,s,r1,r2,r3,r4,r5);
315: }
317: PetscOptionsTail();
318: return(0);
319: }
323: PetscErrorCode RGDestroy_Ring(RG rg)
324: {
328: PetscFree(rg->data);
329: PetscObjectComposeFunction((PetscObject)rg,"RGRingSetParameters_C",NULL);
330: PetscObjectComposeFunction((PetscObject)rg,"RGRingGetParameters_C",NULL);
331: return(0);
332: }
336: PETSC_EXTERN PetscErrorCode RGCreate_Ring(RG rg)
337: {
338: RG_RING *ring;
342: PetscNewLog(rg,&ring);
343: ring->center = 0.0;
344: ring->radius = 1.0;
345: ring->vscale = 1.0;
346: ring->start_ang = 0.0;
347: ring->end_ang = 1.0;
348: ring->width = 0.1;
349: rg->data = (void*)ring;
351: rg->ops->istrivial = RGIsTrivial_Ring;
352: rg->ops->computecontour = RGComputeContour_Ring;
353: rg->ops->checkinside = RGCheckInside_Ring;
354: rg->ops->setfromoptions = RGSetFromOptions_Ring;
355: rg->ops->view = RGView_Ring;
356: rg->ops->destroy = RGDestroy_Ring;
357: PetscObjectComposeFunction((PetscObject)rg,"RGRingSetParameters_C",RGRingSetParameters_Ring);
358: PetscObjectComposeFunction((PetscObject)rg,"RGRingGetParameters_C",RGRingGetParameters_Ring);
359: return(0);
360: }