Actual source code: cdf.c


  2: #include <petsc/private/vecimpl.h>
  3: #include "../src/vec/vec/utils/tagger/impls/simple.h"

  5: const char *const VecTaggerCDFMethods[VECTAGGER_CDF_NUM_METHODS] = {"gather","iterative"};

  7: #if !defined (PETSC_USE_COMPLEX)
  8: typedef VecTaggerBox VecTaggerBoxReal;
  9: #else
 10: typedef struct {
 11:   PetscReal min;
 12:   PetscReal max;
 13: } VecTaggerBoxReal;
 14: #endif

 16: typedef struct {
 17:   VecTagger_Simple   smpl;
 18:   PetscReal          atol;
 19:   PetscReal          rtol;
 20:   PetscInt           maxit;
 21:   PetscInt           numMoments;
 22:   VecTaggerCDFMethod method;
 23: } VecTagger_CDF;

 25: static PetscErrorCode VecTaggerComputeBox_CDF_SortedArray(const PetscReal *cArray, PetscInt m, const VecTaggerBoxReal *bxs, VecTaggerBoxReal *boxes)
 26: {
 27:   PetscInt    minInd, maxInd;
 28:   PetscReal   minCDF, maxCDF;

 30:   minCDF = PetscMax(0., bxs->min);
 31:   maxCDF = PetscMin(1., bxs->max);
 32:   minInd = (PetscInt) (minCDF * m);
 33:   maxInd = (PetscInt) (maxCDF * m);
 34:   boxes->min = cArray[PetscMin(minInd,m-1)];
 35:   boxes->max = cArray[PetscMax(minInd,maxInd-1)];
 36:   return 0;
 37: }

 39: static PetscErrorCode VecTaggerComputeBoxes_CDF_Serial(VecTagger tagger,Vec vec,PetscInt bs,VecTaggerBox *boxes)
 40: {
 41:   VecTagger_Simple *smpl = (VecTagger_Simple *) tagger->data;
 42:   Vec              vComp;
 43:   PetscInt         n, m;
 44:   PetscInt         i;
 45: #if defined (PETSC_USE_COMPLEX)
 46:   PetscReal        *cReal, *cImag;
 47: #endif

 49:   VecGetLocalSize(vec,&n);
 50:   m    = n/bs;
 51:   VecCreateSeq(PETSC_COMM_SELF,m,&vComp);
 52: #if defined (PETSC_USE_COMPLEX)
 53:   PetscMalloc2(m,&cReal,m,&cImag);
 54: #endif
 55:   for (i = 0; i < bs; i++) {
 56:     IS          isStride;
 57:     VecScatter  vScat;
 58:     PetscScalar *cArray;

 60:     ISCreateStride(PETSC_COMM_SELF,m,i,bs,&isStride);
 61:     VecScatterCreate(vec,isStride,vComp,NULL,&vScat);
 62:     VecScatterBegin(vScat,vec,vComp,INSERT_VALUES,SCATTER_FORWARD);
 63:     VecScatterEnd(vScat,vec,vComp,INSERT_VALUES,SCATTER_FORWARD);
 64:     VecScatterDestroy(&vScat);
 65:     ISDestroy(&isStride);

 67:     VecGetArray(vComp,&cArray);
 68: #if !defined(PETSC_USE_COMPLEX)
 69:     PetscSortReal(m,cArray);
 70:     VecTaggerComputeBox_CDF_SortedArray(cArray,m,&smpl->box[i],&boxes[i]);
 71: #else
 72:     {
 73:       PetscInt         j;
 74:       VecTaggerBoxReal realBxs, imagBxs;
 75:       VecTaggerBoxReal realBoxes, imagBoxes;

 77:       for (j = 0; j < m; j++) {
 78:         cReal[j] = PetscRealPart(cArray[j]);
 79:         cImag[j] = PetscImaginaryPart(cArray[j]);
 80:       }
 81:       PetscSortReal(m,cReal);
 82:       PetscSortReal(m,cImag);

 84:       realBxs.min = PetscRealPart(smpl->box[i].min);
 85:       realBxs.max = PetscRealPart(smpl->box[i].max);
 86:       imagBxs.min = PetscImaginaryPart(smpl->box[i].min);
 87:       imagBxs.max = PetscImaginaryPart(smpl->box[i].max);
 88:       VecTaggerComputeBox_CDF_SortedArray(cReal,m,&realBxs,&realBoxes);
 89:       VecTaggerComputeBox_CDF_SortedArray(cImag,m,&imagBxs,&imagBoxes);
 90:       boxes[i].min = PetscCMPLX(realBoxes.min,imagBoxes.min);
 91:       boxes[i].max = PetscCMPLX(realBoxes.max,imagBoxes.max);
 92:     }
 93: #endif
 94:     VecRestoreArray(vComp,&cArray);
 95:   }
 96: #if defined(PETSC_USE_COMPLEX)
 97:   PetscFree2(cReal,cImag);
 98: #endif
 99:   VecDestroy(&vComp);
100:   return 0;
101: }

