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 : Ring region, similar to the ellipse but with a start and end angle,
12 : together with the width
13 : */
14 :
15 : #include <slepc/private/rgimpl.h> /*I "slepcrg.h" I*/
16 : #include <petscdraw.h>
17 :
18 : typedef struct {
19 : PetscScalar center; /* center of the ellipse */
20 : PetscReal radius; /* radius of the ellipse */
21 : PetscReal vscale; /* vertical scale of the ellipse */
22 : PetscReal start_ang; /* start angle */
23 : PetscReal end_ang; /* end angle */
24 : PetscReal width; /* ring width */
25 : } RG_RING;
26 :
27 19 : static PetscErrorCode RGRingSetParameters_Ring(RG rg,PetscScalar center,PetscReal radius,PetscReal vscale,PetscReal start_ang,PetscReal end_ang,PetscReal width)
28 : {
29 19 : RG_RING *ctx = (RG_RING*)rg->data;
30 :
31 19 : PetscFunctionBegin;
32 19 : ctx->center = center;
33 19 : if (radius == (PetscReal)PETSC_DETERMINE) {
34 5 : ctx->radius = 1.0;
35 14 : } else if (radius != (PetscReal)PETSC_CURRENT) {
36 14 : PetscCheck(radius>0.0,PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The radius argument must be > 0.0");
37 14 : ctx->radius = radius;
38 : }
39 19 : if (vscale == (PetscReal)PETSC_DETERMINE) {
40 0 : ctx->vscale = 1.0;
41 19 : } else if (vscale != (PetscReal)PETSC_CURRENT) {
42 19 : PetscCheck(vscale>0.0,PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The vscale argument must be > 0.0");
43 19 : ctx->vscale = vscale;
44 : }
45 19 : if (start_ang == (PetscReal)PETSC_DETERMINE) {
46 0 : ctx->start_ang = 0.0;
47 19 : } else if (start_ang != (PetscReal)PETSC_CURRENT) {
48 19 : PetscCheck(start_ang>=0.0,PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The right-hand side angle argument must be >= 0.0");
49 19 : PetscCheck(start_ang<=1.0,PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The right-hand side angle argument must be <= 1.0");
50 19 : ctx->start_ang = start_ang;
51 : }
52 19 : if (end_ang == (PetscReal)PETSC_DETERMINE) {
53 0 : ctx->end_ang = 1.0;
54 19 : } else if (end_ang != (PetscReal)PETSC_CURRENT) {
55 19 : PetscCheck(end_ang>=0.0,PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The left-hand side angle argument must be >= 0.0");
56 19 : PetscCheck(end_ang<=1.0,PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The left-hand side angle argument must be <= 1.0");
57 19 : ctx->end_ang = end_ang;
58 : }
59 : #if !defined(PETSC_USE_COMPLEX)
60 : PetscCheck(ctx->start_ang+ctx->end_ang==1.0,PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_WRONG,"In real scalars the region must be symmetric wrt real axis");
61 : #endif
62 19 : if (width == (PetscReal)PETSC_DETERMINE) {
63 0 : ctx->width = 0.1;
64 19 : } else if (width != (PetscReal)PETSC_CURRENT) {
65 19 : PetscCheck(width>0.0,PetscObjectComm((PetscObject)rg),PETSC_ERR_ARG_OUTOFRANGE,"The width argument must be > 0.0");
66 19 : ctx->width = width;
67 : }
68 19 : PetscFunctionReturn(PETSC_SUCCESS);
69 : }
70 :
71 : /*@
72 : RGRingSetParameters - Sets the parameters defining the ring region.
73 :
74 : Logically Collective
75 :
76 : Input Parameters:
77 : + rg - the region context
78 : . center - center of the ellipse
79 : . radius - radius of the ellipse
80 : . vscale - vertical scale of the ellipse
81 : . start_ang - the right-hand side angle
82 : . end_ang - the left-hand side angle
83 : - width - width of the ring
84 :
85 : Options Database Keys:
86 : + -rg_ring_center - Sets the center
87 : . -rg_ring_radius - Sets the radius
88 : . -rg_ring_vscale - Sets the vertical scale
89 : . -rg_ring_startangle - Sets the right-hand side angle
90 : . -rg_ring_endangle - Sets the left-hand side angle
91 : - -rg_ring_width - Sets the width of the ring
92 :
93 : Notes:
94 : The values of center, radius and vscale have the same meaning as in the
95 : ellipse region. The startangle and endangle define the span of the ring
96 : (by default it is the whole ring), while the width is the separation
97 : between the two concentric ellipses (above and below the radius by
98 : width/2).
99 :
100 : The start and end angles are expressed as a fraction of the circumference.
101 : The allowed range is [0..1], with 0 corresponding to 0 radians, 0.25 to
102 : pi/2 radians, and so on. It is allowed to have startangle>endangle, in
103 : which case the ring region crosses over the zero angle.
104 :
105 : In the case of complex scalars, a complex center can be provided in the
106 : command line with [+/-][realnumber][+/-]realnumberi with no spaces, e.g.
107 : -rg_ring_center 1.0+2.0i
108 :
109 : When PETSc is built with real scalars, the center is restricted to a real value,
110 : and the start and end angles must be such that the region is symmetric with
111 : respect to the real axis.
112 :
113 : For all arguments except center, you can use PETSC_CURRENT to keep the current
114 : value, and PETSC_DETERMINE to set them to a default value (1 for radius, vscale,
115 : end_ang, 0 for start_and, and 0.1 for width).
116 :
117 : Level: advanced
118 :
119 : .seealso: RGRingGetParameters()
120 : @*/
121 19 : PetscErrorCode RGRingSetParameters(RG rg,PetscScalar center,PetscReal radius,PetscReal vscale,PetscReal start_ang,PetscReal end_ang,PetscReal width)
122 : {
123 19 : PetscFunctionBegin;
124 19 : PetscValidHeaderSpecific(rg,RG_CLASSID,1);
125 57 : PetscValidLogicalCollectiveScalar(rg,center,2);
126 57 : PetscValidLogicalCollectiveReal(rg,radius,3);
127 57 : PetscValidLogicalCollectiveReal(rg,vscale,4);
128 57 : PetscValidLogicalCollectiveReal(rg,start_ang,5);
129 57 : PetscValidLogicalCollectiveReal(rg,end_ang,6);
130 57 : PetscValidLogicalCollectiveReal(rg,width,7);
131 19 : PetscTryMethod(rg,"RGRingSetParameters_C",(RG,PetscScalar,PetscReal,PetscReal,PetscReal,PetscReal,PetscReal),(rg,center,radius,vscale,start_ang,end_ang,width));
132 19 : PetscFunctionReturn(PETSC_SUCCESS);
133 : }
134 :
135 24 : static PetscErrorCode RGRingGetParameters_Ring(RG rg,PetscScalar *center,PetscReal *radius,PetscReal *vscale,PetscReal *start_ang,PetscReal *end_ang,PetscReal *width)
136 : {
137 24 : RG_RING *ctx = (RG_RING*)rg->data;
138 :
139 24 : PetscFunctionBegin;
140 24 : if (center) *center = ctx->center;
141 24 : if (radius) *radius = ctx->radius;
142 24 : if (vscale) *vscale = ctx->vscale;
143 24 : if (start_ang) *start_ang = ctx->start_ang;
144 24 : if (end_ang) *end_ang = ctx->end_ang;
145 24 : if (width) *width = ctx->width;
146 24 : PetscFunctionReturn(PETSC_SUCCESS);
147 : }
148 :
149 : /*@
150 : RGRingGetParameters - Gets the parameters that define the ring region.
151 :
152 : Not Collective
153 :
154 : Input Parameter:
155 : . rg - the region context
156 :
157 : Output Parameters:
158 : + center - center of the region
159 : . radius - radius of the region
160 : . vscale - vertical scale of the region
161 : . start_ang - the right-hand side angle
162 : . end_ang - the left-hand side angle
163 : - width - width of the ring
164 :
165 : Level: advanced
166 :
167 : .seealso: RGRingSetParameters()
168 : @*/
169 24 : PetscErrorCode RGRingGetParameters(RG rg,PetscScalar *center,PetscReal *radius,PetscReal *vscale,PetscReal *start_ang,PetscReal *end_ang,PetscReal *width)
170 : {
171 24 : PetscFunctionBegin;
172 24 : PetscValidHeaderSpecific(rg,RG_CLASSID,1);
173 24 : PetscUseMethod(rg,"RGRingGetParameters_C",(RG,PetscScalar*,PetscReal*,PetscReal*,PetscReal*,PetscReal*,PetscReal*),(rg,center,radius,vscale,start_ang,end_ang,width));
174 24 : PetscFunctionReturn(PETSC_SUCCESS);
175 : }
176 :
177 6 : static PetscErrorCode RGView_Ring(RG rg,PetscViewer viewer)
178 : {
179 6 : RG_RING *ctx = (RG_RING*)rg->data;
180 6 : int winw,winh;
181 6 : PetscBool isdraw,isascii;
182 6 : PetscDraw draw;
183 6 : PetscDrawAxis axis;
184 6 : PetscReal cx,cy,radius,width,ab,cd,lx,ly,w,end_ang,x1,y1,x2,y2,r,theta,scale=1.2;
185 6 : char str[50];
186 :
187 6 : PetscFunctionBegin;
188 6 : PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw));
189 6 : PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
190 6 : if (isascii) {
191 5 : PetscCall(SlepcSNPrintfScalar(str,sizeof(str),ctx->center,PETSC_FALSE));
192 5 : PetscCall(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),(double)ctx->start_ang,(double)ctx->end_ang,(double)ctx->width));
193 1 : } else if (isdraw) {
194 1 : PetscCall(PetscViewerDrawGetDraw(viewer,0,&draw));
195 1 : PetscCall(PetscDrawCheckResizedWindow(draw));
196 1 : PetscCall(PetscDrawGetWindowSize(draw,&winw,&winh));
197 1 : winw = PetscMax(winw,1); winh = PetscMax(winh,1);
198 1 : PetscCall(PetscDrawClear(draw));
199 1 : PetscCall(PetscDrawSetTitle(draw,"Ring region"));
200 1 : PetscCall(PetscDrawAxisCreate(draw,&axis));
201 1 : cx = PetscRealPart(ctx->center)*rg->sfactor;
202 1 : cy = PetscImaginaryPart(ctx->center)*rg->sfactor;
203 1 : radius = ctx->radius*rg->sfactor;
204 1 : width = ctx->width*rg->sfactor;
205 1 : lx = 2*(radius+width);
206 1 : ly = 2*(radius+width)*ctx->vscale;
207 1 : ab = cx;
208 1 : cd = cy;
209 1 : w = scale*PetscMax(lx/winw,ly/winh)/2;
210 1 : PetscCall(PetscDrawAxisSetLimits(axis,ab-w*winw,ab+w*winw,cd-w*winh,cd+w*winh));
211 1 : PetscCall(PetscDrawAxisDraw(axis));
212 1 : PetscCall(PetscDrawAxisDestroy(&axis));
213 : /* draw outer ellipse */
214 1 : PetscCall(PetscDrawEllipse(draw,cx,cy,2*(radius+width),2*(radius+width)*ctx->vscale,PETSC_DRAW_ORANGE));
215 : /* remove inner part */
216 1 : PetscCall(PetscDrawEllipse(draw,cx,cy,2*(radius-width),2*(radius-width)*ctx->vscale,PETSC_DRAW_WHITE));
217 1 : if (ctx->start_ang!=ctx->end_ang) {
218 : /* remove section from end_ang to start_ang */
219 1 : end_ang = (ctx->start_ang<ctx->end_ang)? ctx->end_ang-1: ctx->end_ang;
220 1 : theta = end_ang;
221 1 : r = scale*(radius+width);
222 1 : if (ctx->vscale>1) r *= ctx->vscale;
223 2 : x1 = PetscMin(PetscMax(ab+r*PetscCosReal(2.0*PETSC_PI*theta),ab-w*winw),ab+w*winw);
224 2 : y1 = PetscMin(PetscMax(cd+r*PetscSinReal(2.0*PETSC_PI*theta),cd-w*winh),cd+w*winh);
225 4 : do {
226 4 : theta = PetscMin(PetscFloorReal(8*theta+1)/8,ctx->start_ang);
227 8 : x2 = PetscMin(PetscMax(ab+r*PetscCosReal(2.0*PETSC_PI*theta),ab-w*winw),ab+w*winw);
228 8 : y2 = PetscMin(PetscMax(cd+r*PetscSinReal(2.0*PETSC_PI*theta),cd-w*winh),cd+w*winh);
229 4 : PetscCall(PetscDrawTriangle(draw,cx,cy,x1,y1,x2,y2,PETSC_DRAW_WHITE,PETSC_DRAW_WHITE,PETSC_DRAW_WHITE));
230 4 : x1 = x2; y1 = y2;
231 4 : } while (theta<ctx->start_ang);
232 : }
233 1 : PetscCall(PetscDrawFlush(draw));
234 1 : PetscCall(PetscDrawSave(draw));
235 1 : PetscCall(PetscDrawPause(draw));
236 : }
237 6 : PetscFunctionReturn(PETSC_SUCCESS);
238 : }
239 :
240 13 : static PetscErrorCode RGIsTrivial_Ring(RG rg,PetscBool *trivial)
241 : {
242 13 : RG_RING *ctx = (RG_RING*)rg->data;
243 :
244 13 : PetscFunctionBegin;
245 13 : if (rg->complement) *trivial = PetscNot(ctx->radius);
246 13 : else *trivial = PetscNot(ctx->radius<PETSC_MAX_REAL);
247 13 : PetscFunctionReturn(PETSC_SUCCESS);
248 : }
249 :
250 8 : static PetscErrorCode RGComputeContour_Ring(RG rg,PetscInt n,PetscScalar *cr,PetscScalar *ci)
251 : {
252 8 : RG_RING *ctx = (RG_RING*)rg->data;
253 8 : PetscReal theta,start_ang;
254 8 : PetscInt i,n2=n/2;
255 :
256 8 : PetscFunctionBegin;
257 8 : start_ang = (ctx->start_ang>ctx->end_ang)? ctx->start_ang-1: ctx->start_ang;
258 159 : for (i=0;i<n;i++) {
259 151 : if (i < n2) {
260 73 : theta = ((ctx->end_ang-start_ang)*i/n2 + start_ang)*2.0*PETSC_PI;
261 : #if defined(PETSC_USE_COMPLEX)
262 73 : cr[i] = ctx->center + (ctx->radius+ctx->width/2.0)*PetscCMPLX(PetscCosReal(theta),ctx->vscale*PetscSinReal(theta));
263 : #else
264 : if (cr) cr[i] = ctx->center + (ctx->radius+ctx->width/2.0)*PetscCosReal(theta);
265 : if (ci) ci[i] = (ctx->radius+ctx->width/2.0)*ctx->vscale*PetscSinReal(theta);
266 : #endif
267 : } else {
268 78 : theta = ((ctx->end_ang-start_ang)*(n-i)/n2 + start_ang)*2.0*PETSC_PI;
269 : #if defined(PETSC_USE_COMPLEX)
270 78 : cr[i] = ctx->center + (ctx->radius-ctx->width/2.0)*PetscCMPLX(PetscCosReal(theta),ctx->vscale*PetscSinReal(theta));
271 : #else
272 : if (cr) cr[i] = ctx->center + (ctx->radius-ctx->width/2.0)*PetscCosReal(theta);
273 : if (ci) ci[i] = (ctx->radius-ctx->width/2.0)*ctx->vscale*PetscSinReal(theta);
274 : #endif
275 : }
276 : }
277 8 : PetscFunctionReturn(PETSC_SUCCESS);
278 : }
279 :
280 5 : static PetscErrorCode RGComputeBoundingBox_Ring(RG rg,PetscReal *a,PetscReal *b,PetscReal *c,PetscReal *d)
281 : {
282 5 : RG_RING *ctx = (RG_RING*)rg->data;
283 :
284 5 : PetscFunctionBegin;
285 : /* current implementation does not return a tight bounding box */
286 5 : if (a) *a = PetscRealPart(ctx->center) - (ctx->radius+ctx->width/2.0);
287 5 : if (b) *b = PetscRealPart(ctx->center) + (ctx->radius+ctx->width/2.0);
288 5 : if (c) *c = PetscImaginaryPart(ctx->center) - (ctx->radius+ctx->width/2.0)*ctx->vscale;
289 5 : if (d) *d = PetscImaginaryPart(ctx->center) + (ctx->radius+ctx->width/2.0)*ctx->vscale;
290 5 : PetscFunctionReturn(PETSC_SUCCESS);
291 : }
292 :
293 3 : static PetscErrorCode RGComputeQuadrature_Ring(RG rg,RGQuadRule quad,PetscInt n,PetscScalar *z,PetscScalar *zn,PetscScalar *w)
294 : {
295 3 : RG_RING *ctx = (RG_RING*)rg->data;
296 3 : PetscReal max_w=0.0;
297 3 : PetscScalar tmp,tmp2;
298 3 : PetscInt i,j;
299 :
300 3 : PetscFunctionBegin;
301 3 : if (quad == RG_QUADRULE_CHEBYSHEV) {
302 : #if defined(PETSC_USE_COMPLEX)
303 : PetscReal theta;
304 33 : for (i=0;i<n;i++) {
305 32 : theta = PETSC_PI*(i+0.5)/n;
306 32 : zn[i] = PetscCosReal(theta);
307 32 : w[i] = PetscCosReal((n-1)*theta)/n;
308 32 : theta = (ctx->start_ang*2.0+(ctx->end_ang-ctx->start_ang)*(PetscRealPart(zn[i])+1.0))*PETSC_PI;
309 32 : z[i] = rg->sfactor*(ctx->center + ctx->radius*PetscCMPLX(PetscCosReal(theta),ctx->vscale*PetscSinReal(theta)));
310 : }
311 : #else
312 : SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Integration points on a vertical line require complex arithmetic");
313 : #endif
314 : } else { /* RG_QUADRULE_TRAPEZOIDAL */
315 66 : for (i=0;i<n;i++) {
316 64 : zn[i] = (z[i]-rg->sfactor*ctx->center)/(rg->sfactor*ctx->radius);
317 64 : tmp = 1.0; tmp2 = 1.0;
318 2112 : for (j=0;j<n;j++) {
319 2048 : tmp *= z[j];
320 2048 : if (i != j) tmp2 *= z[j]-z[i];
321 : }
322 64 : w[i] = tmp/tmp2;
323 86 : max_w = PetscMax(PetscAbsScalar(w[i]),max_w);
324 : }
325 66 : for (i=0;i<n;i++) w[i] /= (PetscScalar)max_w;
326 : }
327 3 : PetscFunctionReturn(PETSC_SUCCESS);
328 : }
329 :
330 69 : static PetscErrorCode RGCheckInside_Ring(RG rg,PetscReal px,PetscReal py,PetscInt *inside)
331 : {
332 69 : RG_RING *ctx = (RG_RING*)rg->data;
333 69 : PetscReal dx,dy,r;
334 :
335 69 : PetscFunctionBegin;
336 : /* outer ellipse */
337 : #if defined(PETSC_USE_COMPLEX)
338 69 : dx = (px-PetscRealPart(ctx->center))/(ctx->radius+ctx->width/2.0);
339 69 : dy = (py-PetscImaginaryPart(ctx->center))/(ctx->radius+ctx->width/2.0);
340 : #else
341 : dx = (px-ctx->center)/(ctx->radius+ctx->width/2.0);
342 : dy = py/(ctx->radius+ctx->width/2.0);
343 : #endif
344 69 : r = 1.0-dx*dx-(dy*dy)/(ctx->vscale*ctx->vscale);
345 69 : *inside = PetscSign(r);
346 : /* inner ellipse */
347 : #if defined(PETSC_USE_COMPLEX)
348 69 : dx = (px-PetscRealPart(ctx->center))/(ctx->radius-ctx->width/2.0);
349 69 : dy = (py-PetscImaginaryPart(ctx->center))/(ctx->radius-ctx->width/2.0);
350 : #else
351 : dx = (px-ctx->center)/(ctx->radius-ctx->width/2.0);
352 : dy = py/(ctx->radius-ctx->width/2.0);
353 : #endif
354 69 : r = -1.0+dx*dx+(dy*dy)/(ctx->vscale*ctx->vscale);
355 69 : *inside *= PetscSign(r);
356 69 : if (*inside == 1) { /* check angles */
357 : #if defined(PETSC_USE_COMPLEX)
358 45 : dx = (px-PetscRealPart(ctx->center));
359 45 : dy = (py-PetscImaginaryPart(ctx->center));
360 : #else
361 : dx = px-ctx->center;
362 : dy = py;
363 : #endif
364 45 : if (dx == 0) {
365 1 : if (dy == 0) r = -1;
366 1 : else if (dy > 0) r = 0.25;
367 0 : else r = 0.75;
368 44 : } else if (dx > 0) {
369 25 : r = PetscAtanReal((dy/ctx->vscale)/dx);
370 25 : if (dy >= 0) r /= 2*PETSC_PI;
371 12 : else r = r/(2*PETSC_PI)+1;
372 19 : } else r = PetscAtanReal((dy/ctx->vscale)/dx)/(2*PETSC_PI)+0.5;
373 45 : if (ctx->start_ang>ctx->end_ang) {
374 25 : if (r>ctx->end_ang && r<ctx->start_ang) *inside = -1;
375 : } else {
376 20 : if (r<ctx->start_ang || r>ctx->end_ang) *inside = -1;
377 : }
378 : }
379 69 : PetscFunctionReturn(PETSC_SUCCESS);
380 : }
381 :
382 4 : static PetscErrorCode RGIsAxisymmetric_Ring(RG rg,PetscBool vertical,PetscBool *symm)
383 : {
384 4 : RG_RING *ctx = (RG_RING*)rg->data;
385 :
386 4 : PetscFunctionBegin;
387 5 : if (vertical) *symm = (PetscRealPart(ctx->center) == 0.0 && PetscAbs(ctx->start_ang+ctx->end_ang-PetscRealConstant(1.0)) == 0.5)? PETSC_TRUE: PETSC_FALSE;
388 3 : else *symm = (PetscImaginaryPart(ctx->center) == 0.0 && ctx->start_ang+ctx->end_ang == 1.0)? PETSC_TRUE: PETSC_FALSE;
389 4 : PetscFunctionReturn(PETSC_SUCCESS);
390 : }
391 :
392 15 : static PetscErrorCode RGSetFromOptions_Ring(RG rg,PetscOptionItems *PetscOptionsObject)
393 : {
394 15 : PetscScalar s;
395 15 : PetscReal r1,r2,r3,r4,r5;
396 15 : PetscBool flg1,flg2,flg3,flg4,flg5,flg6;
397 :
398 15 : PetscFunctionBegin;
399 15 : PetscOptionsHeadBegin(PetscOptionsObject,"RG Ring Options");
400 :
401 15 : PetscCall(RGRingGetParameters(rg,&s,&r1,&r2,&r3,&r4,&r5));
402 15 : PetscCall(PetscOptionsScalar("-rg_ring_center","Center of ellipse","RGRingSetParameters",s,&s,&flg1));
403 15 : PetscCall(PetscOptionsReal("-rg_ring_radius","Radius of ellipse","RGRingSetParameters",r1,&r1,&flg2));
404 15 : PetscCall(PetscOptionsReal("-rg_ring_vscale","Vertical scale of ellipse","RGRingSetParameters",r2,&r2,&flg3));
405 15 : PetscCall(PetscOptionsReal("-rg_ring_startangle","Right-hand side angle","RGRingSetParameters",r3,&r3,&flg4));
406 15 : PetscCall(PetscOptionsReal("-rg_ring_endangle","Left-hand side angle","RGRingSetParameters",r4,&r4,&flg5));
407 15 : PetscCall(PetscOptionsReal("-rg_ring_width","Width of ring","RGRingSetParameters",r5,&r5,&flg6));
408 15 : if (flg1 || flg2 || flg3 || flg4 || flg5 || flg6) PetscCall(RGRingSetParameters(rg,s,r1,r2,r3,r4,r5));
409 :
410 15 : PetscOptionsHeadEnd();
411 15 : PetscFunctionReturn(PETSC_SUCCESS);
412 : }
413 :
414 12 : static PetscErrorCode RGDestroy_Ring(RG rg)
415 : {
416 12 : PetscFunctionBegin;
417 12 : PetscCall(PetscFree(rg->data));
418 12 : PetscCall(PetscObjectComposeFunction((PetscObject)rg,"RGRingSetParameters_C",NULL));
419 12 : PetscCall(PetscObjectComposeFunction((PetscObject)rg,"RGRingGetParameters_C",NULL));
420 12 : PetscFunctionReturn(PETSC_SUCCESS);
421 : }
422 :
423 12 : SLEPC_EXTERN PetscErrorCode RGCreate_Ring(RG rg)
424 : {
425 12 : RG_RING *ring;
426 :
427 12 : PetscFunctionBegin;
428 12 : PetscCall(PetscNew(&ring));
429 12 : ring->center = 0.0;
430 12 : ring->radius = PETSC_MAX_REAL;
431 12 : ring->vscale = 1.0;
432 12 : ring->start_ang = 0.0;
433 12 : ring->end_ang = 1.0;
434 12 : ring->width = 0.1;
435 12 : rg->data = (void*)ring;
436 :
437 12 : rg->ops->istrivial = RGIsTrivial_Ring;
438 12 : rg->ops->computecontour = RGComputeContour_Ring;
439 12 : rg->ops->computebbox = RGComputeBoundingBox_Ring;
440 12 : rg->ops->computequadrature = RGComputeQuadrature_Ring;
441 12 : rg->ops->checkinside = RGCheckInside_Ring;
442 12 : rg->ops->isaxisymmetric = RGIsAxisymmetric_Ring;
443 12 : rg->ops->setfromoptions = RGSetFromOptions_Ring;
444 12 : rg->ops->view = RGView_Ring;
445 12 : rg->ops->destroy = RGDestroy_Ring;
446 12 : PetscCall(PetscObjectComposeFunction((PetscObject)rg,"RGRingSetParameters_C",RGRingSetParameters_Ring));
447 12 : PetscCall(PetscObjectComposeFunction((PetscObject)rg,"RGRingGetParameters_C",RGRingGetParameters_Ring));
448 12 : PetscFunctionReturn(PETSC_SUCCESS);
449 : }
|