Date: 2023-01-26T12:18:25+00:00

Actual source code: rgbasic.c
slepc-3.18.2 2023-01-26
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-, 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:    Basic RG routines
     12: */

     14: #include <slepc/private/rgimpl.h>

     16: PetscFunctionList RGList = NULL;
     17: PetscBool         RGRegisterAllCalled = PETSC_FALSE;
     18: PetscClassId      RG_CLASSID = 0;
     19: static PetscBool  RGPackageInitialized = PETSC_FALSE;

     21: /*@C
     22:    RGFinalizePackage - This function destroys everything in the Slepc interface
     23:    to the RG package. It is called from SlepcFinalize().

     25:    Level: developer

     27: .seealso: SlepcFinalize()
     28: @*/
     29: PetscErrorCode RGFinalizePackage(void)
     30: {
     31:   PetscFunctionListDestroy(&RGList);
     32:   RGPackageInitialized = PETSC_FALSE;
     33:   RGRegisterAllCalled  = PETSC_FALSE;
     34:   return 0;
     35: }

     37: /*@C
     38:   RGInitializePackage - This function initializes everything in the RG package.
     39:   It is called from PetscDLLibraryRegister() when using dynamic libraries, and
     40:   on the first call to RGCreate() when using static libraries.

     42:   Level: developer

     44: .seealso: SlepcInitialize()
     45: @*/
     46: PetscErrorCode RGInitializePackage(void)
     47: {
     48:   char           logList[256];
     49:   PetscBool      opt,pkg;
     50:   PetscClassId   classids[1];

     52:   if (RGPackageInitialized) return 0;
     53:   RGPackageInitialized = PETSC_TRUE;
     54:   /* Register Classes */
     55:   PetscClassIdRegister("Region",&RG_CLASSID);
     56:   /* Register Constructors */
     57:   RGRegisterAll();
     58:   /* Process Info */
     59:   classids[0] = RG_CLASSID;
     60:   PetscInfoProcessClass("rg",1,&classids[0]);
     61:   /* Process summary exclusions */
     62:   PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt);
     63:   if (opt) {
     64:     PetscStrInList("rg",logList,',',&pkg);
     65:     if (pkg) PetscLogEventDeactivateClass(RG_CLASSID);
     66:   }
     67:   /* Register package finalizer */
     68:   PetscRegisterFinalize(RGFinalizePackage);
     69:   return 0;
     70: }

     72: /*@
     73:    RGCreate - Creates an RG context.

     75:    Collective

     77:    Input Parameter:
     78: .  comm - MPI communicator

     80:    Output Parameter:
     81: .  newrg - location to put the RG context

     83:    Level: beginner

     85: .seealso: RGDestroy(), RG
     86: @*/
     87: PetscErrorCode RGCreate(MPI_Comm comm,RG *newrg)
     88: {
     89:   RG             rg;

     92:   *newrg = NULL;
     93:   RGInitializePackage();
     94:   SlepcHeaderCreate(rg,RG_CLASSID,"RG","Region","RG",comm,RGDestroy,RGView);
     95:   rg->complement = PETSC_FALSE;
     96:   rg->sfactor    = 1.0;
     97:   rg->osfactor   = 0.0;
     98:   rg->data       = NULL;

    100:   *newrg = rg;
    101:   return 0;
    102: }

    104: /*@C
    105:    RGSetOptionsPrefix - Sets the prefix used for searching for all
    106:    RG options in the database.

    108:    Logically Collective on rg

    110:    Input Parameters:
    111: +  rg     - the region context
    112: -  prefix - the prefix string to prepend to all RG option requests

    114:    Notes:
    115:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    116:    The first character of all runtime options is AUTOMATICALLY the
    117:    hyphen.

    119:    Level: advanced

    121: .seealso: RGAppendOptionsPrefix()
    122: @*/
    123: PetscErrorCode RGSetOptionsPrefix(RG rg,const char *prefix)
    124: {
    126:   PetscObjectSetOptionsPrefix((PetscObject)rg,prefix);
    127:   return 0;
    128: }

    130: /*@C
    131:    RGAppendOptionsPrefix - Appends to the prefix used for searching for all
    132:    RG options in the database.

    134:    Logically Collective on rg

    136:    Input Parameters:
    137: +  rg     - the region context
    138: -  prefix - the prefix string to prepend to all RG option requests

    140:    Notes:
    141:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    142:    The first character of all runtime options is AUTOMATICALLY the hyphen.

    144:    Level: advanced

    146: .seealso: RGSetOptionsPrefix()
    147: @*/
    148: PetscErrorCode RGAppendOptionsPrefix(RG rg,const char *prefix)
    149: {
    151:   PetscObjectAppendOptionsPrefix((PetscObject)rg,prefix);
    152:   return 0;
    153: }

    155: /*@C
    156:    RGGetOptionsPrefix - Gets the prefix used for searching for all
    157:    RG options in the database.

    159:    Not Collective

    161:    Input Parameters:
    162: .  rg - the region context

    164:    Output Parameters:
    165: .  prefix - pointer to the prefix string used is returned

    167:    Note:
    168:    On the Fortran side, the user should pass in a string 'prefix' of
    169:    sufficient length to hold the prefix.

    171:    Level: advanced

    173: .seealso: RGSetOptionsPrefix(), RGAppendOptionsPrefix()
    174: @*/
    175: PetscErrorCode RGGetOptionsPrefix(RG rg,const char *prefix[])
    176: {
    179:   PetscObjectGetOptionsPrefix((PetscObject)rg,prefix);
    180:   return 0;
    181: }

    183: /*@C
    184:    RGSetType - Selects the type for the RG object.

    186:    Logically Collective on rg

    188:    Input Parameters:
    189: +  rg   - the region context
    190: -  type - a known type

    192:    Level: intermediate

    194: .seealso: RGGetType()
    195: @*/
    196: PetscErrorCode RGSetType(RG rg,RGType type)
    197: {
    198:   PetscErrorCode (*r)(RG);
    199:   PetscBool      match;

    204:   PetscObjectTypeCompare((PetscObject)rg,type,&match);
    205:   if (match) return 0;

    207:   PetscFunctionListFind(RGList,type,&r);

    210:   PetscTryTypeMethod(rg,destroy);
    211:   PetscMemzero(rg->ops,sizeof(struct _RGOps));

    213:   PetscObjectChangeTypeName((PetscObject)rg,type);
    214:   (*r)(rg);
    215:   return 0;
    216: }

    218: /*@C
    219:    RGGetType - Gets the RG type name (as a string) from the RG context.

    221:    Not Collective

    223:    Input Parameter:
    224: .  rg - the region context

    226:    Output Parameter:
    227: .  type - name of the region

    229:    Level: intermediate

    231: .seealso: RGSetType()
    232: @*/
    233: PetscErrorCode RGGetType(RG rg,RGType *type)
    234: {
    237:   *type = ((PetscObject)rg)->type_name;
    238:   return 0;
    239: }

    241: /*@
    242:    RGSetFromOptions - Sets RG options from the options database.

    244:    Collective on rg

    246:    Input Parameters:
    247: .  rg - the region context

    249:    Notes:
    250:    To see all options, run your program with the -help option.

    252:    Level: beginner

    254: .seealso: RGSetOptionsPrefix()
    255: @*/
    256: PetscErrorCode RGSetFromOptions(RG rg)
    257: {
    258:   char           type[256];
    259:   PetscBool      flg;
    260:   PetscReal      sfactor;

    263:   RGRegisterAll();
    264:   PetscObjectOptionsBegin((PetscObject)rg);
    265:     PetscOptionsFList("-rg_type","Region type","RGSetType",RGList,(char*)(((PetscObject)rg)->type_name?((PetscObject)rg)->type_name:RGINTERVAL),type,sizeof(type),&flg);
    266:     if (flg) RGSetType(rg,type);
    267:     else if (!((PetscObject)rg)->type_name) RGSetType(rg,RGINTERVAL);

    269:     PetscOptionsBool("-rg_complement","Whether region is complemented or not","RGSetComplement",rg->complement,&rg->complement,NULL);

    271:     PetscOptionsReal("-rg_scale","Scaling factor","RGSetScale",1.0,&sfactor,&flg);
    272:     if (flg) RGSetScale(rg,sfactor);

    274:     PetscTryTypeMethod(rg,setfromoptions,PetscOptionsObject);
    275:     PetscObjectProcessOptionsHandlers((PetscObject)rg,PetscOptionsObject);
    276:   PetscOptionsEnd();
    277:   return 0;
    278: }

    280: /*@C
    281:    RGView - Prints the RG data structure.

    283:    Collective on rg

    285:    Input Parameters:
    286: +  rg - the region context
    287: -  viewer - optional visualization context

    289:    Note:
    290:    The available visualization contexts include
    291: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
    292: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
    293:          output where only the first processor opens
    294:          the file.  All other processors send their
    295:          data to the first processor to print.

    297:    The user can open an alternative visualization context with
    298:    PetscViewerASCIIOpen() - output to a specified file.

    300:    Level: beginner

    302: .seealso: RGCreate()
    303: @*/
    304: PetscErrorCode RGView(RG rg,PetscViewer viewer)
    305: {
    306:   PetscBool      isdraw,isascii;

    309:   if (!viewer) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)rg),&viewer);
    312:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    313:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
    314:   if (isascii) {
    315:     PetscObjectPrintClassNamePrefixType((PetscObject)rg,viewer);
    316:     PetscViewerASCIIPushTab(viewer);
    317:     PetscTryTypeMethod(rg,view,viewer);
    318:     PetscViewerASCIIPopTab(viewer);
    319:     if (rg->complement) PetscViewerASCIIPrintf(viewer,"  selected region is the complement of the specified one\n");
    320:     if (rg->sfactor!=1.0) PetscViewerASCIIPrintf(viewer,"  scaling factor = %g\n",(double)rg->sfactor);
    321:   } else if (isdraw) PetscTryTypeMethod(rg,view,viewer);
    322:   return 0;
    323: }

    325: /*@C
    326:    RGViewFromOptions - View from options

    328:    Collective on RG

    330:    Input Parameters:
    331: +  rg   - the region context
    332: .  obj  - optional object
    333: -  name - command line option

    335:    Level: intermediate

    337: .seealso: RGView(), RGCreate()
    338: @*/
    339: PetscErrorCode RGViewFromOptions(RG rg,PetscObject obj,const char name[])
    340: {
    342:   PetscObjectViewFromOptions((PetscObject)rg,obj,name);
    343:   return 0;
    344: }

    346: /*@
    347:    RGIsTrivial - Whether it is the trivial region (whole complex plane).

    349:    Not Collective

    351:    Input Parameter:
    352: .  rg - the region context

    354:    Output Parameter:
    355: .  trivial - true if the region is equal to the whole complex plane, e.g.,
    356:              an interval region with all four endpoints unbounded or an
    357:              ellipse with infinite radius.

    359:    Level: beginner

    361: .seealso: RGCheckInside()
    362: @*/
    363: PetscErrorCode RGIsTrivial(RG rg,PetscBool *trivial)
    364: {
    368:   *trivial = PETSC_FALSE;
    369:   PetscTryTypeMethod(rg,istrivial,trivial);
    370:   return 0;
    371: }

    373: /*@
    374:    RGCheckInside - Determines if a set of given points are inside the region or not.

    376:    Not Collective

    378:    Input Parameters:
    379: +  rg - the region context
    380: .  n  - number of points to check
    381: .  ar - array of real parts
    382: -  ai - array of imaginary parts

    384:    Output Parameter:
    385: .  inside - array of results (1=inside, 0=on the contour, -1=outside)

    387:    Note:
    388:    The point a is expressed as a couple of PetscScalar variables ar,ai.
    389:    If built with complex scalars, the point is supposed to be stored in ar,
    390:    otherwise ar,ai contain the real and imaginary parts, respectively.

    392:    If a scaling factor was set, the points are scaled before checking.

    394:    Level: intermediate

    396: .seealso: RGSetScale(), RGSetComplement()
    397: @*/
    398: PetscErrorCode RGCheckInside(RG rg,PetscInt n,PetscScalar *ar,PetscScalar *ai,PetscInt *inside)
    399: {
    400:   PetscReal      px,py;
    401:   PetscInt       i;

    406: #if !defined(PETSC_USE_COMPLEX)
    408: #endif

    411:   for (i=0;i<n;i++) {
    412: #if defined(PETSC_USE_COMPLEX)
    413:     px = PetscRealPart(ar[i]);
    414:     py = PetscImaginaryPart(ar[i]);
    415: #else
    416:     px = ar[i];
    417:     py = ai[i];
    418: #endif
    419:     if (PetscUnlikely(rg->sfactor != 1.0)) {
    420:       px /= rg->sfactor;
    421:       py /= rg->sfactor;
    422:     }
    423:     PetscUseTypeMethod(rg,checkinside,px,py,inside+i);
    424:     if (PetscUnlikely(rg->complement)) inside[i] = -inside[i];
    425:   }
    426:   return 0;
    427: }

    429: /*@
    430:    RGIsAxisymmetric - Determines if the region is symmetric with respect
    431:    to the real or imaginary axis.

    433:    Not Collective

    435:    Input Parameters:
    436: +  rg       - the region context
    437: -  vertical - true if symmetry must be checked against the vertical axis

    439:    Output Parameter:
    440: .  symm - true if the region is axisymmetric

    442:    Note:
    443:    If the vertical argument is true, symmetry is checked with respect to
    444:    the vertical axis, otherwise with respect to the horizontal axis.

    446:    Level: intermediate

    448: .seealso: RGCanUseConjugates()
    449: @*/
    450: PetscErrorCode RGIsAxisymmetric(RG rg,PetscBool vertical,PetscBool *symm)
    451: {
    455:   *symm = PETSC_FALSE;
    456:   PetscTryTypeMethod(rg,isaxisymmetric,vertical,symm);
    457:   return 0;
    458: }

    460: /*@
    461:    RGCanUseConjugates - Used in contour integral methods to determine whether
    462:    half of integration points can be avoided (use their conjugates).

    464:    Not Collective

    466:    Input Parameters:
    467: +  rg       - the region context
    468: -  realmats - true if the problem matrices are real

    470:    Output Parameter:
    471: .  useconj  - whether it is possible to use conjugates

    473:    Notes:
    474:    If some integration points are the conjugates of other points, then the
    475:    associated computational cost can be saved. This depends on the problem
    476:    matrices being real and also the region being symmetric with respect to
    477:    the horizontal axis. The result is false if using real arithmetic or
    478:    in the case of a flat region (height equal to zero).

    480:    Level: developer

    482: .seealso: RGIsAxisymmetric()
    483: @*/
    484: PetscErrorCode RGCanUseConjugates(RG rg,PetscBool realmats,PetscBool *useconj)
    485: {
    486: #if defined(PETSC_USE_COMPLEX)
    487:   PetscReal      c,d;
    488:   PetscBool      isaxisymm;
    489: #endif

    494:   *useconj = PETSC_FALSE;
    495: #if defined(PETSC_USE_COMPLEX)
    496:   if (realmats) {
    497:     RGIsAxisymmetric(rg,PETSC_FALSE,&isaxisymm);
    498:     if (isaxisymm) {
    499:       RGComputeBoundingBox(rg,NULL,NULL,&c,&d);
    500:       if (c!=d) *useconj = PETSC_TRUE;
    501:     }
    502:   }
    503: #endif
    504:   return 0;
    505: }

    507: /*@
    508:    RGComputeContour - Computes the coordinates of several points lying on the
    509:    contour of the region.

    511:    Not Collective

    513:    Input Parameters:
    514: +  rg - the region context
    515: -  n  - number of points to compute

    517:    Output Parameters:
    518: +  cr - location to store real parts
    519: -  ci - location to store imaginary parts

    521:    Notes:
    522:    In real scalars, either cr or ci can be NULL (but not both). In complex
    523:    scalars, the coordinates are stored in cr, which cannot be NULL (ci is
    524:    not referenced).

    526:    Level: intermediate

    528: .seealso: RGComputeBoundingBox()
    529: @*/
    530: PetscErrorCode RGComputeContour(RG rg,PetscInt n,PetscScalar cr[],PetscScalar ci[])
    531: {
    532:   PetscInt       i;

    536: #if defined(PETSC_USE_COMPLEX)
    538: #else
    540: #endif
    542:   PetscUseTypeMethod(rg,computecontour,n,cr,ci);
    543:   for (i=0;i<n;i++) {
    544:     if (cr) cr[i] *= rg->sfactor;
    545:     if (ci) ci[i] *= rg->sfactor;
    546:   }
    547:   return 0;
    548: }

    550: /*@
    551:    RGComputeBoundingBox - Determines the endpoints of a rectangle in the complex plane that
    552:    contains the region.

    554:    Not Collective

    556:    Input Parameter:
    557: .  rg - the region context

    559:    Output Parameters:
    560: +  a - left endpoint of the bounding box in the real axis
    561: .  b - right endpoint of the bounding box in the real axis
    562: .  c - bottom endpoint of the bounding box in the imaginary axis
    563: -  d - top endpoint of the bounding box in the imaginary axis

    565:    Notes:
    566:    The bounding box is defined as [a,b]x[c,d]. In regions that are not bounded (e.g. an
    567:    open interval) or with the complement flag set, it makes no sense to compute a bounding
    568:    box, so the return values are infinite.

    570:    Level: intermediate

    572: .seealso: RGComputeContour()
    573: @*/
    574: PetscErrorCode RGComputeBoundingBox(RG rg,PetscReal *a,PetscReal *b,PetscReal *c,PetscReal *d)
    575: {

    579:   if (rg->complement) {  /* cannot compute bounding box */
    580:     if (a) *a = -PETSC_MAX_REAL;
    581:     if (b) *b =  PETSC_MAX_REAL;
    582:     if (c) *c = -PETSC_MAX_REAL;
    583:     if (d) *d =  PETSC_MAX_REAL;
    584:   } else {
    585:     PetscUseTypeMethod(rg,computebbox,a,b,c,d);
    586:     if (a && *a!=-PETSC_MAX_REAL) *a *= rg->sfactor;
    587:     if (b && *b!= PETSC_MAX_REAL) *b *= rg->sfactor;
    588:     if (c && *c!=-PETSC_MAX_REAL) *c *= rg->sfactor;
    589:     if (d && *d!= PETSC_MAX_REAL) *d *= rg->sfactor;
    590:   }
    591:   return 0;
    592: }

    594: /*@
    595:    RGComputeQuadrature - Computes the values of the parameters used in a
    596:    quadrature rule for a contour integral around the boundary of the region.

    598:    Not Collective

    600:    Input Parameters:
    601: +  rg   - the region context
    602: .  quad - the type of quadrature
    603: -  n    - number of quadrature points to compute

    605:    Output Parameters:
    606: +  z  - quadrature points
    607: .  zn - normalized quadrature points
    608: -  w  - quadrature weights

    610:    Notes:
    611:    In complex scalars, the values returned in z are often the same as those
    612:    computed by RGComputeContour(), but this is not the case in real scalars
    613:    where all output arguments are real.

    615:    The computed values change for different quadrature rules (trapezoidal
    616:    or Chebyshev).

    618:    Level: intermediate

    620: .seealso: RGComputeContour()
    621: @*/
    622: PetscErrorCode RGComputeQuadrature(RG rg,RGQuadRule quad,PetscInt n,PetscScalar z[],PetscScalar zn[],PetscScalar w[])
    623: {

    630:   RGComputeContour(rg,n,z,NULL);
    631:   PetscUseTypeMethod(rg,computequadrature,quad,n,z,zn,w);
    632:   return 0;
    633: }

    635: /*@
    636:    RGSetComplement - Sets a flag to indicate that the region is the complement
    637:    of the specified one.

    639:    Logically Collective on rg

    641:    Input Parameters:
    642: +  rg  - the region context
    643: -  flg - the boolean flag

    645:    Options Database Key:
    646: .  -rg_complement <bool> - Activate/deactivate the complementation of the region

    648:    Level: intermediate

    650: .seealso: RGGetComplement()
    651: @*/
    652: PetscErrorCode RGSetComplement(RG rg,PetscBool flg)
    653: {
    656:   rg->complement = flg;
    657:   return 0;
    658: }

    660: /*@
    661:    RGGetComplement - Gets a flag that that indicates whether the region
    662:    is complemented or not.

    664:    Not Collective

    666:    Input Parameter:
    667: .  rg - the region context

    669:    Output Parameter:
    670: .  flg - the flag

    672:    Level: intermediate

    674: .seealso: RGSetComplement()
    675: @*/
    676: PetscErrorCode RGGetComplement(RG rg,PetscBool *flg)
    677: {
    680:   *flg = rg->complement;
    681:   return 0;
    682: }

    684: /*@
    685:    RGSetScale - Sets the scaling factor to be used when checking that a
    686:    point is inside the region and when computing the contour.

    688:    Logically Collective on rg

    690:    Input Parameters:
    691: +  rg      - the region context
    692: -  sfactor - the scaling factor

    694:    Options Database Key:
    695: .  -rg_scale <real> - Sets the scaling factor

    697:    Level: advanced

    699: .seealso: RGGetScale(), RGCheckInside()
    700: @*/
    701: PetscErrorCode RGSetScale(RG rg,PetscReal sfactor)
    702: {
    705:   if (sfactor == PETSC_DEFAULT || sfactor == PETSC_DECIDE) rg->sfactor = 1.0;
    706:   else {
    708:     rg->sfactor = sfactor;
    709:   }
    710:   return 0;
    711: }

    713: /*@
    714:    RGGetScale - Gets the scaling factor.

    716:    Not Collective

    718:    Input Parameter:
    719: .  rg - the region context

    721:    Output Parameter:
    722: .  sfactor - the scaling factor

    724:    Level: advanced

    726: .seealso: RGSetScale()
    727: @*/
    728: PetscErrorCode RGGetScale(RG rg,PetscReal *sfactor)
    729: {
    732:   *sfactor = rg->sfactor;
    733:   return 0;
    734: }

    736: /*@
    737:    RGPushScale - Sets an additional scaling factor, that will multiply the
    738:    user-defined scaling factor.

    740:    Logically Collective on rg

    742:    Input Parameters:
    743: +  rg      - the region context
    744: -  sfactor - the scaling factor

    746:    Notes:
    747:    The current implementation does not allow pushing several scaling factors.

    749:    This is intended for internal use, for instance in polynomial eigensolvers
    750:    that use parameter scaling.

    752:    Level: developer

    754: .seealso: RGPopScale(), RGSetScale()
    755: @*/
    756: PetscErrorCode RGPushScale(RG rg,PetscReal sfactor)
    757: {
    762:   rg->osfactor = rg->sfactor;
    763:   rg->sfactor *= sfactor;
    764:   return 0;
    765: }

    767: /*@
    768:    RGPopScale - Pops the scaling factor set with RGPushScale().

    770:    Not Collective

    772:    Input Parameter:
    773: .  rg - the region context

    775:    Level: developer

    777: .seealso: RGPushScale()
    778: @*/
    779: PetscErrorCode RGPopScale(RG rg)
    780: {
    783:   rg->sfactor  = rg->osfactor;
    784:   rg->osfactor = 0.0;
    785:   return 0;
    786: }

    788: /*@C
    789:    RGDestroy - Destroys RG context that was created with RGCreate().

    791:    Collective on rg

    793:    Input Parameter:
    794: .  rg - the region context

    796:    Level: beginner

    798: .seealso: RGCreate()
    799: @*/
    800: PetscErrorCode RGDestroy(RG *rg)
    801: {
    802:   if (!*rg) return 0;
    804:   if (--((PetscObject)(*rg))->refct > 0) { *rg = NULL; return 0; }
    805:   PetscTryTypeMethod(*rg,destroy);
    806:   PetscHeaderDestroy(rg);
    807:   return 0;
    808: }

    810: /*@C
    811:    RGRegister - Adds a region to the RG package.

    813:    Not collective

    815:    Input Parameters:
    816: +  name - name of a new user-defined RG
    817: -  function - routine to create context

    819:    Notes:
    820:    RGRegister() may be called multiple times to add several user-defined regions.

    822:    Level: advanced

    824: .seealso: RGRegisterAll()
    825: @*/
    826: PetscErrorCode RGRegister(const char *name,PetscErrorCode (*function)(RG))
    827: {
    828:   RGInitializePackage();
    829:   PetscFunctionListAdd(&RGList,name,function);
    830:   return 0;
    831: }