103: static PetscErrorCode VecTaggerComputeBoxes_CDF_Gather(VecTagger tagger,Vec vec,PetscInt bs,VecTaggerBox *boxes)
104: {
105:   Vec            gVec = NULL;
106:   VecScatter     vScat;
107:   PetscMPIInt    rank;

109:   VecScatterCreateToZero(vec,&vScat,&gVec);
110:   VecScatterBegin(vScat,vec,gVec,INSERT_VALUES,SCATTER_FORWARD);
111:   VecScatterEnd(vScat,vec,gVec,INSERT_VALUES,SCATTER_FORWARD);
112:   VecScatterDestroy(&vScat);
113:   MPI_Comm_rank (PetscObjectComm((PetscObject)vec),&rank);
114:   if (rank == 0) {
115:     VecTaggerComputeBoxes_CDF_Serial(tagger,gVec,bs,boxes);
116:   }
117:   MPI_Bcast((PetscScalar *)boxes,2*bs,MPIU_SCALAR,0,PetscObjectComm((PetscObject)vec));
118:   VecDestroy(&gVec);
119:   return 0;
120: }

122: typedef struct _n_CDFStats
123: {
124:   PetscReal min;
125:   PetscReal max;
126:   PetscReal moment[3];
127: } CDFStats;

129: static void MPIAPI VecTaggerCDFStatsReduce(void *a, void *b, int * len, MPI_Datatype *datatype)
130: {
131:   PetscInt  i, j, N = *len;
132:   CDFStats *A = (CDFStats *) a;
133:   CDFStats *B = (CDFStats *) b;

135:   for (i = 0; i < N; i++) {
136:     B[i].min = PetscMin(A[i].min,B[i].min);
137:     B[i].max = PetscMax(A[i].max,B[i].max);
138:     for (j = 0; j < 3; j++) {
139:       B[i].moment[j] += A[i].moment[j];
140:     }
141:   }
142: }

144: static PetscErrorCode CDFUtilInverseEstimate(const CDFStats *stats,PetscReal cdfTarget,PetscReal *absEst)
145: {
146:   PetscReal min, max;

148:   min = stats->min;
149:   max = stats->max;
150:   *absEst = min + cdfTarget * (max - min);
151:   return 0;
152: }

