Actual source code: cdf.c
1: #include <petsc/private/vecimpl.h>
2: #include "../src/vec/vec/utils/tagger/impls/simple.h"
4: const char *const VecTaggerCDFMethods[VECTAGGER_CDF_NUM_METHODS] = {"gather", "iterative"};
6: #if !defined(PETSC_USE_COMPLEX)
7: typedef VecTaggerBox VecTaggerBoxReal;
8: #else
9: typedef struct {
10: PetscReal min;
11: PetscReal max;
12: } VecTaggerBoxReal;
13: #endif
15: typedef struct {
16: VecTagger_Simple smpl;
17: PetscReal atol;
18: PetscReal rtol;
19: PetscInt maxit;
20: PetscInt numMoments;
21: VecTaggerCDFMethod method;
22: } VecTagger_CDF;
24: static PetscErrorCode VecTaggerComputeBox_CDF_SortedArray(const PetscReal *cArray, PetscInt m, const VecTaggerBoxReal *bxs, VecTaggerBoxReal *boxes)
25: {
26: PetscInt minInd, maxInd;
27: PetscReal minCDF, maxCDF;
29: PetscFunctionBegin;
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: PetscFunctionReturn(PETSC_SUCCESS);
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: PetscFunctionBegin;
50: PetscCall(VecGetLocalSize(vec, &n));
51: m = n / bs;
52: PetscCall(VecCreateSeq(PETSC_COMM_SELF, m, &vComp));
53: #if defined(PETSC_USE_COMPLEX)
54: PetscCall(PetscMalloc2(m, &cReal, m, &cImag));
55: #endif
56: for (i = 0; i < bs; i++) {
57: IS isStride;
58: VecScatter vScat;
59: PetscScalar *cArray;
61: PetscCall(ISCreateStride(PETSC_COMM_SELF, m, i, bs, &isStride));
62: PetscCall(VecScatterCreate(vec, isStride, vComp, NULL, &vScat));
63: PetscCall(VecScatterBegin(vScat, vec, vComp, INSERT_VALUES, SCATTER_FORWARD));
64: PetscCall(VecScatterEnd(vScat, vec, vComp, INSERT_VALUES, SCATTER_FORWARD));
65: PetscCall(VecScatterDestroy(&vScat));
66: PetscCall(ISDestroy(&isStride));
68: PetscCall(VecGetArray(vComp, &cArray));
69: #if !defined(PETSC_USE_COMPLEX)
70: PetscCall(PetscSortReal(m, cArray));
71: PetscCall(VecTaggerComputeBox_CDF_SortedArray(cArray, m, &smpl->box[i], &boxes[i]));
72: #else
73: {
74: PetscInt j;
75: VecTaggerBoxReal realBxs, imagBxs;
76: VecTaggerBoxReal realBoxes, imagBoxes;
78: for (j = 0; j < m; j++) {
79: cReal[j] = PetscRealPart(cArray[j]);
80: cImag[j] = PetscImaginaryPart(cArray[j]);
81: }
82: PetscCall(PetscSortReal(m, cReal));
83: PetscCall(PetscSortReal(m, cImag));
85: realBxs.min = PetscRealPart(smpl->box[i].min);
86: realBxs.max = PetscRealPart(smpl->box[i].max);
87: imagBxs.min = PetscImaginaryPart(smpl->box[i].min);
88: imagBxs.max = PetscImaginaryPart(smpl->box[i].max);
89: PetscCall(VecTaggerComputeBox_CDF_SortedArray(cReal, m, &realBxs, &realBoxes));
90: PetscCall(VecTaggerComputeBox_CDF_SortedArray(cImag, m, &imagBxs, &imagBoxes));
91: boxes[i].min = PetscCMPLX(realBoxes.min, imagBoxes.min);
92: boxes[i].max = PetscCMPLX(realBoxes.max, imagBoxes.max);
93: }
94: #endif
95: PetscCall(VecRestoreArray(vComp, &cArray));
96: }
97: #if defined(PETSC_USE_COMPLEX)
98: PetscCall(PetscFree2(cReal, cImag));
99: #endif
100: PetscCall(VecDestroy(&vComp));
101: PetscFunctionReturn(PETSC_SUCCESS);
102: }
104: static PetscErrorCode VecTaggerComputeBoxes_CDF_Gather(VecTagger tagger, Vec vec, PetscInt bs, VecTaggerBox *boxes)
105: {
106: Vec gVec = NULL;
107: VecScatter vScat;
108: PetscMPIInt rank, bs2;
110: PetscFunctionBegin;
111: PetscCall(VecScatterCreateToZero(vec, &vScat, &gVec));
112: PetscCall(VecScatterBegin(vScat, vec, gVec, INSERT_VALUES, SCATTER_FORWARD));
113: PetscCall(VecScatterEnd(vScat, vec, gVec, INSERT_VALUES, SCATTER_FORWARD));
114: PetscCall(VecScatterDestroy(&vScat));
115: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)vec), &rank));
116: if (rank == 0) PetscCall(VecTaggerComputeBoxes_CDF_Serial(tagger, gVec, bs, boxes));
117: PetscCall(PetscMPIIntCast(2 * bs, &bs2));
118: PetscCallMPI(MPI_Bcast(boxes, bs2, MPIU_SCALAR, 0, PetscObjectComm((PetscObject)vec)));
119: PetscCall(VecDestroy(&gVec));
120: PetscFunctionReturn(PETSC_SUCCESS);
121: }
123: typedef struct _n_CDFStats {
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++) B[i].moment[j] += A[i].moment[j];
139: }
140: }
142: static PetscErrorCode CDFUtilInverseEstimate(const CDFStats *stats, PetscReal cdfTarget, PetscReal *absEst)
143: {
144: PetscReal min, max;
146: PetscFunctionBegin;
147: min = stats->min;
148: max = stats->max;
149: *absEst = min + cdfTarget * (max - min);
150: PetscFunctionReturn(PETSC_SUCCESS);
151: }
153: static PetscErrorCode VecTaggerComputeBox_CDF_SortedArray_Iterative(VecTagger tagger, MPI_Datatype statType, MPI_Op statReduce, const PetscReal *cArray, PetscInt m, const VecTaggerBoxReal *cdfBox, VecTaggerBoxReal *absBox)
154: {
155: MPI_Comm comm;
156: VecTagger_CDF *cdf;
157: PetscInt maxit, i, j, k, l, M;
158: PetscInt bounds[2][2];
159: PetscInt offsets[2];
160: PetscReal intervalLen = cdfBox->max - cdfBox->min;
161: PetscReal rtol, atol;
163: PetscFunctionBegin;
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;
173: bounds[0][1] = m;
174: bounds[1][0] = 0;
175: bounds[1][1] = m;
176: PetscCall(VecTaggerComputeBox_CDF_SortedArray(cArray, m, cdfBox, absBox)); /* compute a local estimate of the interval */
177: {
178: CDFStats stats[3];
180: for (i = 0; i < 2; i++) { /* compute statistics of those local estimates */
181: PetscReal val = i ? absBox->max : absBox->min;
183: stats[i].min = m ? val : PETSC_MAX_REAL;
184: stats[i].max = m ? val : PETSC_MIN_REAL;
185: stats[i].moment[0] = m;
186: stats[i].moment[1] = m * val;
187: stats[i].moment[2] = m * val * val;
188: }
189: stats[2].min = PETSC_MAX_REAL;
190: stats[2].max = PETSC_MAX_REAL;
191: for (i = 0; i < 3; i++) stats[2].moment[i] = 0.;
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: PetscCallMPI(MPIU_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++) PetscCall(CDFUtilInverseEstimate(&stats[i], i ? cdfBox->max : cdfBox->min, i ? &absBox->max : &absBox->min));
206: }
207: /* refine the estimates by computing how close they come to the desired box and refining */
208: for (k = 0; k < maxit; k++) {
209: PetscReal maxDiff = 0.;
211: CDFStats stats[2][2];
212: PetscInt newBounds[2][2][2];
213: for (i = 0; i < 2; i++) {
214: for (j = 0; j < 2; j++) {
215: stats[i][j].min = PETSC_MAX_REAL;
216: stats[i][j].max = PETSC_MIN_REAL;
217: for (l = 0; l < 3; l++) stats[i][j].moment[l] = 0.;
218: newBounds[i][j][0] = PetscMax(bounds[i][0], bounds[i][1]);
219: newBounds[i][j][1] = PetscMin(bounds[i][0], bounds[i][1]);
220: }
221: }
222: for (i = 0; i < 2; i++) {
223: for (j = 0; j < bounds[i][1] - bounds[i][0]; j++) {
224: PetscInt thisInd = bounds[i][0] + j;
225: PetscReal val = cArray[thisInd];
226: PetscInt section;
227: if (!i) {
228: section = (val < absBox->min) ? 0 : 1;
229: } else {
230: section = (val <= absBox->max) ? 0 : 1;
231: }
232: stats[i][section].min = PetscMin(stats[i][section].min, val);
233: stats[i][section].max = PetscMax(stats[i][section].max, val);
234: stats[i][section].moment[0]++;
235: stats[i][section].moment[1] += val;
236: stats[i][section].moment[2] += val * val;
237: newBounds[i][section][0] = PetscMin(newBounds[i][section][0], thisInd);
238: newBounds[i][section][1] = PetscMax(newBounds[i][section][0], thisInd + 1);
239: }
240: }
241: PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, stats, 4, statType, statReduce, comm));
242: for (i = 0; i < 2; i++) {
243: PetscInt totalLessThan = offsets[i] + stats[i][0].moment[0];
244: PetscReal cdfOfAbs = (PetscReal)totalLessThan / (PetscReal)M;
245: PetscReal diff;
246: PetscInt section;
248: if (cdfOfAbs == (i ? cdfBox->max : cdfBox->min)) {
249: offsets[i] = totalLessThan;
250: bounds[i][0] = bounds[i][1] = 0;
251: continue;
252: }
253: if (cdfOfAbs > (i ? cdfBox->max : cdfBox->min)) { /* the correct absolute value lies in the lower section */
254: section = 0;
255: } else {
256: section = 1;
257: offsets[i] = totalLessThan;
258: }
259: for (j = 0; j < 2; j++) bounds[i][j] = newBounds[i][section][j];
260: PetscCall(CDFUtilInverseEstimate(&stats[i][section], ((i ? cdfBox->max : cdfBox->min) - ((PetscReal)offsets[i] / (PetscReal)M)) / stats[i][section].moment[0], i ? &absBox->max : &absBox->min));
261: diff = PetscAbs(cdfOfAbs - (i ? cdfBox->max : cdfBox->min));
262: maxDiff = PetscMax(maxDiff, diff);
263: }
264: if (!maxDiff) PetscFunctionReturn(PETSC_SUCCESS);
265: if ((atol || rtol) && ((!atol) || (maxDiff <= atol)) && ((!rtol) || (maxDiff <= rtol * intervalLen))) break;
266: }
267: PetscFunctionReturn(PETSC_SUCCESS);
268: }
270: static PetscErrorCode VecTaggerComputeBoxes_CDF_Iterative(VecTagger tagger, Vec vec, PetscInt bs, VecTaggerBox *boxes)
271: {
272: VecTagger_CDF *cdf = (VecTagger_CDF *)tagger->data;
273: VecTagger_Simple *smpl = &cdf->smpl;
274: Vec vComp;
275: PetscInt i, N, M, n, m, rstart;
276: #if defined(PETSC_USE_COMPLEX)
277: PetscReal *cReal, *cImag;
278: #endif
279: MPI_Comm comm;
280: MPI_Datatype statType;
281: MPI_Op statReduce;
283: PetscFunctionBegin;
284: comm = PetscObjectComm((PetscObject)vec);
285: PetscCall(VecGetSize(vec, &N));
286: PetscCall(VecGetLocalSize(vec, &n));
287: M = N / bs;
288: m = n / bs;
289: PetscCall(VecCreateMPI(comm, m, M, &vComp));
290: PetscCall(VecSetUp(vComp));
291: PetscCall(VecGetOwnershipRange(vComp, &rstart, NULL));
292: #if defined(PETSC_USE_COMPLEX)
293: PetscCall(PetscMalloc2(m, &cReal, m, &cImag));
294: #endif
295: PetscCallMPI(MPI_Type_contiguous(5, MPIU_REAL, &statType));
296: PetscCallMPI(MPI_Type_commit(&statType));
297: PetscCallMPI(MPI_Op_create(VecTaggerCDFStatsReduce, 1, &statReduce));
298: for (i = 0; i < bs; i++) {
299: IS isStride;
300: VecScatter vScat;
301: PetscScalar *cArray;
303: PetscCall(ISCreateStride(comm, m, bs * rstart + i, bs, &isStride));
304: PetscCall(VecScatterCreate(vec, isStride, vComp, NULL, &vScat));
305: PetscCall(VecScatterBegin(vScat, vec, vComp, INSERT_VALUES, SCATTER_FORWARD));
306: PetscCall(VecScatterEnd(vScat, vec, vComp, INSERT_VALUES, SCATTER_FORWARD));
307: PetscCall(VecScatterDestroy(&vScat));
308: PetscCall(ISDestroy(&isStride));
310: PetscCall(VecGetArray(vComp, &cArray));
311: #if !defined(PETSC_USE_COMPLEX)
312: PetscCall(PetscSortReal(m, cArray));
313: PetscCall(VecTaggerComputeBox_CDF_SortedArray_Iterative(tagger, statType, statReduce, cArray, m, &smpl->box[i], &boxes[i]));
314: #else
315: {
316: PetscInt j;
317: VecTaggerBoxReal realBxs, imagBxs;
318: VecTaggerBoxReal realBoxes, imagBoxes;
320: for (j = 0; j < m; j++) {
321: cReal[j] = PetscRealPart(cArray[j]);
322: cImag[j] = PetscImaginaryPart(cArray[j]);
323: }
324: PetscCall(PetscSortReal(m, cReal));
325: PetscCall(PetscSortReal(m, cImag));
327: realBxs.min = PetscRealPart(smpl->box[i].min);
328: realBxs.max = PetscRealPart(smpl->box[i].max);
329: imagBxs.min = PetscImaginaryPart(smpl->box[i].min);
330: imagBxs.max = PetscImaginaryPart(smpl->box[i].max);
331: PetscCall(VecTaggerComputeBox_CDF_SortedArray_Iterative(tagger, statType, statReduce, cReal, m, &realBxs, &realBoxes));
332: PetscCall(VecTaggerComputeBox_CDF_SortedArray_Iterative(tagger, statType, statReduce, cImag, m, &imagBxs, &imagBoxes));
333: boxes[i].min = PetscCMPLX(realBoxes.min, imagBoxes.min);
334: boxes[i].max = PetscCMPLX(realBoxes.max, imagBoxes.max);
335: }
336: #endif
337: PetscCall(VecRestoreArray(vComp, &cArray));
338: }
339: PetscCallMPI(MPI_Op_free(&statReduce));
340: PetscCallMPI(MPI_Type_free(&statType));
341: #if defined(PETSC_USE_COMPLEX)
342: PetscCall(PetscFree2(cReal, cImag));
343: #endif
344: PetscCall(VecDestroy(&vComp));
345: PetscFunctionReturn(PETSC_SUCCESS);
346: }
348: static PetscErrorCode VecTaggerComputeBoxes_CDF(VecTagger tagger, Vec vec, PetscInt *numBoxes, VecTaggerBox **boxes, PetscBool *listed)
349: {
350: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
351: PetscMPIInt size;
352: PetscInt bs;
353: VecTaggerBox *bxs;
355: PetscFunctionBegin;
356: PetscCall(VecTaggerGetBlockSize(tagger, &bs));
357: *numBoxes = 1;
358: PetscCall(PetscMalloc1(bs, &bxs));
359: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)tagger), &size));
360: if (size == 1) {
361: PetscCall(VecTaggerComputeBoxes_CDF_Serial(tagger, vec, bs, bxs));
362: *boxes = bxs;
363: PetscFunctionReturn(PETSC_SUCCESS);
364: }
365: switch (cuml->method) {
366: case VECTAGGER_CDF_GATHER:
367: PetscCall(VecTaggerComputeBoxes_CDF_Gather(tagger, vec, bs, bxs));
368: break;
369: case VECTAGGER_CDF_ITERATIVE:
370: PetscCall(VecTaggerComputeBoxes_CDF_Iterative(tagger, vec, bs, bxs));
371: break;
372: default:
373: SETERRQ(PetscObjectComm((PetscObject)tagger), PETSC_ERR_SUP, "Unknown CDF calculation/estimation method.");
374: }
375: *boxes = bxs;
376: if (listed) *listed = PETSC_TRUE;
377: PetscFunctionReturn(PETSC_SUCCESS);
378: }
380: static PetscErrorCode VecTaggerView_CDF(VecTagger tagger, PetscViewer viewer)
381: {
382: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
383: PetscBool iascii;
384: PetscMPIInt size;
386: PetscFunctionBegin;
387: PetscCall(VecTaggerView_Simple(tagger, viewer));
388: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)tagger), &size));
389: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
390: if (size > 1 && iascii) {
391: PetscCall(PetscViewerASCIIPrintf(viewer, "CDF computation method: %s\n", VecTaggerCDFMethods[cuml->method]));
392: if (cuml->method == VECTAGGER_CDF_ITERATIVE) {
393: PetscCall(PetscViewerASCIIPushTab(viewer));
394: PetscCall(PetscViewerASCIIPrintf(viewer, "max its: %" PetscInt_FMT ", abs tol: %g, rel tol %g\n", cuml->maxit, (double)cuml->atol, (double)cuml->rtol));
395: PetscCall(PetscViewerASCIIPopTab(viewer));
396: }
397: }
398: PetscFunctionReturn(PETSC_SUCCESS);
399: }
401: static PetscErrorCode VecTaggerSetFromOptions_CDF(VecTagger tagger, PetscOptionItems PetscOptionsObject)
402: {
403: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
404: PetscInt method;
405: PetscBool set;
407: PetscFunctionBegin;
408: PetscCall(VecTaggerSetFromOptions_Simple(tagger, PetscOptionsObject));
409: PetscOptionsHeadBegin(PetscOptionsObject, "VecTagger options for CDF boxes");
410: PetscCall(PetscOptionsEList("-vec_tagger_cdf_method", "Method for computing absolute boxes from CDF boxes", "VecTaggerCDFSetMethod()", VecTaggerCDFMethods, VECTAGGER_CDF_NUM_METHODS, VecTaggerCDFMethods[cuml->method], &method, &set));
411: if (set) cuml->method = (VecTaggerCDFMethod)method;
412: PetscCall(PetscOptionsInt("-vec_tagger_cdf_max_it", "Maximum iterations for iterative computation of absolute boxes from CDF boxes", "VecTaggerCDFIterativeSetTolerances()", cuml->maxit, &cuml->maxit, NULL));
413: PetscCall(PetscOptionsReal("-vec_tagger_cdf_rtol", "Maximum relative tolerance for iterative computation of absolute boxes from CDF boxes", "VecTaggerCDFIterativeSetTolerances()", cuml->rtol, &cuml->rtol, NULL));
414: PetscCall(PetscOptionsReal("-vec_tagger_cdf_atol", "Maximum absolute tolerance for iterative computation of absolute boxes from CDF boxes", "VecTaggerCDFIterativeSetTolerances()", cuml->atol, &cuml->atol, NULL));
415: PetscOptionsHeadEnd();
416: PetscFunctionReturn(PETSC_SUCCESS);
417: }
419: /*@
420: VecTaggerCDFSetMethod - Set the method used to compute absolute boxes from CDF boxes
422: Logically Collective
424: Input Parameters:
425: + tagger - the `VecTagger` context
426: - method - the method
428: Level: advanced
430: .seealso: `Vec`, `VecTagger`, `VecTaggerCDFMethod`
431: @*/
432: PetscErrorCode VecTaggerCDFSetMethod(VecTagger tagger, VecTaggerCDFMethod method)
433: {
434: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
436: PetscFunctionBegin;
439: cuml->method = method;
440: PetscFunctionReturn(PETSC_SUCCESS);
441: }
443: /*@
444: VecTaggerCDFGetMethod - Get the method used to compute absolute boxes from CDF boxes
446: Logically Collective
448: Input Parameter:
449: . tagger - the `VecTagger` context
451: Output Parameter:
452: . method - the method
454: Level: advanced
456: .seealso: `Vec`, `VecTagger`, `VecTaggerCDFMethod`
457: @*/
458: PetscErrorCode VecTaggerCDFGetMethod(VecTagger tagger, VecTaggerCDFMethod *method)
459: {
460: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
462: PetscFunctionBegin;
464: PetscAssertPointer(method, 2);
465: *method = cuml->method;
466: PetscFunctionReturn(PETSC_SUCCESS);
467: }
469: /*@C
470: VecTaggerCDFIterativeSetTolerances - Set the tolerances for iterative computation of absolute boxes from CDF boxes.
472: Logically Collective
474: Input Parameters:
475: + tagger - the `VecTagger` context
476: . 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,
477: and standard deviation of the box endpoints.
478: . rtol - the acceptable relative tolerance in the absolute values from the initial guess
479: - atol - the acceptable absolute tolerance in the absolute values from the initial guess
481: Level: advanced
483: .seealso: `VecTagger`, `VecTaggerCDFSetMethod()`
484: @*/
485: PetscErrorCode VecTaggerCDFIterativeSetTolerances(VecTagger tagger, PetscInt maxit, PetscReal rtol, PetscReal atol)
486: {
487: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
489: PetscFunctionBegin;
494: cuml->maxit = maxit;
495: cuml->rtol = rtol;
496: cuml->atol = atol;
497: PetscFunctionReturn(PETSC_SUCCESS);
498: }
500: /*@
501: VecTaggerCDFIterativeGetTolerances - Get the tolerances for iterative computation of absolute boxes from CDF boxes.
503: Logically Collective
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,
510: mean, and standard deviation of the box endpoints.
511: . rtol - the acceptable relative tolerance in the absolute values from the initial guess
512: - atol - the acceptable absolute tolerance in the absolute values from the initial guess
514: Level: advanced
516: .seealso: `VecTagger`, `VecTaggerCDFSetMethod()`
517: @*/
518: PetscErrorCode VecTaggerCDFIterativeGetTolerances(VecTagger tagger, PetscInt *maxit, PetscReal *rtol, PetscReal *atol)
519: {
520: VecTagger_CDF *cuml = (VecTagger_CDF *)tagger->data;
522: PetscFunctionBegin;
524: if (maxit) *maxit = cuml->maxit;
525: if (rtol) *rtol = cuml->rtol;
526: if (atol) *atol = cuml->atol;
527: PetscFunctionReturn(PETSC_SUCCESS);
528: }
530: /*@C
531: 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.
533: Logically Collective
535: Input Parameters:
536: + tagger - the `VecTagger` context
537: - box - a blocksize array of `VecTaggerBox` boxes
539: Level: advanced
541: .seealso: `VecTagger`, `VecTaggerCDFGetBox()`, `VecTaggerBox`
542: @*/
543: PetscErrorCode VecTaggerCDFSetBox(VecTagger tagger, VecTaggerBox box[])
544: {
545: PetscFunctionBegin;
546: PetscCall(VecTaggerSetBox_Simple(tagger, box));
547: PetscFunctionReturn(PETSC_SUCCESS);
548: }
550: /*@C
551: VecTaggerCDFGetBox - Get the cumulative box (multi-dimensional box) defining the values to be tagged by the tagger, where cumulative boxes
552: are subsets of [0,1], where 0 indicates the smallest value present in the vector and 1 indicates the largest.
554: Logically Collective
556: Input Parameter:
557: . tagger - the `VecTagger` context
559: Output Parameter:
560: . box - a blocksize array of `VecTaggerBox` boxes
562: Level: advanced
564: .seealso: `VecTagger`, `VecTaggerCDFSetBox()`, `VecTaggerBox`
565: @*/
566: PetscErrorCode VecTaggerCDFGetBox(VecTagger tagger, const VecTaggerBox *box[])
567: {
568: PetscFunctionBegin;
569: PetscCall(VecTaggerGetBox_Simple(tagger, box));
570: PetscFunctionReturn(PETSC_SUCCESS);
571: }
573: PETSC_INTERN PetscErrorCode VecTaggerCreate_CDF(VecTagger tagger)
574: {
575: VecTagger_CDF *cuml;
577: PetscFunctionBegin;
578: PetscCall(VecTaggerCreate_Simple(tagger));
579: PetscCall(PetscNew(&cuml));
580: PetscCall(PetscMemcpy(&cuml->smpl, tagger->data, sizeof(VecTagger_Simple)));
581: PetscCall(PetscFree(tagger->data));
582: tagger->data = cuml;
583: tagger->ops->view = VecTaggerView_CDF;
584: tagger->ops->setfromoptions = VecTaggerSetFromOptions_CDF;
585: tagger->ops->computeboxes = VecTaggerComputeBoxes_CDF;
586: PetscFunctionReturn(PETSC_SUCCESS);
587: }