LCOV - code coverage report
Current view: top level - sys/classes/rg/impls/ring - rgring.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 236 241 97.9 %
Date: 2024-12-18 00:51:33 Functions: 14 14 100.0 %
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.14