154: static PetscErrorCode VecTaggerComputeBox_CDF_SortedArray_Iterative(VecTagger tagger, MPI_Datatype statType, MPI_Op statReduce, const PetscReal *cArray, PetscInt m, const VecTaggerBoxReal *cdfBox, VecTaggerBoxReal *absBox)
155: {
156:   MPI_Comm       comm;
157:   VecTagger_CDF  *cdf;
158:   PetscInt       maxit, i, j, k, l, M;
159:   PetscInt       bounds[2][2];
160:   PetscInt       offsets[2];
161:   PetscReal      intervalLen = cdfBox->max - cdfBox->min;
162:   PetscReal      rtol, atol;

164:   comm  = PetscObjectComm((PetscObject)tagger);
165:   cdf   = (VecTagger_CDF *) tagger->data;
166:   maxit = cdf->maxit;
167:   rtol  = cdf->rtol;
168:   atol  = cdf->atol;
169:   /* local range of sorted values that can contain the sought radix */
170:   offsets[0] = 0;
171:   offsets[1] = 0;
172:   bounds[0][0] = 0; bounds[0][1] = m;
173:   bounds[1][0] = 0; bounds[1][1] = m;
174:   VecTaggerComputeBox_CDF_SortedArray(cArray,m,cdfBox,absBox); /* compute a local estimate of the interval */
175:   {
176:     CDFStats stats[3];

178:     for (i = 0; i < 2; i++) { /* compute statistics of those local estimates */
179:       PetscReal val = i ? absBox->max : absBox->min;

181:       stats[i].min = m ? val : PETSC_MAX_REAL;
182:       stats[i].max = m ? val : PETSC_MIN_REAL;
183:       stats[i].moment[0] = m;
184:       stats[i].moment[1] = m * val;
185:       stats[i].moment[2] = m * val * val;
186:     }
187:     stats[2].min = PETSC_MAX_REAL;
188:     stats[2].max = PETSC_MAX_REAL;
189:     for (i = 0; i < 3; i++) {
190:       stats[2].moment[i] = 0.;
191:     }
192:     for (i = 0; i < m; i++) {
193:       PetscReal val = cArray[i];

195:       stats[2].min = PetscMin(stats[2].min, val);
196:       stats[2].max = PetscMax(stats[2].max, val);
197:       stats[2].moment[0] ++;
198:       stats[2].moment[1] += val;
199:       stats[2].moment[2] += val * val;
200:     }
201:     /* reduce those statistics */
202:     MPI_Allreduce(MPI_IN_PLACE,stats,3,statType,statReduce,comm);
203:     M    = (PetscInt) stats[2].moment[0];
204:     /* use those initial statistics to get the initial (globally agreed-upon) choices for the absolute box bounds */
205:     for (i = 0; i < 2; i++) {
206:       CDFUtilInverseEstimate(&stats[i],i ? cdfBox->max : cdfBox->min,(i ? &absBox->max : &absBox->min));
207:     }
208:   }
209:   /* refine the estimates by computing how close they come to the desired box and refining */
210:   for (k = 0; k < maxit; k++) {
211:     PetscReal maxDiff = 0.;

213:     CDFStats stats[2][2];
214:     PetscInt newBounds[2][2][2];
215:     for (i = 0; i < 2; i++) {
216:       for (j = 0; j < 2; j++) {
217:         stats[i][j].min = PETSC_MAX_REAL;
218:         stats[i][j].max = PETSC_MIN_REAL;
219:         for (l = 0; l < 3; l++) {
220:           stats[i][j].moment[l] = 0.;
221:         }
222:         newBounds[i][j][0] = PetscMax(bounds[i][0],bounds[i][1]);
223:         newBounds[i][j][1] = PetscMin(bounds[i][0],bounds[i][1]);
224:       }
225:     }
226:     for (i = 0; i < 2; i++) {
227:       for (j = 0; j < bounds[i][1] - bounds[i][0]; j++) {
228:         PetscInt  thisInd = bounds[i][0] + j;
229:         PetscReal val     = cArray[thisInd];
230:         PetscInt  section;
231:         if (!i) {
232:           section = (val <  absBox->min) ? 0 : 1;
233:         } else {
234:           section = (val <= absBox->max) ? 0 : 1;
235:         }
236:         stats[i][section].min = PetscMin(stats[i][section].min,val);
237:         stats[i][section].max = PetscMax(stats[i][section].max,val);
238:         stats[i][section].moment[0] ++;
239:         stats[i][section].moment[1] += val;
240:         stats[i][section].moment[2] += val * val;
241:         newBounds[i][section][0] = PetscMin(newBounds[i][section][0],thisInd);
242:         newBounds[i][section][1] = PetscMax(newBounds[i][section][0],thisInd + 1);
243:       }
244:     }
245:     MPI_Allreduce(MPI_IN_PLACE, stats, 4, statType, statReduce, comm);
246:     for (i = 0; i < 2; i++) {
247:       PetscInt  totalLessThan = offsets[i] + stats[i][0].moment[0];
248:       PetscReal cdfOfAbs      = (PetscReal) totalLessThan / (PetscReal) M;
249:       PetscReal diff;
250:       PetscInt  section;

252:       if (cdfOfAbs == (i ? cdfBox->max : cdfBox->min)) {
253:         offsets[i] = totalLessThan;
254:         bounds[i][0] = bounds[i][1] = 0;
255:         continue;
256:       }
257:       if (cdfOfAbs > (i ? cdfBox->max : cdfBox->min)) { /* the correct absolute value lies in the lower section */
258:         section = 0;
259:       } else {
260:         section = 1;
261:         offsets[i] = totalLessThan;
262:       }
263:       for (j = 0; j < 2; j++) {
264:         bounds[i][j] = newBounds[i][section][j];
265:       }
266:       CDFUtilInverseEstimate(&stats[i][section],((i ? cdfBox->max : cdfBox->min) - ((PetscReal) offsets[i] / (PetscReal) M))/stats[i][section].moment[0],(i ? &absBox->max : &absBox->min));
267:       diff = PetscAbs(cdfOfAbs - (i ? cdfBox->max : cdfBox->min));
268:       maxDiff = PetscMax(maxDiff,diff);
269:     }
270:     if (!maxDiff) return 0;
271:     if ((atol || rtol) && ((!atol) || (maxDiff <= atol)) && ((!rtol) || (maxDiff <= rtol * intervalLen))) {
272:       break;
273:     }
274:   }
275:   return 0;
276: }

