Date: 2022-03-04T17:37:21+00:00

Actual source code: tagger.c

      1: #include <petsc/private/vecimpl.h>

      3: /*@C
      4:    VecTaggerCreate - create a Vec tagger context.  This object is used to control the tagging/selection of index sets
      5:    based on the values in a vector.  This is used, for example, in adaptive simulations when aspects are selected for
      6:    refinement or coarsening.  The primary intent is that the selected index sets are based purely on the values in the
      7:    vector, though implementations that do not follow this intent are possible.

      9:    Once a VecTagger is created (VecTaggerCreate()), optionally modified by options (VecTaggerSetFromOptions()), and
     10:    set up (VecTaggerSetUp()), it is applied to vectors with VecTaggerComputeIS() to comute the selected index sets.

     12:    In many cases, the selection criteria for an index is whether the corresponding value falls within a collection of
     13:    boxes: for this common case, VecTaggerCreateBoxes() can also be used to determine those boxes.

     15:    Provided implementations support tagging based on a box/interval of values (VECTAGGERABSOLUTE), based on a box of
     16:    values of relative to the range of values present in the vector (VECTAGGERRELATIVE), based on where values fall in
     17:    the cumulative distribution of values in the vector (VECTAGGERCDF), and based on unions (VECTAGGEROR) or
     18:    intersections (VECTAGGERAND) of other criteria.

     20:    Collective

     22:    Input Parameter:
     23: .  comm - communicator on which the vec tagger will operate

     25:    Output Parameter:
     26: .  tagger - new Vec tagger context

     28:    Level: advanced

     30: .seealso: VecTaggerSetBlockSize(), VecTaggerSetFromOptions(), VecTaggerSetUp(), VecTaggerComputeIS(), VecTaggerComputeBoxes(), VecTaggerDestroy()
     31: @*/
     32: PetscErrorCode VecTaggerCreate(MPI_Comm comm,VecTagger *tagger)
     33: {
     35:   VecTagger      b;

     39:   VecTaggerInitializePackage();

     41:   PetscHeaderCreate(b,VEC_TAGGER_CLASSID,"VecTagger","Vec Tagger","Vec",comm,VecTaggerDestroy,VecTaggerView);

     43:   b->blocksize   = 1;
     44:   b->invert      = PETSC_FALSE;
     45:   b->setupcalled = PETSC_FALSE;

     47:   *tagger = b;
     48:   return(0);
     49: }

     51: /*@C
     52:    VecTaggerSetType - set the Vec tagger implementation

     54:    Collective on VecTagger

     56:    Input Parameters:
     57: +  tagger - the VecTagger context
     58: -  type - a known method

     60:    Options Database Key:
     61: .  -vec_tagger_type <type> - Sets the method; use -help for a list
     62:    of available methods (for instance, absolute, relative, cdf, or, and)

     64:    Notes:
     65:    See "include/petscvec.h" for available methods (for instance)
     66: +    VECTAGGERABSOLUTE - tag based on a box of values
     67: .    VECTAGGERRELATIVE - tag based on a box relative to the range of values present in the vector
     68: .    VECTAGGERCDF      - tag based on a box in the cumulative distribution of values present in the vector
     69: .    VECTAGGEROR       - tag based on the union of a set of VecTagger contexts
     70: -    VECTAGGERAND      - tag based on the intersection of a set of other VecTagger contexts

     72:   Level: advanced

     74: .seealso: VecTaggerType, VecTaggerCreate()
     75: @*/
     76: PetscErrorCode VecTaggerSetType(VecTagger tagger,VecTaggerType type)
     77: {
     78:   PetscErrorCode ierr,(*r)(VecTagger);
     79:   PetscBool      match;

     85:   PetscObjectTypeCompare((PetscObject)tagger,type,&match);
     86:   if (match) return(0);

     88:   PetscFunctionListFind(VecTaggerList,type,&r);
     89:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested VecTagger type %s",type);
     90:   /* Destroy the previous private VecTagger context */
     91:   if (tagger->ops->destroy) {
     92:     (*(tagger)->ops->destroy)(tagger);
     93:   }
     94:   PetscMemzero(tagger->ops,sizeof(*tagger->ops));
     95:   PetscObjectChangeTypeName((PetscObject)tagger,type);
     96:   tagger->ops->create = r;
     97:   (*r)(tagger);
     98:   return(0);
     99: }

    101: /*@C
    102:   VecTaggerGetType - Gets the VecTagger type name (as a string) from the VecTagger.

    104:   Not Collective

    106:   Input Parameter:
    107: . tagger  - The Vec tagger context

    109:   Output Parameter:
    110: . type - The VecTagger type name

    112:   Level: advanced

    114: .seealso: VecTaggerSetType(), VecTaggerCreate()
    115: @*/
    116: PetscErrorCode  VecTaggerGetType(VecTagger tagger, VecTaggerType *type)
    117: {

    123:   VecTaggerRegisterAll();
    124:   *type = ((PetscObject)tagger)->type_name;
    125:   return(0);
    126: }

    128: /*@
    129:    VecTaggerDestroy - destroy a VecTagger context

    131:    Collective

    133:    Input Parameter:
    134: .  tagger - address of tagger

    136:    Level: advanced

    138: .seealso: VecTaggerCreate()
    139: @*/
    140: PetscErrorCode VecTaggerDestroy(VecTagger *tagger)
    141: {

    145:   if (!*tagger) return(0);
    147:   if (--((PetscObject)(*tagger))->refct > 0) {*tagger = NULL; return(0);}
    148:   if ((*tagger)->ops->destroy) {(*(*tagger)->ops->destroy)(*tagger);}
    149:   PetscHeaderDestroy(tagger);
    150:   return(0);
    151: }

    153: /*@
    154:    VecTaggerSetUp - set up a VecTagger context

    156:    Collective

    158:    Input Parameter:
    159: .  tagger - Vec tagger object

    161:    Level: advanced

    163: .seealso: VecTaggerSetFromOptions(), VecTaggerSetType()
    164: @*/
    165: PetscErrorCode VecTaggerSetUp(VecTagger tagger)
    166: {

    170:   if (tagger->setupcalled) return(0);
    171:   if (!((PetscObject)tagger)->type_name) {VecTaggerSetType(tagger,VECTAGGERABSOLUTE);}
    172:   if (tagger->ops->setup) {(*tagger->ops->setup)(tagger);}
    173:   tagger->setupcalled = PETSC_TRUE;
    174:   return(0);
    175: }

    177: /*@C
    178:    VecTaggerSetFromOptions - set VecTagger options using the options database

    180:    Logically Collective

    182:    Input Parameter:
    183: .  tagger - vec tagger

    185:    Options Database Keys:
    186: +  -vec_tagger_type       - implementation type, see VecTaggerSetType()
    187: .  -vec_tagger_block_size - set the block size, see VecTaggerSetBlockSize()
    188: -  -vec_tagger_invert     - invert the index set returned by VecTaggerComputeIS()

    190:    Level: advanced

    192: @*/
    193: PetscErrorCode VecTaggerSetFromOptions(VecTagger tagger)
    194: {
    195:   VecTaggerType  deft;
    196:   char           type[256];
    198:   PetscBool      flg;

    202:   PetscObjectOptionsBegin((PetscObject)tagger);
    203:   deft = ((PetscObject)tagger)->type_name ? ((PetscObject)tagger)->type_name : VECTAGGERABSOLUTE;
    204:   PetscOptionsFList("-vec_tagger_type","VecTagger implementation type","VecTaggerSetType",VecTaggerList,deft,type,256,&flg);
    205:   VecTaggerSetType(tagger,flg ? type : deft);
    206:   PetscOptionsInt("-vec_tagger_block_size","block size of the vectors the tagger operates on","VecTaggerSetBlockSize",tagger->blocksize,&tagger->blocksize,NULL);
    207:   PetscOptionsBool("-vec_tagger_invert","invert the set of indices returned by VecTaggerComputeIS()","VecTaggerSetInvert",tagger->invert,&tagger->invert,NULL);
    208:   if (tagger->ops->setfromoptions) {(*tagger->ops->setfromoptions)(PetscOptionsObject,tagger);}
    209:   PetscOptionsEnd();
    210:   return(0);
    211: }

    213: /*@C
    214:    VecTaggerSetBlockSize - block size of the set of indices returned by VecTaggerComputeIS().  Values greater than one
    215:    are useful when there are multiple criteria for determining which indices to include in the set.  For example,
    216:    consider adaptive mesh refinement in a multiphysics problem, with metrics of solution quality for multiple fields
    217:    measure on each cell.  The size of the vector will be [numCells * numFields]; the VecTagger block size should be
    218:    numFields; VecTaggerComputeIS() will return indices in the range [0,numCells), i.e., one index is given for each
    219:    block of values.

    221:    Note that the block size of the vector does not have to match.

    223:    Note also that the index set created in VecTaggerComputeIS() has block size: it is an index set over the list of
    224:    items that the vector refers to, not to the vector itself.

    226:    Logically Collective

    228:    Input Parameters:
    229: +  tagger - vec tagger
    230: -  blocksize - block size of the criteria used to tagger vectors

    232:    Level: advanced

    234: .seealso: VecTaggerComputeIS(), VecTaggerGetBlockSize(), VecSetBlockSize(), VecGetBlockSize()
    235: @*/
    236: PetscErrorCode VecTaggerSetBlockSize(VecTagger tagger, PetscInt blocksize)
    237: {

    242:   tagger->blocksize = blocksize;
    243:   return(0);
    244: }

    246: /*@C
    247:    VecTaggerGetBlockSize - get the block size of the indices created by VecTaggerComputeIS().

    249:    Logically Collective

    251:    Input Parameters:
    252: +  tagger - vec tagger
    253: -  blocksize - block size of the vectors the tagger operates on

    255:    Level: advanced

    257: .seealso: VecTaggerComputeIS(), VecTaggerSetBlockSize(),
    258: @*/
    259: PetscErrorCode VecTaggerGetBlockSize(VecTagger tagger, PetscInt *blocksize)
    260: {

    265:   *blocksize = tagger->blocksize;
    266:   return(0);
    267: }

    269: /*@C
    270:    VecTaggerSetInvert - If the tagged index sets are based on boxes that can be returned by VecTaggerComputeBoxes(),
    271:    then this option inverts values used to compute the IS, i.e., from being in the union of the boxes to being in the
    272:    intersection of their exteriors.

    274:    Logically Collective

    276:    Input Parameters:
    277: +  tagger - vec tagger
    278: -  invert - PETSC_TRUE to invert, PETSC_FALSE to use the indices as is

    280:    Level: advanced

    282: .seealso: VecTaggerComputeIS(), VecTaggerGetInvert()
    283: @*/
    284: PetscErrorCode VecTaggerSetInvert(VecTagger tagger, PetscBool invert)
    285: {

    290:   tagger->invert = invert;
    291:   return(0);
    292: }

    294: /*@C
    295:    VecTaggerGetInvert - get whether the set of indices returned by VecTaggerComputeIS() are inverted

    297:    Logically Collective

    299:    Input Parameters:
    300: +  tagger - vec tagger
    301: -  invert - PETSC_TRUE to invert, PETSC_FALSE to use the indices as is

    303:    Level: advanced

    305: .seealso: VecTaggerComputeIS(), VecTaggerSetInvert()
    306: @*/
    307: PetscErrorCode VecTaggerGetInvert(VecTagger tagger, PetscBool *invert)
    308: {

    313:   *invert = tagger->invert;
    314:   return(0);
    315: }

    317: /*@C
    318:    VecTaggerView - view a VecTagger context

    320:    Collective

    322:    Input Parameters:
    323: +  tagger - vec tagger
    324: -  viewer - viewer to display tagger, for example PETSC_VIEWER_STDOUT_WORLD

    326:    Level: advanced

    328: .seealso: VecTaggerCreate()
    329: @*/
    330: PetscErrorCode VecTaggerView(VecTagger tagger,PetscViewer viewer)
    331: {
    332:   PetscErrorCode    ierr;
    333:   PetscBool         iascii;

    337:   if (!viewer) {PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)tagger),&viewer);}
    340:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    341:   if (iascii) {
    342:     PetscObjectPrintClassNamePrefixType((PetscObject)tagger,viewer);
    343:     PetscViewerASCIIPushTab(viewer);
    344:     PetscViewerASCIIPrintf(viewer,"Block size: %D\n",tagger->blocksize);
    345:     if (tagger->ops->view) {(*tagger->ops->view)(tagger,viewer);}
    346:     if (tagger->invert) {PetscViewerASCIIPrintf(viewer,"Inverting ISs.\n");}
    347:     PetscViewerASCIIPopTab(viewer);
    348:   }
    349:   return(0);
    350: }

    352: /*@C
    353:    VecTaggerComputeBoxes - If the tagged index set can be summarized as a list of boxes of values, returns that list

    355:    Collective on VecTagger

    357:    Input Parameters:
    358: +  tagger - the VecTagger context
    359: -  vec - the vec to tag

    361:    Output Parameters:
    362: +  numBoxes - the number of boxes in the tag definition
    363: -  boxes - a newly allocated list of boxes.  This is a flat array of (BlockSize * numBoxes) pairs that the user can free with PetscFree().

    365:    Notes:
    366: .  A value is tagged if it is in any of the boxes, unless the tagger has been inverted (see VecTaggerSetInvert()/VecTaggerGetInvert()), in which case a value is tagged if it is in none of the boxes.

    368:    Level: advanced

    370: .seealso: VecTaggerComputeIS()
    371: @*/
    372: PetscErrorCode VecTaggerComputeBoxes(VecTagger tagger,Vec vec,PetscInt *numBoxes,VecTaggerBox **boxes)
    373: {
    374:   PetscInt       vls, tbs;

    382:   VecGetLocalSize(vec,&vls);
    383:   VecTaggerGetBlockSize(tagger,&tbs);
    384:   if (vls % tbs) SETERRQ2(PetscObjectComm((PetscObject)tagger),PETSC_ERR_ARG_INCOMP,"vec local size %D is not a multiple of tagger block size %D",vls,tbs);
    385:   if (tagger->ops->computeboxes) {(*tagger->ops->computeboxes) (tagger,vec,numBoxes,boxes);}
    386:   else {
    387:     const char *type;
    388:     PetscObjectGetType ((PetscObject)tagger,&type);
    389:     SETERRQ1(PetscObjectComm((PetscObject)tagger),PETSC_ERR_SUP,"VecTagger type %s does not compute value boxes",type);
    390:   }
    391:   return(0);
    392: }

    394: /*@C
    395:    VecTaggerComputeIS - Use a VecTagger context to tag a set of indices based on a vector's values

    397:    Collective on VecTagger

    399:    Input Parameters:
    400: +  tagger - the VecTagger context
    401: -  vec - the vec to tag

    403:    Output Parameter:
    404: .  IS - a list of the indices tagged by the tagger, i.e., if the number of local indices will be n / bs, where n is VecGetLocalSize() and bs is VecTaggerGetBlockSize().

    406:    Level: advanced

    408: .seealso: VecTaggerComputeBoxes()
    409: @*/
    410: PetscErrorCode VecTaggerComputeIS(VecTagger tagger,Vec vec,IS *is)
    411: {
    412:   PetscInt       vls, tbs;

    419:   VecGetLocalSize(vec,&vls);
    420:   VecTaggerGetBlockSize(tagger,&tbs);
    421:   if (vls % tbs) SETERRQ2(PetscObjectComm((PetscObject)tagger),PETSC_ERR_ARG_INCOMP,"vec local size %D is not a multiple of tagger block size %D",vls,tbs);
    422:   if (tagger->ops->computeis) {(*tagger->ops->computeis) (tagger,vec,is);}
    423:   else {
    424:     SETERRQ(PetscObjectComm((PetscObject)tagger),PETSC_ERR_SUP,"VecTagger type does not compute ISs");
    425:   }
    426:   return(0);
    427: }

    429: PetscErrorCode VecTaggerComputeIS_FromBoxes(VecTagger tagger, Vec vec, IS *is)
    430: { PetscInt       numBoxes;
    431:   VecTaggerBox   *boxes;
    432:   PetscInt       numTagged, offset;
    433:   PetscInt       *tagged;
    434:   PetscInt       bs, b, i, j, k, n;
    435:   PetscBool      invert;
    436:   const PetscScalar *vecArray;

    440:   VecTaggerGetBlockSize(tagger,&bs);
    441:   VecTaggerComputeBoxes(tagger,vec,&numBoxes,&boxes);
    442:   VecGetArrayRead(vec, &vecArray);
    443:   VecGetLocalSize(vec, &n);
    444:   invert = tagger->invert;
    445:   numTagged = 0;
    446:   offset = 0;
    447:   tagged = NULL;
    448:   if (n % bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"blocksize %D does not divide vector length %D", bs, n);
    449:   n /= bs;
    450:   for (i = 0; i < 2; i++) {
    451:     if (i) {
    452:       PetscMalloc1(numTagged,&tagged);
    453:     }
    454:     for (j = 0; j < n; j++) {

    456:       for (k = 0; k < numBoxes; k++) {
    457:         for (b = 0; b < bs; b++) {
    458:           PetscScalar  val = vecArray[j * bs + b];
    459:           PetscInt     l = k * bs + b;
    460:           VecTaggerBox box;
    461:           PetscBool    in;

    463:           box = boxes[l];
    464: #if !defined(PETSC_USE_COMPLEX)
    465:           in = (PetscBool) ((box.min <= val) && (val <= box.max));
    466: #else
    467:           in = (PetscBool) ((PetscRealPart     (box.min) <= PetscRealPart     (val)) &&
    468:                             (PetscImaginaryPart(box.min) <= PetscImaginaryPart(val)) &&
    469:                             (PetscRealPart     (val)     <= PetscRealPart     (box.max)) &&
    470:                             (PetscImaginaryPart(val)     <= PetscImaginaryPart(box.max)));
    471: #endif
    472:           if (!in) break;
    473:         }
    474:         if (b == bs) break;
    475:       }
    476:       if ((PetscBool)(k < numBoxes) ^ invert) {
    477:         if (!i) numTagged++;
    478:         else    tagged[offset++] = j;
    479:       }
    480:     }
    481:   }
    482:   VecRestoreArrayRead(vec, &vecArray);
    483:   PetscFree(boxes);
    484:   ISCreateGeneral(PetscObjectComm((PetscObject)vec),numTagged,tagged,PETSC_OWN_POINTER,is);
    485:   ISSort(*is);
    486:   return(0);
    487: }