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) VecTaggerComputeBoxes_CDF_Serial(tagger, gVec, bs, boxes);
115: MPI_Bcast((PetscScalar *)boxes, 2 * bs, MPIU_SCALAR, 0, PetscObjectComm((PetscObject)vec));
116: VecDestroy(&gVec);
117: return 0;
118: }
120: typedef struct _n_CDFStats {
121: PetscReal min;
122: PetscReal max;
123: PetscReal moment[3];
124: } CDFStats;
126: static void MPIAPI VecTaggerCDFStatsReduce(void *a, void *b, int *len, MPI_Datatype *datatype)
127: {
128: PetscInt i, j, N = *len;
129: CDFStats *A = (CDFStats *)a;
130: CDFStats *B = (CDFStats *)b;
132: for (i = 0; i < N; i++) {
133: B[i].min = PetscMin(A[i].min, B[i].min);
134: B[i].max = PetscMax(A[i].max, B[i].max);
135: for (j = 0; j < 3; j++) B[i].moment[j] += A[i].moment[j];
136: }
137: }
139: static PetscErrorCode CDFUtilInverseEstimate(const CDFStats *stats, PetscReal cdfTarget, PetscReal *absEst)
140: {
141: PetscReal min, max;
143: min = stats->min;
144: max = stats->max;
145: *absEst = min + cdfTarget * (max - min);
146: return 0;
147: }
149: static PetscErrorCode VecTaggerComputeBox_CDF_SortedArray_Iterative(VecTagger tagger, MPI_Datatype statType, MPI_Op statReduce, const PetscReal *cArray, PetscInt m, const VecTaggerBoxReal *cdfBox, VecTaggerBoxReal *absBox)
150: {
151: MPI_Comm comm;
152: VecTagger_CDF *cdf;
153: PetscInt maxit, i, j, k, l, M;
154: PetscInt bounds[2][2];
155: PetscInt offsets[2];
156: PetscReal intervalLen = cdfBox->max - cdfBox->min;
157: PetscReal rtol, atol;
159: comm = PetscObjectComm((PetscObject)tagger);
160: cdf = (VecTagger_CDF *)tagger->data;
161: maxit = cdf->maxit;
162: rtol = cdf->rtol;
163: atol = cdf->atol;
164: /* local range of sorted values that can contain the sought radix */
165: offsets[0] = 0;
166: offsets[1] = 0;
167: bounds[0][0] = 0;
168: bounds[0][1] = m;
169: bounds[1][0] = 0;
170: bounds[1][1] = m;
171: VecTaggerComputeBox_CDF_SortedArray(cArray, m, cdfBox, absBox); /* compute a local estimate of the interval */
172: {
173: CDFStats stats[3];
175: for (i = 0; i < 2; i++) { /* compute statistics of those local estimates */
176: PetscReal val = i ? absBox->max : absBox->min;
178: stats[i].min = m ? val : PETSC_MAX_REAL;
179: stats[i].max = m ? val : PETSC_MIN_REAL;
180: stats[i].moment[0] = m;
181: stats[i].moment[1] = m * val;
182: stats[i].moment[2] = m * val * val;
183: }
184: stats[2].min = PETSC_MAX_REAL;
185: stats[2].max = PETSC_MAX_REAL;
186: for (i = 0; i < 3; i++) stats[2].moment[i] = 0.;
187: for (i = 0; i < m; i++) {
188: PetscReal val = cArray[i];
190: stats[2].min = PetscMin(stats[2].min, val);
191: stats[2].max = PetscMax(stats[2].max, val);
192: stats[2].moment[0]++;
193: stats[2].moment[1] += val;
194: stats[2].moment[2] += val * val;
195: }
196: /* reduce those statistics */
197: MPI_Allreduce(MPI_IN_PLACE, stats, 3, statType, statReduce, comm);
198: M = (PetscInt)stats[2].moment[0];
199: /* use those initial statistics to get the initial (globally agreed-upon) choices for the absolute box bounds */
200: for (i = 0; i < 2; i++) CDFUtilInverseEstimate(&stats[i], i ? cdfBox->max : cdfBox->min, (i ? &absBox->max : &absBox->min));
201: }
202: /* refine the estimates by computing how close they come to the desired box and refining */
203: for (k = 0; k < maxit; k++) {
204: PetscReal maxDiff = 0.;
206: CDFStats stats[2][2];
207: PetscInt newBounds[2][2][2];
208: for (i = 0; i < 2; i++) {
209: for (j = 0; j < 2; j++) {
210: stats[i][j].min = PETSC_MAX_REAL;
211: stats[i][j].max = PETSC_MIN_REAL;
212: for (l = 0; l < 3; l++) stats[i][j].moment[l] = 0.;
213: newBounds[i][j][0] = PetscMax(bounds[i][0], bounds[i][1]);
214: newBounds[i][j][1] = PetscMin(bounds[i][0], bounds[i][1]);
215: }
216: }
217: for (i = 0; i < 2; i++) {
218: for (j = 0; j < bounds[i][1] - bounds[i][0]; j++) {
219: PetscInt thisInd = bounds[i][0] + j;
220: PetscReal val = cArray[thisInd];
221: PetscInt section;
222: if (!i) {
223: section = (val < absBox->min) ? 0 : 1;
224: } else {
225: section = (val <= absBox->max) ? 0 : 1;
226: }
227: stats[i][section].min = PetscMin(stats[i][section].min, val);
228: stats[i][section].max = PetscMax(stats[i][section].max, val);
229: stats[i][section].moment[0]++;
230: stats[i][section].moment[1] += val;
231: stats[i][section].moment[2] += val * val;
232: newBounds[i][section][0] = PetscMin(newBounds[i][section][0], thisInd);
233: newBounds[i][section][1] = PetscMax(newBounds[i][section][0], thisInd + 1);
234: }
235: }
236: MPI_Allreduce(MPI_IN_PLACE, stats, 4, statType, statReduce, comm);
237: for (i = 0; i < 2; i++) {
238: PetscInt totalLessThan = offsets[i] + stats[i][0].moment[0];
239: PetscReal cdfOfAbs = (PetscReal)totalLessThan / (PetscReal)M;
240: PetscReal diff;
241: PetscInt section;
243: if (cdfOfAbs == (i ? cdfBox->max : cdfBox->min)) {
244: offsets[i] = totalLessThan;
245: bounds[i][0] = bounds[i][1] = 0;
246: continue;
247: }
248: if (cdfOfAbs > (i ? cdfBox->max : cdfBox->min)) { /* the correct absolute value lies in the lower section */
249: section = 0;
250: } else {
251: section = 1;
252: offsets[i] = totalLessThan;
253: }
254: for (j = 0; j < 2; j++) bounds[i][j] = newBounds[i][section][j];
255: CDFUtilInverseEstimate(&stats[i][section], ((i ? cdfBox->max : cdfBox->min) - ((PetscReal)offsets[i] / (PetscReal)M)) / stats[i][section].moment[0], (i ? &absBox->max : &absBox->min));
256: diff = PetscAbs(cdfOfAbs - (i ? cdfBox->max : cdfBox->min));
257: maxDiff = PetscMax(maxDiff, diff);
258: }
259: if (!maxDiff) return 0;
260: if ((atol || rtol) && ((!atol) || (maxDiff <= atol)) && ((!rtol) || (maxDiff <= rtol * intervalLen))) break;
261: }
262: return 0;
263: }
265: static PetscErrorCode VecTaggerComputeBoxes_CDF_Iterative(VecTagger tagger, Vec vec, PetscInt bs, VecTaggerBox *boxes)
266: {
267: VecTagger_CDF *cdf = (VecTagger_CDF *)tagger->data;
268: VecTagger_Simple *smpl = &(cdf->smpl);
269: Vec vComp;
270: PetscInt i, N, M, n, m, rstart;
271: #if defined(PETSC_USE_COMPLEX)
272: PetscReal *cReal, *cImag;
273: #endif
274: MPI_Comm comm;
275: MPI_Datatype statType;
276: MPI_Op statReduce;
278: comm = PetscObjectComm((PetscObject)vec);
279: VecGetSize(vec, &N);
280: VecGetLocalSize(vec, &n);
281: M = N / bs;
282: m = n / bs;
283: VecCreateMPI(comm, m, M, &vComp);
284: VecSetUp(vComp);
285: VecGetOwnershipRange(vComp, &rstart, NULL);
286: #if defined(PETSC_USE_COMPLEX)
287: PetscMalloc2(m, &cReal, m, &cImag);
288: #endif
289: MPI_Type_contiguous(5, MPIU_REAL, &statType);
290: MPI_Type_commit(&statType);
291: MPI_Op_create(VecTaggerCDFStatsReduce, 1, &statReduce);
292: for (i = 0; i < bs; i++) {
293: IS isStride;
294: VecScatter vScat;
295: PetscScalar *cArray;
297: ISCreateStride(comm, m, bs * rstart + i, bs, &isStride);
298: VecScatterCreate(vec, isStride, vComp, NULL, &vScat);
299: VecScatterBegin(vScat, vec, vComp, INSERT_VALUES, SCATTER_FORWARD);
300: VecScatterEnd(vScat, vec, vComp, INSERT_VALUES, SCATTER_FORWARD);
301: VecScatterDestroy(&vScat);
302: ISDestroy(&isStride);
304: VecGetArray(vComp, &cArray);
305: #if !defined(PETSC_USE_COMPLEX)
306: PetscSortReal(m, cArray);
307: VecTaggerComputeBox_CDF_SortedArray_Iterative(tagger, statType, statReduce, cArray, m, &smpl->box[i], &boxes[i]);
308: #else
309: {
310: PetscInt j;
311: VecTaggerBoxReal realBxs, imagBxs;
312: VecTaggerBoxReal realBoxes, imagBoxes;
314: for (j = 0; j < m; j++) {
315: cReal[j] = PetscRealPart(cArray[j]);
316: cImag[j] = PetscImaginaryPart(cArray[j]);
317: }
318: PetscSortReal(m, cReal);
319: PetscSortReal(m, cImag);
321: realBxs.min = PetscRealPart(smpl->box[i].min);
322: realBxs.max = PetscRealPart(smpl->box[i].max);
323: imagBxs.min = PetscImaginaryPart(smpl->box[i].min);
324: imagBxs.max = PetscImaginaryPart(smpl->box[i].max);
325: VecTaggerComputeBox_CDF_SortedArray_Iterative(tagger, statType, statReduce, cReal, m, &realBxs, &realBoxes);
326: VecTaggerComputeBox_CDF_SortedArray_Iterative(tagger, statType, statReduce, cImag, m, &imagBxs, &imagBoxes);
327: boxes[i].min = PetscCMPLX(realBoxes.min, imagBoxes.min);
328: boxes[i].max = PetscCMPLX(realBoxes.max, imagBoxes.max);
329: }
330: #endif
331: VecRestoreArray(vComp, &cArray);
332: }
333: MPI_Op_free(&statReduce);
334: MPI_Type_free(&statType);
335: #if defined(PETSC_USE_COMPLEX)
336: PetscFree2(cReal, cImag);
337: #endif
338: VecDestroy(&vComp);
339: return 0;
340: }
342: static PetscErrorCode VecTaggerComputeBoxes_CDF(VecTagger tagger, Vec vec, PetscInt *numBoxes, VecTaggerBox **boxes, PetscBool *listed)
343: {
344: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
345: PetscMPIInt size;
346: PetscInt bs;
347: VecTaggerBox *bxs;
349: VecTaggerGetBlockSize(tagger, &bs);
350: *numBoxes = 1;
351: PetscMalloc1(bs, &bxs);
352: MPI_Comm_size(PetscObjectComm((PetscObject)tagger), &size);
353: if (size == 1) {
354: VecTaggerComputeBoxes_CDF_Serial(tagger, vec, bs, bxs);
355: *boxes = bxs;
356: return 0;
357: }
358: switch (cuml->method) {
359: case VECTAGGER_CDF_GATHER:
360: VecTaggerComputeBoxes_CDF_Gather(tagger, vec, bs, bxs);
361: break;
362: case VECTAGGER_CDF_ITERATIVE:
363: VecTaggerComputeBoxes_CDF_Iterative(tagger, vec, bs, bxs);
364: break;
365: default:
366: SETERRQ(PetscObjectComm((PetscObject)tagger), PETSC_ERR_SUP, "Unknown CDF calculation/estimation method.");
367: }
368: *boxes = bxs;
369: if (listed) *listed = PETSC_TRUE;
370: return 0;
371: }
373: static PetscErrorCode VecTaggerView_CDF(VecTagger tagger, PetscViewer viewer)
374: {
375: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
376: PetscBool iascii;
377: PetscMPIInt size;
379: VecTaggerView_Simple(tagger, viewer);
380: MPI_Comm_size(PetscObjectComm((PetscObject)tagger), &size);
381: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
382: if (size > 1 && iascii) {
383: PetscViewerASCIIPrintf(viewer, "CDF computation method: %s\n", VecTaggerCDFMethods[cuml->method]);
384: if (cuml->method == VECTAGGER_CDF_ITERATIVE) {
385: PetscViewerASCIIPushTab(viewer);
386: PetscViewerASCIIPrintf(viewer, "max its: %" PetscInt_FMT ", abs tol: %g, rel tol %g\n", cuml->maxit, (double)cuml->atol, (double)cuml->rtol);
387: PetscViewerASCIIPopTab(viewer);
388: }
389: }
390: return 0;
391: }
393: static PetscErrorCode VecTaggerSetFromOptions_CDF(VecTagger tagger, PetscOptionItems *PetscOptionsObject)
394: {
395: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
396: PetscInt method;
397: PetscBool set;
399: VecTaggerSetFromOptions_Simple(tagger, PetscOptionsObject);
400: PetscOptionsHeadBegin(PetscOptionsObject, "VecTagger options for CDF boxes");
401: PetscOptionsEList("-vec_tagger_cdf_method", "Method for computing absolute boxes from CDF boxes", "VecTaggerCDFSetMethod()", VecTaggerCDFMethods, VECTAGGER_CDF_NUM_METHODS, VecTaggerCDFMethods[cuml->method], &method, &set);
402: if (set) cuml->method = (VecTaggerCDFMethod)method;
403: PetscOptionsInt("-vec_tagger_cdf_max_it", "Maximum iterations for iterative computation of absolute boxes from CDF boxes", "VecTaggerCDFIterativeSetTolerances()", cuml->maxit, &cuml->maxit, NULL);
404: PetscOptionsReal("-vec_tagger_cdf_rtol", "Maximum relative tolerance for iterative computation of absolute boxes from CDF boxes", "VecTaggerCDFIterativeSetTolerances()", cuml->rtol, &cuml->rtol, NULL);
405: PetscOptionsReal("-vec_tagger_cdf_atol", "Maximum absolute tolerance for iterative computation of absolute boxes from CDF boxes", "VecTaggerCDFIterativeSetTolerances()", cuml->atol, &cuml->atol, NULL);
406: PetscOptionsHeadEnd();
407: return 0;
408: }
410: /*@C
411: VecTaggerCDFSetMethod - Set the method used to compute absolute boxes from CDF boxes
413: Logically Collective on tagger
415: Level: advanced
417: Input Parameters:
418: + tagger - the `VecTagger` context
419: - method - the method
421: .seealso: `Vec`, `VecTagger`, `VecTaggerCDFMethod`
422: @*/
423: PetscErrorCode VecTaggerCDFSetMethod(VecTagger tagger, VecTaggerCDFMethod method)
424: {
425: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
429: cuml->method = method;
430: return 0;
431: }
433: /*@C
434: VecTaggerCDFGetMethod - Get the method used to compute absolute boxes from CDF boxes
436: Logically Collective on tagger
438: Level: advanced
440: Input Parameters:
441: . tagger - the `VecTagger` context
443: Output Parameters:
444: . method - the method
446: .seealso: `Vec`, `VecTagger`, `VecTaggerCDFMethod`
447: @*/
448: PetscErrorCode VecTaggerCDFGetMethod(VecTagger tagger, VecTaggerCDFMethod *method)
449: {
450: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
454: *method = cuml->method;
455: return 0;
456: }
458: /*@C
459: VecTaggerCDFIterativeSetTolerances - Set the tolerances for iterative computation of absolute boxes from CDF boxes.
461: Logically Collective on VecTagger
463: Input Parameters:
464: + tagger - the VecTagger context
465: . 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.
466: . rtol - the acceptable relative tolerance in the absolute values from the initial guess
467: - atol - the acceptable absolute tolerance in the absolute values from the initial guess
469: Level: advanced
471: .seealso: `VecTaggerCDFSetMethod()`
472: @*/
473: PetscErrorCode VecTaggerCDFIterativeSetTolerances(VecTagger tagger, PetscInt maxit, PetscReal rtol, PetscReal atol)
474: {
475: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
481: cuml->maxit = maxit;
482: cuml->rtol = rtol;
483: cuml->atol = atol;
484: return 0;
485: }
487: /*@C
488: VecTaggerCDFIterativeGetTolerances - Get the tolerances for iterative computation of absolute boxes from CDF boxes.
490: Logically Collective on VecTagger
492: Input Parameter:
493: . tagger - the VecTagger context
495: Output Parameters:
496: + 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.
497: . rtol - the acceptable relative tolerance in the absolute values from the initial guess
498: - atol - the acceptable absolute tolerance in the absolute values from the initial guess
500: Level: advanced
502: .seealso: `VecTaggerCDFSetMethod()`
503: @*/
504: PetscErrorCode VecTaggerCDFIterativeGetTolerances(VecTagger tagger, PetscInt *maxit, PetscReal *rtol, PetscReal *atol)
505: {
506: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
509: if (maxit) *maxit = cuml->maxit;
510: if (rtol) *rtol = cuml->rtol;
511: if (atol) *atol = cuml->atol;
512: return 0;
513: }
515: /*@C
516: 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.
518: Logically Collective
520: Input Parameters:
521: + tagger - the VecTagger context
522: - boxes - a blocksize array of VecTaggerBox boxes
524: Level: advanced
526: .seealso: `VecTaggerCDFGetBox()`
527: @*/
528: PetscErrorCode VecTaggerCDFSetBox(VecTagger tagger, VecTaggerBox *box)
529: {
530: VecTaggerSetBox_Simple(tagger, box);
531: return 0;
532: }
534: /*@C
535: 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.
537: Logically Collective
539: Input Parameter:
540: . tagger - the VecTagger context
542: Output Parameter:
543: . boxes - a blocksize array of VecTaggerBox boxes
545: Level: advanced
547: .seealso: `VecTaggerCDFSetBox()`
548: @*/
549: PetscErrorCode VecTaggerCDFGetBox(VecTagger tagger, const VecTaggerBox **box)
550: {
551: VecTaggerGetBox_Simple(tagger, box);
552: return 0;
553: }
555: PETSC_INTERN PetscErrorCode VecTaggerCreate_CDF(VecTagger tagger)
556: {
557: VecTagger_CDF *cuml;
559: VecTaggerCreate_Simple(tagger);
560: PetscNew(&cuml);
561: PetscMemcpy(&cuml->smpl, tagger->data, sizeof(VecTagger_Simple));
562: PetscFree(tagger->data);
563: tagger->data = cuml;
564: tagger->ops->view = VecTaggerView_CDF;
565: tagger->ops->setfromoptions = VecTaggerSetFromOptions_CDF;
566: tagger->ops->computeboxes = VecTaggerComputeBoxes_CDF;
567: return 0;
568: }