278: static PetscErrorCode VecTaggerComputeBoxes_CDF_Iterative(VecTagger tagger,Vec vec,PetscInt bs,VecTaggerBox *boxes)
279: {
280:   VecTagger_CDF    *cdf = (VecTagger_CDF *) tagger->data;
281:   VecTagger_Simple *smpl = &(cdf->smpl);
282:   Vec              vComp;
283:   PetscInt         i, N, M, n, m, rstart;
284: #if defined (PETSC_USE_COMPLEX)
285:   PetscReal        *cReal, *cImag;
286: #endif
287:   MPI_Comm         comm;
288:   MPI_Datatype     statType;
289:   MPI_Op           statReduce;

291:   comm = PetscObjectComm((PetscObject)vec);
292:   VecGetSize(vec,&N);
293:   VecGetLocalSize(vec,&n);
294:   M    = N/bs;
295:   m    = n/bs;
296:   VecCreateMPI(comm,m,M,&vComp);
297:   VecSetUp(vComp);
298:   VecGetOwnershipRange(vComp,&rstart,NULL);
299: #if defined (PETSC_USE_COMPLEX)
300:   PetscMalloc2(m,&cReal,m,&cImag);
301: #endif
302:   MPI_Type_contiguous(5,MPIU_REAL,&statType);
303:   MPI_Type_commit(&statType);
304:   MPI_Op_create(VecTaggerCDFStatsReduce,1,&statReduce);
305:   for (i = 0; i < bs; i++) {
306:     IS          isStride;
307:     VecScatter  vScat;
308:     PetscScalar *cArray;

310:     ISCreateStride(comm,m,bs * rstart + i,bs,&isStride);
311:     VecScatterCreate(vec,isStride,vComp,NULL,&vScat);
312:     VecScatterBegin(vScat,vec,vComp,INSERT_VALUES,SCATTER_FORWARD);
313:     VecScatterEnd(vScat,vec,vComp,INSERT_VALUES,SCATTER_FORWARD);
314:     VecScatterDestroy(&vScat);
315:     ISDestroy(&isStride);

317:     VecGetArray(vComp,&cArray);
318: #if !defined(PETSC_USE_COMPLEX)
319:     PetscSortReal(m,cArray);
320:     VecTaggerComputeBox_CDF_SortedArray_Iterative(tagger,statType,statReduce,cArray,m,&smpl->box[i],&boxes[i]);
321: #else
322:     {
323:       PetscInt         j;
324:       VecTaggerBoxReal realBxs, imagBxs;
325:       VecTaggerBoxReal realBoxes, imagBoxes;

327:       for (j = 0; j < m; j++) {
328:         cReal[j] = PetscRealPart(cArray[j]);
329:         cImag[j] = PetscImaginaryPart(cArray[j]);
330:       }
331:       PetscSortReal(m,cReal);
332:       PetscSortReal(m,cImag);

334:       realBxs.min = PetscRealPart(smpl->box[i].min);
335:       realBxs.max = PetscRealPart(smpl->box[i].max);
336:       imagBxs.min = PetscImaginaryPart(smpl->box[i].min);
337:       imagBxs.max = PetscImaginaryPart(smpl->box[i].max);
338:       VecTaggerComputeBox_CDF_SortedArray_Iterative(tagger,statType,statReduce,cReal,m,&realBxs,&realBoxes);
339:       VecTaggerComputeBox_CDF_SortedArray_Iterative(tagger,statType,statReduce,cImag,m,&imagBxs,&imagBoxes);
340:       boxes[i].min = PetscCMPLX(realBoxes.min,imagBoxes.min);
341:       boxes[i].max = PetscCMPLX(realBoxes.max,imagBoxes.max);
342:     }
343: #endif
344:     VecRestoreArray(vComp,&cArray);
345:   }
346:   MPI_Op_free(&statReduce);
347:   MPI_Type_free(&statType);
348: #if defined(PETSC_USE_COMPLEX)
349:   PetscFree2(cReal,cImag);
350: #endif
351:   VecDestroy(&vComp);
352:   return 0;
353: }

