xref: /petsc/src/sys/classes/draw/utils/axisc.c (revision 3f02e49b19195914bf17f317a25cb39636853415)
1 #include <petsc/private/drawimpl.h> /*I   "petscdraw.h"  I*/
2 
3 #define PETSC_DRAW_AXIS_MAX_SEGMENTS 20
4 PetscClassId PETSC_DRAWAXIS_CLASSID = 0;
5 
6 /*@
7   PetscDrawAxisCreate - Generate the axis data structure.
8 
9   Collective
10 
11   Input Parameter:
12 . draw - `PetscDraw` object where axis to be made
13 
14   Output Parameter:
15 . axis - the axis datastructure
16 
17   Note:
18   The MPI communicator that owns the underlying draw object owns the `PetscDrawAxis` object, but calls to set `PetscDrawAxis` options are
19   ignored by all processes except the first MPI rank in the communicator
20 
21   Level: advanced
22 
23 .seealso: `PetscDrawLGCreate()`, `PetscDrawLG`, `PetscDrawSPCreate()`, `PetscDrawSP`, `PetscDrawHGCreate()`, `PetscDrawHG`, `PetscDrawBarCreate()`, `PetscDrawBar`, `PetscDrawLGGetAxis()`, `PetscDrawSPGetAxis()`,
24           `PetscDrawHGGetAxis()`, `PetscDrawBarGetAxis()`, `PetscDrawAxis`, `PetscDrawAxisDestroy()`, `PetscDrawAxisSetColors()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetHoldLimits()`,
25           `PetscDrawAxisDraw()`
26 @*/
27 PetscErrorCode PetscDrawAxisCreate(PetscDraw draw, PetscDrawAxis *axis)
28 {
29   PetscDrawAxis ad;
30 
31   PetscFunctionBegin;
32   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
33   PetscAssertPointer(axis, 2);
34 
35   PetscCall(PetscHeaderCreate(ad, PETSC_DRAWAXIS_CLASSID, "DrawAxis", "Draw Axis", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawAxisDestroy, NULL));
36   PetscCall(PetscObjectReference((PetscObject)draw));
37   ad->win       = draw;
38   ad->xticks    = PetscADefTicks;
39   ad->yticks    = PetscADefTicks;
40   ad->xlabelstr = PetscADefLabel;
41   ad->ylabelstr = PetscADefLabel;
42   ad->ac        = PETSC_DRAW_BLACK;
43   ad->tc        = PETSC_DRAW_BLACK;
44   ad->cc        = PETSC_DRAW_BLACK;
45   ad->xlabel    = NULL;
46   ad->ylabel    = NULL;
47   ad->toplabel  = NULL;
48   *axis         = ad;
49   PetscFunctionReturn(PETSC_SUCCESS);
50 }
51 
52 /*@
53   PetscDrawAxisDestroy - Frees the space used by an axis structure.
54 
55   Collective
56 
57   Input Parameter:
58 . axis - the axis context
59 
60   Level: advanced
61 
62 .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`
63 @*/
64 PetscErrorCode PetscDrawAxisDestroy(PetscDrawAxis *axis)
65 {
66   PetscFunctionBegin;
67   if (!*axis) PetscFunctionReturn(PETSC_SUCCESS);
68   PetscValidHeaderSpecific(*axis, PETSC_DRAWAXIS_CLASSID, 1);
69   if (--((PetscObject)*axis)->refct > 0) {
70     *axis = NULL;
71     PetscFunctionReturn(PETSC_SUCCESS);
72   }
73 
74   PetscCall(PetscFree((*axis)->toplabel));
75   PetscCall(PetscFree((*axis)->xlabel));
76   PetscCall(PetscFree((*axis)->ylabel));
77   PetscCall(PetscDrawDestroy(&(*axis)->win));
78   PetscCall(PetscHeaderDestroy(axis));
79   PetscFunctionReturn(PETSC_SUCCESS);
80 }
81 
82 /*@
83   PetscDrawAxisSetColors -  Sets the colors to be used for the axis,
84   tickmarks, and text.
85 
86   Logically Collective
87 
88   Input Parameters:
89 + axis - the axis
90 . ac   - the color of the axis lines
91 . tc   - the color of the tick marks
92 - cc   - the color of the text strings
93 
94   Level: advanced
95 
96 .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisDraw()`, `PetscDrawAxisSetLimits()`
97 @*/
98 PetscErrorCode PetscDrawAxisSetColors(PetscDrawAxis axis, int ac, int tc, int cc)
99 {
100   PetscFunctionBegin;
101   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
102   PetscValidLogicalCollectiveInt(axis, ac, 2);
103   PetscValidLogicalCollectiveInt(axis, tc, 3);
104   PetscValidLogicalCollectiveInt(axis, cc, 4);
105   axis->ac = ac;
106   axis->tc = tc;
107   axis->cc = cc;
108   PetscFunctionReturn(PETSC_SUCCESS);
109 }
110 
111 /*@
112   PetscDrawAxisSetLabels -  Sets the x and y axis labels.
113 
114   Logically Collective
115 
116   Input Parameters:
117 + axis   - the axis
118 . top    - the label at the top of the image
119 . xlabel - the x axis label
120 - ylabel - the y axis label
121 
122   Level: advanced
123 
124   Notes:
125   Must be called before `PetscDrawAxisDraw()` or `PetscDrawLGDraw()`
126 
127   There should be no newlines in the arguments
128 
129 .seealso: `PetscDraw`, `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetColors()`, `PetscDrawAxisDraw()`, `PetscDrawAxisSetLimits()`
130 @*/
131 PetscErrorCode PetscDrawAxisSetLabels(PetscDrawAxis axis, const char top[], const char xlabel[], const char ylabel[])
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
135   PetscCall(PetscFree(axis->xlabel));
136   PetscCall(PetscFree(axis->ylabel));
137   PetscCall(PetscFree(axis->toplabel));
138   PetscCall(PetscStrallocpy(xlabel, &axis->xlabel));
139   PetscCall(PetscStrallocpy(ylabel, &axis->ylabel));
140   PetscCall(PetscStrallocpy(top, &axis->toplabel));
141   PetscFunctionReturn(PETSC_SUCCESS);
142 }
143 
144 /*@
145   PetscDrawAxisSetLimits -  Sets the limits (in user coords) of the axis
146 
147   Logically Collective
148 
149   Input Parameters:
150 + axis - the axis
151 . xmin - the lower x limit
152 . xmax - the upper x limit
153 . ymin - the lower y limit
154 - ymax - the upper y limit
155 
156   Options Database Key:
157 . -drawaxis_hold - hold the initial set of axis limits for future plotting
158 
159   Level: advanced
160 
161 .seealso: `PetscDrawAxisSetHoldLimits()`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
162 @*/
163 PetscErrorCode PetscDrawAxisSetLimits(PetscDrawAxis axis, PetscReal xmin, PetscReal xmax, PetscReal ymin, PetscReal ymax)
164 {
165   PetscFunctionBegin;
166   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
167   if (axis->hold) PetscFunctionReturn(PETSC_SUCCESS);
168   axis->xlow  = xmin;
169   axis->xhigh = xmax;
170   axis->ylow  = ymin;
171   axis->yhigh = ymax;
172   PetscCall(PetscOptionsHasName(((PetscObject)axis)->options, ((PetscObject)axis)->prefix, "-drawaxis_hold", &axis->hold));
173   PetscFunctionReturn(PETSC_SUCCESS);
174 }
175 
176 /*@
177   PetscDrawAxisGetLimits -  Gets the limits (in user coords) of the axis
178 
179   Not Collective
180 
181   Input Parameters:
182 + axis - the axis
183 . xmin - the lower x limit
184 . xmax - the upper x limit
185 . ymin - the lower y limit
186 - ymax - the upper y limit
187 
188   Level: advanced
189 
190 .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisSetHoldLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
191 @*/
192 PetscErrorCode PetscDrawAxisGetLimits(PetscDrawAxis axis, PetscReal *xmin, PetscReal *xmax, PetscReal *ymin, PetscReal *ymax)
193 {
194   PetscFunctionBegin;
195   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
196   if (xmin) *xmin = axis->xlow;
197   if (xmax) *xmax = axis->xhigh;
198   if (ymin) *ymin = axis->ylow;
199   if (ymax) *ymax = axis->yhigh;
200   PetscFunctionReturn(PETSC_SUCCESS);
201 }
202 
203 /*@
204   PetscDrawAxisSetHoldLimits -  Causes an axis to keep the same limits until this is called
205   again
206 
207   Logically Collective
208 
209   Input Parameters:
210 + axis - the axis
211 - hold - `PETSC_TRUE` - hold current limits, `PETSC_FALSE` allow limits to be changed
212 
213   Level: advanced
214 
215   Note:
216   Once this has been called with `PETSC_TRUE` the limits will not change if you call
217   `PetscDrawAxisSetLimits()` until you call this with `PETSC_FALSE`
218 
219 .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
220 @*/
221 PetscErrorCode PetscDrawAxisSetHoldLimits(PetscDrawAxis axis, PetscBool hold)
222 {
223   PetscFunctionBegin;
224   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
225   PetscValidLogicalCollectiveBool(axis, hold, 2);
226   axis->hold = hold;
227   PetscFunctionReturn(PETSC_SUCCESS);
228 }
229 
230 /*@
231   PetscDrawAxisDraw - draws an axis.
232 
233   Collective
234 
235   Input Parameter:
236 . axis - `PetscDrawAxis` structure
237 
238   Level: advanced
239 
240   Note:
241   This draws the actual axis.  The limits etc have already been set.
242   By picking special routines for the ticks and labels, special
243   effects may be generated.  These routines are part of the Axis
244   structure (axis).
245 
246 .seealso: `PetscDrawAxisCreate()`, `PetscDrawAxis`, `PetscDrawAxisGetLimits()`, `PetscDrawAxisSetLimits()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetColors()`
247 @*/
248 PetscErrorCode PetscDrawAxisDraw(PetscDrawAxis axis)
249 {
250   int         i, ntick, numx, numy, ac, tc, cc;
251   PetscMPIInt rank;
252   size_t      len, ytlen = 0;
253   PetscReal   coors[4] = {0, 0, 0, 0}, tickloc[PETSC_DRAW_AXIS_MAX_SEGMENTS], sep, tw, th;
254   PetscReal   xl, xr, yl, yr, dxl = 0, dyl = 0, dxr = 0, dyr = 0;
255   char       *p;
256   PetscDraw   draw;
257   PetscBool   isnull;
258 
259   PetscFunctionBegin;
260   PetscValidHeaderSpecific(axis, PETSC_DRAWAXIS_CLASSID, 1);
261   PetscCall(PetscDrawIsNull(axis->win, &isnull));
262   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
263   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)axis), &rank));
264 
265   draw = axis->win;
266 
267   ac = axis->ac;
268   tc = axis->tc;
269   cc = axis->cc;
270   if (axis->xlow == axis->xhigh) {
271     axis->xlow -= .5;
272     axis->xhigh += .5;
273   }
274   if (axis->ylow == axis->yhigh) {
275     axis->ylow -= .5;
276     axis->yhigh += .5;
277   }
278 
279   PetscDrawCollectiveBegin(draw);
280   if (rank) goto finally;
281 
282   /* get canonical string size */
283   PetscCall(PetscDrawSetCoordinates(draw, 0, 0, 1, 1));
284   PetscCall(PetscDrawStringGetSize(draw, &tw, &th));
285   /* lower spacing */
286   if (axis->xlabelstr) dyl += 1.5 * th;
287   if (axis->xlabel) dyl += 1.5 * th;
288   /* left spacing */
289   if (axis->ylabelstr) dxl += 7.5 * tw;
290   if (axis->ylabel) dxl += 2.0 * tw;
291   /* right and top spacing */
292   if (axis->xlabelstr) dxr = 2.5 * tw;
293   if (axis->ylabelstr) dyr = 0.5 * th;
294   if (axis->toplabel) dyr = 1.5 * th;
295   /* extra spacing */
296   dxl += 0.7 * tw;
297   dxr += 0.5 * tw;
298   dyl += 0.2 * th;
299   dyr += 0.2 * th;
300   /* determine coordinates */
301   xl = (dxl * axis->xhigh + dxr * axis->xlow - axis->xlow) / (dxl + dxr - 1);
302   xr = (dxl * axis->xhigh + dxr * axis->xlow - axis->xhigh) / (dxl + dxr - 1);
303   yl = (dyl * axis->yhigh + dyr * axis->ylow - axis->ylow) / (dyl + dyr - 1);
304   yr = (dyl * axis->yhigh + dyr * axis->ylow - axis->yhigh) / (dyl + dyr - 1);
305   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
306   PetscCall(PetscDrawStringGetSize(draw, &tw, &th));
307 
308   /* PetscDraw the axis lines */
309   PetscCall(PetscDrawLine(draw, axis->xlow, axis->ylow, axis->xhigh, axis->ylow, ac));
310   PetscCall(PetscDrawLine(draw, axis->xlow, axis->ylow, axis->xlow, axis->yhigh, ac));
311   PetscCall(PetscDrawLine(draw, axis->xlow, axis->yhigh, axis->xhigh, axis->yhigh, ac));
312   PetscCall(PetscDrawLine(draw, axis->xhigh, axis->ylow, axis->xhigh, axis->yhigh, ac));
313 
314   /* PetscDraw the top label */
315   if (axis->toplabel) {
316     PetscReal x = (axis->xlow + axis->xhigh) / 2, y = axis->yhigh + 0.5 * th;
317 
318     PetscCall(PetscDrawStringCentered(draw, x, y, cc, axis->toplabel));
319   }
320 
321   /* PetscDraw the X ticks and labels */
322   if (axis->xticks) {
323     numx = (int)(.15 * (axis->xhigh - axis->xlow) / tw);
324     numx = PetscClipInterval(numx, 2, 6);
325     PetscCall((*axis->xticks)(axis->xlow, axis->xhigh, numx, &ntick, tickloc, PETSC_DRAW_AXIS_MAX_SEGMENTS));
326     /* PetscDraw in tick marks */
327     for (i = 0; i < ntick; i++) {
328       PetscCall(PetscDrawLine(draw, tickloc[i], axis->ylow, tickloc[i], axis->ylow + .5 * th, tc));
329       PetscCall(PetscDrawLine(draw, tickloc[i], axis->yhigh, tickloc[i], axis->yhigh - .5 * th, tc));
330     }
331     /* label ticks */
332     if (axis->xlabelstr) {
333       for (i = 0; i < ntick; i++) {
334         if (i < ntick - 1) sep = tickloc[i + 1] - tickloc[i];
335         else if (i > 0) sep = tickloc[i] - tickloc[i - 1];
336         else sep = 0.0;
337         PetscCall((*axis->xlabelstr)(tickloc[i], sep, &p));
338         PetscCall(PetscDrawStringCentered(draw, tickloc[i], axis->ylow - 1.5 * th, cc, p));
339       }
340     }
341   }
342   if (axis->xlabel) {
343     PetscReal x = (axis->xlow + axis->xhigh) / 2, y = axis->ylow - 1.5 * th;
344 
345     if (axis->xlabelstr) y -= 1.5 * th;
346     PetscCall(PetscDrawStringCentered(draw, x, y, cc, axis->xlabel));
347   }
348 
349   /* PetscDraw the Y ticks and labels */
350   if (axis->yticks) {
351     numy = (int)(.50 * (axis->yhigh - axis->ylow) / th);
352     numy = PetscClipInterval(numy, 2, 6);
353     PetscCall((*axis->yticks)(axis->ylow, axis->yhigh, numy, &ntick, tickloc, PETSC_DRAW_AXIS_MAX_SEGMENTS));
354     /* PetscDraw in tick marks */
355     for (i = 0; i < ntick; i++) {
356       PetscCall(PetscDrawLine(draw, axis->xlow, tickloc[i], axis->xlow + .5 * tw, tickloc[i], tc));
357       PetscCall(PetscDrawLine(draw, axis->xhigh, tickloc[i], axis->xhigh - .5 * tw, tickloc[i], tc));
358     }
359     /* label ticks */
360     if (axis->ylabelstr) {
361       for (i = 0; i < ntick; i++) {
362         if (i < ntick - 1) sep = tickloc[i + 1] - tickloc[i];
363         else if (i > 0) sep = tickloc[i] - tickloc[i - 1];
364         else sep = 0.0;
365         PetscCall((*axis->ylabelstr)(tickloc[i], sep, &p));
366         PetscCall(PetscStrlen(p, &len));
367         ytlen = PetscMax(ytlen, len);
368         PetscCall(PetscDrawString(draw, axis->xlow - ((PetscReal)len + .5) * tw, tickloc[i] - .5 * th, cc, p));
369       }
370     }
371   }
372   if (axis->ylabel) {
373     PetscReal x = axis->xlow - 2.0 * tw, y = (axis->ylow + axis->yhigh) / 2;
374 
375     if (axis->ylabelstr) x -= ((PetscReal)ytlen + .5) * tw;
376     PetscCall(PetscStrlen(axis->ylabel, &len));
377     PetscCall(PetscDrawStringVertical(draw, x, y + ((PetscReal)len) * th / 2, cc, axis->ylabel));
378   }
379 
380   PetscCall(PetscDrawGetCoordinates(draw, &coors[0], &coors[1], &coors[2], &coors[3]));
381 finally:
382   PetscDrawCollectiveEnd(draw);
383   PetscCallMPI(MPI_Bcast(coors, 4, MPIU_REAL, 0, PetscObjectComm((PetscObject)draw)));
384   PetscCall(PetscDrawSetCoordinates(draw, coors[0], coors[1], coors[2], coors[3]));
385   PetscFunctionReturn(PETSC_SUCCESS);
386 }
387 
388 /*
389     Removes all zeros but one from .0000
390 */
391 PetscErrorCode PetscStripe0(char *buf)
392 {
393   size_t    n;
394   PetscBool flg;
395   char     *str = NULL;
396 
397   PetscFunctionBegin;
398   PetscCall(PetscStrlen(buf, &n));
399   PetscCall(PetscStrendswith(buf, "e00", &flg));
400   if (flg) buf[n - 3] = 0;
401   PetscCall(PetscStrstr(buf, "e0", &str));
402   if (str) {
403     buf[n - 2] = buf[n - 1];
404     buf[n - 1] = 0;
405   }
406   PetscCall(PetscStrstr(buf, "e-0", &str));
407   if (str) {
408     buf[n - 2] = buf[n - 1];
409     buf[n - 1] = 0;
410   }
411   PetscFunctionReturn(PETSC_SUCCESS);
412 }
413 
414 /*
415     Removes all zeros but one from .0000
416 */
417 PetscErrorCode PetscStripAllZeros(char *buf)
418 {
419   size_t i, n;
420 
421   PetscFunctionBegin;
422   PetscCall(PetscStrlen(buf, &n));
423   if (buf[0] != '.') PetscFunctionReturn(PETSC_SUCCESS);
424   for (i = 1; i < n; i++) {
425     if (buf[i] != '0') PetscFunctionReturn(PETSC_SUCCESS);
426   }
427   buf[0] = '0';
428   buf[1] = 0;
429   PetscFunctionReturn(PETSC_SUCCESS);
430 }
431 
432 /*
433     Removes trailing zeros
434 */
435 #if (PETSC_SIZEOF_SIZE_T == 8)
436   #define MAX_SIZE_T PETSC_INT64_MAX
437 #else
438   #define MAX_SIZE_T INT_MAX
439 #endif
440 PetscErrorCode PetscStripTrailingZeros(char *buf)
441 {
442   char  *found = NULL;
443   size_t i, n, m = MAX_SIZE_T;
444 
445   PetscFunctionBegin;
446   /* if there is an e in string DO NOT strip trailing zeros */
447   PetscCall(PetscStrchr(buf, 'e', &found));
448   if (found) PetscFunctionReturn(PETSC_SUCCESS);
449 
450   PetscCall(PetscStrlen(buf, &n));
451   /* locate decimal point */
452   for (i = 0; i < n; i++) {
453     if (buf[i] == '.') {
454       m = i;
455       break;
456     }
457   }
458   /* if not decimal point then no zeros to remove */
459   if (m == MAX_SIZE_T) PetscFunctionReturn(PETSC_SUCCESS);
460   /* start at right end of string removing 0s */
461   for (i = n - 1; i > m; i++) {
462     if (buf[i] != '0') PetscFunctionReturn(PETSC_SUCCESS);
463     buf[i] = 0;
464   }
465   PetscFunctionReturn(PETSC_SUCCESS);
466 }
467 
468 /*
469     Removes leading 0 from 0.22 or -0.22
470 */
471 PetscErrorCode PetscStripInitialZero(char *buf)
472 {
473   size_t i, n;
474 
475   PetscFunctionBegin;
476   PetscCall(PetscStrlen(buf, &n));
477   if (buf[0] == '0') {
478     for (i = 0; i < n; i++) buf[i] = buf[i + 1];
479   } else if (buf[0] == '-' && buf[1] == '0') {
480     for (i = 1; i < n; i++) buf[i] = buf[i + 1];
481   }
482   PetscFunctionReturn(PETSC_SUCCESS);
483 }
484 
485 /*
486      Removes the extraneous zeros in numbers like 1.10000e6
487 */
488 PetscErrorCode PetscStripZeros(char *buf)
489 {
490   size_t i, j, n;
491 
492   PetscFunctionBegin;
493   PetscCall(PetscStrlen(buf, &n));
494   if (n < 5) PetscFunctionReturn(PETSC_SUCCESS);
495   for (i = 1; i < n - 1; i++) {
496     if (buf[i] == 'e' && buf[i - 1] == '0') {
497       for (j = i; j < n + 1; j++) buf[j - 1] = buf[j];
498       PetscCall(PetscStripZeros(buf));
499       PetscFunctionReturn(PETSC_SUCCESS);
500     }
501   }
502   PetscFunctionReturn(PETSC_SUCCESS);
503 }
504 
505 /*
506       Removes the plus in something like 1.1e+2 or 1.1e+02
507 */
508 PetscErrorCode PetscStripZerosPlus(char *buf)
509 {
510   size_t i, j, n;
511 
512   PetscFunctionBegin;
513   PetscCall(PetscStrlen(buf, &n));
514   if (n < 5) PetscFunctionReturn(PETSC_SUCCESS);
515   for (i = 1; i < n - 2; i++) {
516     if (buf[i] == '+') {
517       if (buf[i + 1] == '0') {
518         for (j = i + 1; j < n; j++) buf[j - 1] = buf[j + 1];
519         PetscFunctionReturn(PETSC_SUCCESS);
520       } else {
521         for (j = i + 1; j < n + 1; j++) buf[j - 1] = buf[j];
522         PetscFunctionReturn(PETSC_SUCCESS);
523       }
524     } else if (buf[i] == '-') {
525       if (buf[i + 1] == '0') {
526         for (j = i + 1; j < n; j++) buf[j] = buf[j + 1];
527         PetscFunctionReturn(PETSC_SUCCESS);
528       }
529     }
530   }
531   PetscFunctionReturn(PETSC_SUCCESS);
532 }
533