Actual source code: tagger.c

petsc-3.11.3 2019-06-26
Report Typos and Errors
  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 Arguments:
 23: .  comm - communicator on which the vec tagger will operate

 25:    Output Arguments:
 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: .keywords: VecTagger, set, type

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


 87:   PetscObjectTypeCompare((PetscObject)tagger,type,&match);
 88:   if (match) return(0);

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

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

106:   Not Collective

108:   Input Parameter:
109: . tagger  - The Vec tagger context

111:   Output Parameter:
112: . type - The VecTagger type name

114:   Level: advanced

116: .keywords: VecTagger, get, type, name
117: .seealso: VecTaggerSetType(), VecTaggerCreate()
118: @*/
119: PetscErrorCode  VecTaggerGetType(VecTagger tagger, VecTaggerType *type)
120: {

126:   VecTaggerRegisterAll();
127:   *type = ((PetscObject)tagger)->type_name;
128:   return(0);
129: }

131: /*@
132:    VecTaggerDestroy - destroy a VecTagger context

134:    Collective

136:    Input Arguments:
137: .  tagger - address of tagger

139:    Level: advanced

141: .seealso: VecTaggerCreate()
142: @*/
143: PetscErrorCode VecTaggerDestroy(VecTagger *tagger)
144: {

148:   if (!*tagger) return(0);
150:   if (--((PetscObject)(*tagger))->refct > 0) {*tagger = 0; return(0);}
151:   if ((*tagger)->ops->destroy) {(*(*tagger)->ops->destroy)(*tagger);}
152:   PetscHeaderDestroy(tagger);
153:   return(0);
154: }

156: /*@
157:    VecTaggerSetUp - set up a VecTagger context

159:    Collective

161:    Input Arguments:
162: .  tagger - Vec tagger object

164:    Level: advanced

166: .seealso: VecTaggerSetFromOptions(), VecTaggerSetType()
167: @*/
168: PetscErrorCode VecTaggerSetUp(VecTagger tagger)
169: {

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

180: /*@C
181:    VecTaggerSetFromOptions - set VecTagger options using the options database

183:    Logically Collective

185:    Input Arguments:
186: .  tagger - vec tagger

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

193:    Level: advanced

195: .keywords: tagging, set, from, options, database
196: @*/
197: PetscErrorCode VecTaggerSetFromOptions(VecTagger tagger)
198: {
199:   VecTaggerType  deft;
200:   char           type[256];
202:   PetscBool      flg;

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

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

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

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

230:    Logically Collective

232:    Input Arguments:
233: +  tagger - vec tagger
234: -  blocksize - block size of the criteria used to tagger vectors

236:    Level: advanced

238: .seealso: VecTaggerComputeIS(), VecTaggerGetBlockSize(), VecSetBlockSize(), VecGetBlockSize()
239: @*/
240: PetscErrorCode VecTaggerSetBlockSize(VecTagger tagger, PetscInt blocksize)
241: {

246:   tagger->blocksize = blocksize;
247:   return(0);
248: }

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

253:    Logically Collective

255:    Input Arguments:
256: +  tagger - vec tagger
257: -  blocksize - block size of the vectors the tagger operates on

259:    Level: advanced

261: .seealso: VecTaggerComputeIS(), VecTaggerSetBlockSize(),
262: @*/
263: PetscErrorCode VecTaggerGetBlockSize(VecTagger tagger, PetscInt *blocksize)
264: {

269:   *blocksize = tagger->blocksize;
270:   return(0);
271: }

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

278:    Logically Collective

280:    Input Arguments:
281: +  tagger - vec tagger
282: -  invert - PETSC_TRUE to invert, PETSC_FALSE to use the indices as is

284:    Level: advanced

286: .seealso: VecTaggerComputeIS(), VecTaggerGetInvert()
287: @*/
288: PetscErrorCode VecTaggerSetInvert(VecTagger tagger, PetscBool invert)
289: {

294:   tagger->invert = invert;
295:   return(0);
296: }

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

301:    Logically Collective

303:    Input Arguments:
304: +  tagger - vec tagger
305: -  invert - PETSC_TRUE to invert, PETSC_FALSE to use the indices as is

307:    Level: advanced

309: .seealso: VecTaggerComputeIS(), VecTaggerSetInvert()
310: @*/
311: PetscErrorCode VecTaggerGetInvert(VecTagger tagger, PetscBool *invert)
312: {

317:   *invert = tagger->invert;
318:   return(0);
319: }

321: /*@C
322:    VecTaggerView - view a VecTagger context

324:    Collective

326:    Input Arguments:
327: +  tagger - vec tagger
328: -  viewer - viewer to display tagger, for example PETSC_VIEWER_STDOUT_WORLD

330:    Level: advanced

332: .seealso: VecTaggerCreate()
333: @*/
334: PetscErrorCode VecTaggerView(VecTagger tagger,PetscViewer viewer)
335: {
336:   PetscErrorCode    ierr;
337:   PetscBool         iascii;

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

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

359:    Collective on VecTagger

361:    Input Aguments:
362: +  tagger - the VecTagger context
363: -  vec - the vec to tag

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

369:    Notes:
370: .  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.

372:    Level: advanced

374: .seealso: VecTaggerComputeIS()
375: @*/
376: PetscErrorCode VecTaggerComputeBoxes(VecTagger tagger,Vec vec,PetscInt *numBoxes,VecTaggerBox **boxes)
377: {
378:   PetscInt       vls, tbs;

386:   VecGetLocalSize(vec,&vls);
387:   VecTaggerGetBlockSize(tagger,&tbs);
388:   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);
389:   if (tagger->ops->computeboxes) {(*tagger->ops->computeboxes) (tagger,vec,numBoxes,boxes);}
390:   else {
391:     const char *type;
392:     PetscObjectGetType ((PetscObject)tagger,&type);
393:     SETERRQ1(PetscObjectComm((PetscObject)tagger),PETSC_ERR_SUP,"VecTagger type %s does not compute value boxes",type);
394:   }
395:   return(0);
396: }

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

401:    Collective on VecTagger

403:    Input Aguments:
404: +  tagger - the VecTagger context
405: -  vec - the vec to tag

407:    Output Arguments:
408: .  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().

410:    Level: advanced

412: .seealso: VecTaggerComputeBoxes()
413: @*/
414: PetscErrorCode VecTaggerComputeIS(VecTagger tagger,Vec vec,IS *is)
415: {
416:   PetscInt       vls, tbs;

423:   VecGetLocalSize(vec,&vls);
424:   VecTaggerGetBlockSize(tagger,&tbs);
425:   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);
426:   if (tagger->ops->computeis) {(*tagger->ops->computeis) (tagger,vec,is);}
427:   else {
428:     SETERRQ(PetscObjectComm((PetscObject)tagger),PETSC_ERR_SUP,"VecTagger type does not compute ISs");
429:   }
430:   return(0);
431: }

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

444:   VecTaggerGetBlockSize(tagger,&bs);
445:   VecTaggerComputeBoxes(tagger,vec,&numBoxes,&boxes);
446:   VecGetArrayRead(vec, &vecArray);
447:   VecGetLocalSize(vec, &n);
448:   invert = tagger->invert;
449:   numTagged = 0;
450:   offset = 0;
451:   tagged = NULL;
452:   for (i = 0; i < 2; i++) {
453:     if (i) {
454:       PetscMalloc1(numTagged,&tagged);
455:     }
456:     for (j = 0; j < n; j++) {

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

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