355: static PetscErrorCode VecTaggerComputeBoxes_CDF(VecTagger tagger,Vec vec,PetscInt *numBoxes,VecTaggerBox **boxes,PetscBool *listed)
356: {
357:   VecTagger_CDF  *cuml = (VecTagger_CDF *)tagger->data;
358:   PetscMPIInt    size;
359:   PetscInt       bs;
360:   VecTaggerBox   *bxs;

362:   VecTaggerGetBlockSize(tagger,&bs);
363:   *numBoxes = 1;
364:   PetscMalloc1(bs,&bxs);
365:   MPI_Comm_size(PetscObjectComm((PetscObject)tagger),&size);
366:   if (size == 1) {
367:     VecTaggerComputeBoxes_CDF_Serial(tagger,vec,bs,bxs);
368:     *boxes = bxs;
369:     return 0;
370:   }
371:   switch (cuml->method) {
372:   case VECTAGGER_CDF_GATHER:
373:     VecTaggerComputeBoxes_CDF_Gather(tagger,vec,bs,bxs);
374:     break;
375:   case VECTAGGER_CDF_ITERATIVE:
376:     VecTaggerComputeBoxes_CDF_Iterative(tagger,vec,bs,bxs);
377:     break;
378:   default:
379:     SETERRQ(PetscObjectComm((PetscObject)tagger),PETSC_ERR_SUP,"Unknown CDF calculation/estimation method.");
380:   }
381:   *boxes = bxs;
382:   if (listed) *listed = PETSC_TRUE;
383:   return 0;
384: }

386: static PetscErrorCode VecTaggerView_CDF(VecTagger tagger,PetscViewer viewer)
387: {
388:   VecTagger_CDF  *cuml = (VecTagger_CDF *) tagger->data;
389:   PetscBool      iascii;
390:   PetscMPIInt    size;

392:   VecTaggerView_Simple(tagger,viewer);
393:   MPI_Comm_size(PetscObjectComm((PetscObject)tagger),&size);
394:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
395:   if (size > 1 && iascii) {
396:     PetscViewerASCIIPrintf(viewer,"CDF computation method: %s\n",VecTaggerCDFMethods[cuml->method]);
397:     if (cuml->method == VECTAGGER_CDF_ITERATIVE) {
398:       PetscViewerASCIIPushTab(viewer);
399:       PetscViewerASCIIPrintf(viewer,"max its: %" PetscInt_FMT ", abs tol: %g, rel tol %g\n",cuml->maxit,(double) cuml->atol,(double) cuml->rtol);
400:       PetscViewerASCIIPopTab(viewer);
401:     }
402:   }
403:   return 0;
404: }

