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: }