406: static PetscErrorCode VecTaggerSetFromOptions_CDF(PetscOptionItems *PetscOptionsObject,VecTagger tagger)
407: {
408:   VecTagger_CDF *cuml = (VecTagger_CDF *) tagger->data;
409:   PetscInt       method;
410:   PetscBool      set;

412:   VecTaggerSetFromOptions_Simple(PetscOptionsObject,tagger);
413:   PetscOptionsHead(PetscOptionsObject,"VecTagger options for CDF boxes");
414:   PetscOptionsEList("-vec_tagger_cdf_method","Method for computing absolute boxes from CDF boxes","VecTaggerCDFSetMethod()",VecTaggerCDFMethods,VECTAGGER_CDF_NUM_METHODS,VecTaggerCDFMethods[cuml->method],&method,&set);
415:   if (set) cuml->method = (VecTaggerCDFMethod) method;
416:   PetscOptionsInt("-vec_tagger_cdf_max_it","Maximum iterations for iterative computation of absolute boxes from CDF boxes","VecTaggerCDFIterativeSetTolerances()",cuml->maxit,&cuml->maxit,NULL);
417:   PetscOptionsReal("-vec_tagger_cdf_rtol","Maximum relative tolerance for iterative computation of absolute boxes from CDF boxes","VecTaggerCDFIterativeSetTolerances()",cuml->rtol,&cuml->rtol,NULL);
418:   PetscOptionsReal("-vec_tagger_cdf_atol","Maximum absolute tolerance for iterative computation of absolute boxes from CDF boxes","VecTaggerCDFIterativeSetTolerances()",cuml->atol,&cuml->atol,NULL);
419:   PetscOptionsTail();
420:   return 0;
421: }

423: /*@C
424:   VecTaggerCDFSetMethod - Set the method used to compute absolute boxes from CDF boxes

426:   Logically Collective on VecTagger

428:   Level: advanced

430:   Input Parameters:
431: + tagger - the VecTagger context
432: - method - the method

434: .seealso VecTaggerCDFMethod
435: @*/
436: PetscErrorCode VecTaggerCDFSetMethod(VecTagger tagger, VecTaggerCDFMethod method)
437: {
438:   VecTagger_CDF  *cuml = (VecTagger_CDF *) tagger->data;

442:   cuml->method = method;
443:   return 0;
444: }

446: /*@C
447:   VecTaggerCDFGetMethod - Get the method used to compute absolute boxes from CDF boxes

449:   Logically Collective on VecTagger

451:   Level: advanced

453:   Input Parameters:
454: . tagger - the VecTagger context

456:   Output Parameters:
457: . method - the method

459: .seealso VecTaggerCDFMethod
460: @*/
461: PetscErrorCode VecTaggerCDFGetMethod(VecTagger tagger, VecTaggerCDFMethod *method)
462: {
463:   VecTagger_CDF  *cuml = (VecTagger_CDF *) tagger->data;

467:   *method = cuml->method;
468:   return 0;
469: }

471: /*@C
472:   VecTaggerCDFIterativeSetTolerances - Set the tolerances for iterative computation of absolute boxes from CDF boxes.

474:   Logically Collective on VecTagger

476:   Input Parameters:
477: + tagger - the VecTagger context
478: . maxit - the maximum number of iterations: 0 indicates the absolute values will be estimated from an initial guess based only on the minimum, maximum, mean, and standard deviation of the box endpoints.
479: . rtol - the acceptable relative tolerance in the absolute values from the initial guess
480: - atol - the acceptable absolute tolerance in the absolute values from the initial guess

482:   Level: advanced

484: .seealso: VecTaggerCDFSetMethod()
485: @*/
486: PetscErrorCode VecTaggerCDFIterativeSetTolerances(VecTagger tagger, PetscInt maxit, PetscReal rtol, PetscReal atol)
487: {
488:   VecTagger_CDF  *cuml = (VecTagger_CDF *) tagger->data;

494:   cuml->maxit = maxit;
495:   cuml->rtol  = rtol;
496:   cuml->atol  = atol;
497:   return 0;
498: }

500: /*@C
501:   VecTaggerCDFIterativeGetTolerances - Get the tolerances for iterative computation of absolute boxes from CDF boxes.

503:   Logically Collective on VecTagger

505:   Input Parameter:
506: . tagger - the VecTagger context

508:   Output Parameters:
509: + maxit - the maximum number of iterations: 0 indicates the absolute values will be estimated from an initial guess based only on the minimum, maximum, mean, and standard deviation of the box endpoints.
510: . rtol - the acceptable relative tolerance in the absolute values from the initial guess
511: - atol - the acceptable absolute tolerance in the absolute values from the initial guess

513:   Level: advanced

515: .seealso: VecTaggerCDFSetMethod()
516: @*/
517: PetscErrorCode VecTaggerCDFIterativeGetTolerances(VecTagger tagger, PetscInt *maxit, PetscReal *rtol, PetscReal *atol)
518: {
519:   VecTagger_CDF  *cuml = (VecTagger_CDF *) tagger->data;

522:   if (maxit) *maxit = cuml->maxit;
523:   if (rtol)  *rtol  = cuml->rtol;
524:   if (atol)  *atol  = cuml->atol;
525:   return 0;
526: }

528: /*@C
529:   VecTaggerCDFSetBox - Set the cumulative box defining the values to be tagged by the tagger, where cumulative boxes are subsets of [0,1], where 0 indicates the smallest value present in the vector and 1 indicates the largest.

531:   Logically Collective

533:   Input Parameters:
534: + tagger - the VecTagger context
535: - boxes - a blocksize array of VecTaggerBox boxes

537:   Level: advanced

539: .seealso: VecTaggerCDFGetBox()
540: @*/
541: PetscErrorCode VecTaggerCDFSetBox(VecTagger tagger,VecTaggerBox *box)
542: {
543:   VecTaggerSetBox_Simple(tagger,box);
544:   return 0;
545: }

547: /*@C
548:   VecTaggerCDFGetBox - Get the cumulative box (multi-dimensional box) defining the values to be tagged by the tagger, where cumulative boxes are subsets of [0,1], where 0 indicates the smallest value present in the vector and 1 indicates the largest.

550:   Logically Collective

552:   Input Parameter:
553: . tagger - the VecTagger context

555:   Output Parameter:
556: . boxes - a blocksize array of VecTaggerBox boxes

558:   Level: advanced

560: .seealso: VecTaggerCDFSetBox()
561: @*/
562: PetscErrorCode VecTaggerCDFGetBox(VecTagger tagger,const VecTaggerBox **box)
563: {
564:   VecTaggerGetBox_Simple(tagger,box);
565:   return 0;
566: }

568: PETSC_INTERN PetscErrorCode VecTaggerCreate_CDF(VecTagger tagger)
569: {
570:   VecTagger_CDF  *cuml;

572:   VecTaggerCreate_Simple(tagger);
573:   PetscNewLog(tagger,&cuml);
574:   PetscMemcpy(&cuml->smpl,tagger->data,sizeof(VecTagger_Simple));
575:   PetscFree(tagger->data);
576:   tagger->data = cuml;
577:   tagger->ops->view           = VecTaggerView_CDF;
578:   tagger->ops->setfromoptions = VecTaggerSetFromOptions_CDF;
579:   tagger->ops->computeboxes   = VecTaggerComputeBoxes_CDF;
580:   return 0;
581: }