Actual source code: filev.c


  2: #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h>

  4: #define QUEUESTRINGSIZE 8192

  6: static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer)
  7: {
  8:   PetscMPIInt        rank;
  9:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
 10:   int                err;

 12:   PetscFunctionBegin;
 13:   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
 14:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
 15:   if (rank == 0 && vascii->fd != stderr && vascii->fd != PETSC_STDOUT) {
 16:     if (vascii->fd && vascii->closefile) {
 17:       err = fclose(vascii->fd);
 18:       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
 19:     }
 20:     if (vascii->storecompressed) {
 21:       char  par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN];
 22:       FILE *fp;
 23:       PetscCall(PetscStrncpy(par, "gzip ", sizeof(par)));
 24:       PetscCall(PetscStrlcat(par, vascii->filename, sizeof(par)));
 25: #if defined(PETSC_HAVE_POPEN)
 26:       PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp));
 27:       PetscCheck(!fgets(buf, 1024, fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from compression command %s\n%s", par, buf);
 28:       PetscCall(PetscPClose(PETSC_COMM_SELF, fp));
 29: #else
 30:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
 31: #endif
 32:     }
 33:   }
 34:   PetscCall(PetscFree(vascii->filename));
 35:   PetscFunctionReturn(PETSC_SUCCESS);
 36: }

 38: /* ----------------------------------------------------------------------*/
 39: PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
 40: {
 41:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
 42:   PetscViewerLink   *vlink;
 43:   PetscBool          flg;

 45:   PetscFunctionBegin;
 46:   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
 47:   PetscCall(PetscViewerFileClose_ASCII(viewer));
 48:   PetscCall(PetscFree(vascii));

 50:   /* remove the viewer from the list in the MPI Communicator */
 51:   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0));

 53:   PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
 54:   if (flg) {
 55:     if (vlink && vlink->viewer == viewer) {
 56:       if (vlink->next) {
 57:         PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next));
 58:       } else {
 59:         PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval));
 60:       }
 61:       PetscCall(PetscFree(vlink));
 62:     } else {
 63:       while (vlink && vlink->next) {
 64:         if (vlink->next->viewer == viewer) {
 65:           PetscViewerLink *nv = vlink->next;
 66:           vlink->next         = vlink->next->next;
 67:           PetscCall(PetscFree(nv));
 68:         }
 69:         vlink = vlink->next;
 70:       }
 71:     }
 72:   }

 74:   if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
 75:     PetscViewer aviewer;
 76:     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
 77:     if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval));
 78:   }
 79:   if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
 80:     PetscViewer aviewer;
 81:     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
 82:     if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval));
 83:   }
 84:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
 85:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
 86:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
 87:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
 88:   PetscFunctionReturn(PETSC_SUCCESS);
 89: }

 91: PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
 92: {
 93:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

 95:   PetscFunctionBegin;
 96:   PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer));
 97:   PetscFunctionReturn(PETSC_SUCCESS);
 98: }

100: PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
101: {
102:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
103:   MPI_Comm           comm;
104:   PetscMPIInt        rank, size;
105:   FILE              *fd = vascii->fd;

107:   PetscFunctionBegin;
108:   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
109:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
110:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
111:   PetscCallMPI(MPI_Comm_size(comm, &size));

113:   if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd));

115:   if (vascii->allowsynchronized) {
116:     PetscMPIInt tag, i, j, n = 0, dummy = 0;
117:     char       *message;
118:     MPI_Status  status;

120:     PetscCall(PetscCommDuplicate(comm, &comm, &tag));

122:     /* First processor waits for messages from all other processors */
123:     if (rank == 0) {
124:       /* flush my own messages that I may have queued up */
125:       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
126:       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
127:         if (!vascii->bviewer) {
128:           PetscCall(PetscFPrintf(comm, fd, "%s", next->string));
129:         } else {
130:           PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string));
131:         }
132:         previous = next;
133:         next     = next->next;
134:         PetscCall(PetscFree(previous->string));
135:         PetscCall(PetscFree(previous));
136:       }
137:       vascii->petsc_printfqueue       = NULL;
138:       vascii->petsc_printfqueuelength = 0;
139:       for (i = 1; i < size; i++) {
140:         /* to prevent a flood of messages to process zero, request each message separately */
141:         PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
142:         PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
143:         for (j = 0; j < n; j++) {
144:           PetscMPIInt size = 0;

146:           PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
147:           PetscCall(PetscMalloc1(size, &message));
148:           PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
149:           if (!vascii->bviewer) {
150:             PetscCall(PetscFPrintf(comm, fd, "%s", message));
151:           } else {
152:             PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message));
153:           }
154:           PetscCall(PetscFree(message));
155:         }
156:       }
157:     } else { /* other processors send queue to processor 0 */
158:       PrintfQueue next = vascii->petsc_printfqueuebase, previous;

160:       PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
161:       PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
162:       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
163:         PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
164:         PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
165:         previous = next;
166:         next     = next->next;
167:         PetscCall(PetscFree(previous->string));
168:         PetscCall(PetscFree(previous));
169:       }
170:       vascii->petsc_printfqueue       = NULL;
171:       vascii->petsc_printfqueuelength = 0;
172:     }
173:     PetscCall(PetscCommDestroy(&comm));
174:   }
175:   PetscFunctionReturn(PETSC_SUCCESS);
176: }

178: /*@C
179:     PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`.

181:     Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer; No Fortran Support

183:     Input Parameter:
184: .    viewer - `PetscViewer` context, obtained from `PetscViewerASCIIOpen()`

186:     Output Parameter:
187: .    fd - file pointer

189:     Level: intermediate

191:     Note:
192:     For the standard `PETSCVIEWERASCII` the value is valid only on MPI rank 0 of the viewer

194: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`,
195:           `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
196: @*/
197: PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
198: {
199:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

201:   PetscFunctionBegin;
202:   *fd = vascii->fd;
203:   PetscFunctionReturn(PETSC_SUCCESS);
204: }

206: PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
207: {
208:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

210:   PetscFunctionBegin;
211:   *mode = vascii->mode;
212:   PetscFunctionReturn(PETSC_SUCCESS);
213: }

215: PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
216: {
217:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

219:   PetscFunctionBegin;
220:   vascii->mode = mode;
221:   PetscFunctionReturn(PETSC_SUCCESS);
222: }

224: /*
225:    If petsc_history is on, then all Petsc*Printf() results are saved
226:    if the appropriate (usually .petschistory) file.
227: */
228: PETSC_INTERN FILE *petsc_history;

230: /*@
231:     PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times before printing

233:     Not Collective, but only first processor in set has any effect; No Fortran Support

235:     Input Parameters:
236: +    viewer - obtained with `PetscViewerASCIIOpen()`
237: -    tabs - number of tabs

239:     Level: developer

241:     Note:
242:      `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage

244: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
245:           `PetscViewerASCIIGetTab()`,
246:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
247:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
248:           `PetscViewerASCIIPushTab()`
249: @*/
250: PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
251: {
252:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
253:   PetscBool          iascii;

255:   PetscFunctionBegin;
257:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
258:   if (iascii) ascii->tab = tabs;
259:   PetscFunctionReturn(PETSC_SUCCESS);
260: }

262: /*@
263:     PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.

265:     Not Collective, meaningful on first processor only; No Fortran Support

267:     Input Parameter:
268: .    viewer - obtained with `PetscViewerASCIIOpen()`

270:     Output Parameter:
271: .    tabs - number of tabs

273:     Level: developer

275: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
276:           `PetscViewerASCIISetTab()`,
277:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
278:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
279: @*/
280: PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
281: {
282:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
283:   PetscBool          iascii;

285:   PetscFunctionBegin;
287:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
288:   if (iascii && tabs) *tabs = ascii->tab;
289:   PetscFunctionReturn(PETSC_SUCCESS);
290: }

292: /*@
293:     PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing

295:     Not Collective, but only first processor in set has any effect; No Fortran Support

297:     Input Parameters:
298: +    viewer - obtained with `PetscViewerASCIIOpen()`
299: -    tabs - number of tabs

301:     Level: developer

303:     Note:
304:      `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage

306: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
307:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
308:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
309: @*/
310: PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
311: {
312:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
313:   PetscBool          iascii;

315:   PetscFunctionBegin;
317:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
318:   if (iascii) ascii->tab += tabs;
319:   PetscFunctionReturn(PETSC_SUCCESS);
320: }

322: /*@
323:     PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing

325:     Not Collective, but only first processor in set has any effect; No Fortran Support

327:     Input Parameters:
328: +    viewer - obtained with `PetscViewerASCIIOpen()`
329: -    tabs - number of tabs

331:     Level: developer

333:     Note:
334:      `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage

336: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
337:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
338:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
339:           `PetscViewerASCIIPushTab()`
340: @*/
341: PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
342: {
343:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
344:   PetscBool          iascii;

346:   PetscFunctionBegin;
348:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
349:   if (iascii) ascii->tab -= tabs;
350:   PetscFunctionReturn(PETSC_SUCCESS);
351: }

353: /*@C
354:     PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer

356:     Collective

358:     Input Parameter:
359: .    viewer - obtained with `PetscViewerASCIIOpen()`

361:     Level: intermediate

363:     Note:
364:     See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.

366: .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
367:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
368:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
369: @*/
370: PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
371: {
372:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
373:   PetscBool          iascii;

375:   PetscFunctionBegin;
377:   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
378:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
379:   if (iascii) ascii->allowsynchronized++;
380:   PetscFunctionReturn(PETSC_SUCCESS);
381: }

383: /*@C
384:     PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer

386:     Collective

388:     Input Parameter:
389: .    viewer - obtained with `PetscViewerASCIIOpen()`

391:     Level: intermediate

393:     Note:
394:     See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.

396: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
397:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
398:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
399: @*/
400: PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
401: {
402:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
403:   PetscBool          iascii;

405:   PetscFunctionBegin;
407:   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
408:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
409:   if (iascii) {
410:     ascii->allowsynchronized--;
411:     PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()");
412:   }
413:   PetscFunctionReturn(PETSC_SUCCESS);
414: }

416: /*@C
417:     PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
418:      lines are tabbed.

420:     Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support

422:     Input Parameter:
423: .    viewer - obtained with `PetscViewerASCIIOpen()`

425:     Level: developer

427: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
428:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
429:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
430: @*/
431: PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
432: {
433:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
434:   PetscBool          iascii;

436:   PetscFunctionBegin;
438:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
439:   if (iascii) ascii->tab++;
440:   PetscFunctionReturn(PETSC_SUCCESS);
441: }

443: /*@C
444:     PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by
445:     `PetscViewerASCIIPushTab()`

447:     Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support

449:     Input Parameter:
450: .    viewer - obtained with `PetscViewerASCIIOpen()`

452:     Level: developer

454: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
455:           `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
456:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
457: @*/
458: PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
459: {
460:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
461:   PetscBool          iascii;

463:   PetscFunctionBegin;
465:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
466:   if (iascii) {
467:     PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed");
468:     ascii->tab--;
469:   }
470:   PetscFunctionReturn(PETSC_SUCCESS);
471: }

473: /*@
474:     PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer`

476:     Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support

478:     Input Parameters:
479: +    viewer - obtained with `PetscViewerASCIIOpen()`
480: -    flg - `PETSC_TRUE` or `PETSC_FALSE`

482:     Level: developer

484: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
485:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
486:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
487: @*/
488: PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
489: {
490:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
491:   PetscBool          iascii;

493:   PetscFunctionBegin;
495:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
496:   if (iascii) {
497:     if (flg) ascii->tab = ascii->tab_store;
498:     else {
499:       ascii->tab_store = ascii->tab;
500:       ascii->tab       = 0;
501:     }
502:   }
503:   PetscFunctionReturn(PETSC_SUCCESS);
504: }

506: /*@C
507:     PetscViewerASCIIPrintf - Prints to a file, only from the first
508:     processor in the `PetscViewer` of type `PETSCVIEWERASCII`

510:     Not Collective, but only the first MPI rank in the viewer has any effect

512:     Input Parameters:
513: +    viewer - obtained with `PetscViewerASCIIOpen()`
514: -    format - the usual printf() format string

516:     Level: developer

518:     Fortran Note:
519:     The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran.
520:     That is, you can only pass a single character string from Fortran.

522: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
523:           `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
524:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
525: @*/
526: PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
527: {
528:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
529:   PetscMPIInt        rank;
530:   PetscInt           tab, intab = ascii->tab;
531:   FILE              *fd = ascii->fd;
532:   PetscBool          iascii;

534:   PetscFunctionBegin;
536:   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
538:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
539:   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
540:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
541:   if (rank) PetscFunctionReturn(PETSC_SUCCESS);

543:   if (ascii->bviewer) { /* pass string up to parent viewer */
544:     char   *string;
545:     va_list Argp;
546:     size_t  fullLength;

548:     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
549:     va_start(Argp, format);
550:     PetscCall(PetscVSNPrintf(string, QUEUESTRINGSIZE, format, &fullLength, Argp));
551:     va_end(Argp);
552:     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%s", string));
553:     PetscCall(PetscFree(string));
554:   } else { /* write directly to file */
555:     va_list Argp;
556:     /* flush my own messages that I may have queued up */
557:     PrintfQueue next = ascii->petsc_printfqueuebase, previous;
558:     PetscInt    i;
559:     for (i = 0; i < ascii->petsc_printfqueuelength; i++) {
560:       PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "%s", next->string));
561:       previous = next;
562:       next     = next->next;
563:       PetscCall(PetscFree(previous->string));
564:       PetscCall(PetscFree(previous));
565:     }
566:     ascii->petsc_printfqueue       = NULL;
567:     ascii->petsc_printfqueuelength = 0;
568:     tab                            = intab;
569:     while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "  "));

571:     va_start(Argp, format);
572:     PetscCall((*PetscVFPrintf)(fd, format, Argp));
573:     va_end(Argp);
574:     PetscCall(PetscFFlush(fd));
575:     if (petsc_history) {
576:       tab = intab;
577:       while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, petsc_history, "  "));
578:       va_start(Argp, format);
579:       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
580:       va_end(Argp);
581:       PetscCall(PetscFFlush(petsc_history));
582:     }
583:   }
584:   PetscFunctionReturn(PETSC_SUCCESS);
585: }

587: /*@C
588:      PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.

590:     Collective

592:   Input Parameters:
593: +  viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
594: -  name - the name of the file it should use

596:     Level: advanced

598:   Note:
599:   This will have no effect on viewers that are not related to files

601: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
602:           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
603: @*/
604: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
605: {
606:   char filename[PETSC_MAX_PATH_LEN];

608:   PetscFunctionBegin;
611:   PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
612:   PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
613:   PetscFunctionReturn(PETSC_SUCCESS);
614: }

616: /*@C
617:      PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using

619:     Not Collective

621:   Input Parameter:
622: .  viewer - the `PetscViewer`

624:   Output Parameter:
625: .  name - the name of the file it is using

627:     Level: advanced

629:   Note:
630:   This will have no effect on viewers that are not related to files

632: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
633: @*/
634: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
635: {
636:   PetscFunctionBegin;
639:   PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
640:   PetscFunctionReturn(PETSC_SUCCESS);
641: }

643: PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
644: {
645:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

647:   PetscFunctionBegin;
648:   *name = vascii->filename;
649:   PetscFunctionReturn(PETSC_SUCCESS);
650: }

652: PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
653: {
654:   size_t             len;
655:   char               fname[PETSC_MAX_PATH_LEN], *gz = NULL;
656:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
657:   PetscBool          isstderr, isstdout;
658:   PetscMPIInt        rank;

660:   PetscFunctionBegin;
661:   PetscCall(PetscViewerFileClose_ASCII(viewer));
662:   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
663:   PetscCall(PetscStrallocpy(name, &vascii->filename));

665:   /* Is this file to be compressed */
666:   vascii->storecompressed = PETSC_FALSE;

668:   PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
669:   if (gz) {
670:     PetscCall(PetscStrlen(gz, &len));
671:     if (len == 3) {
672:       PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first");
673:       *gz                     = 0;
674:       vascii->storecompressed = PETSC_TRUE;
675:     }
676:   }
677:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
678:   if (rank == 0) {
679:     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
680:     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
681:     /* empty filename means stdout */
682:     if (name[0] == 0) isstdout = PETSC_TRUE;
683:     if (isstderr) vascii->fd = PETSC_STDERR;
684:     else if (isstdout) vascii->fd = PETSC_STDOUT;
685:     else {
686:       PetscCall(PetscFixFilename(name, fname));
687:       switch (vascii->mode) {
688:       case FILE_MODE_READ:
689:         vascii->fd = fopen(fname, "r");
690:         break;
691:       case FILE_MODE_WRITE:
692:         vascii->fd = fopen(fname, "w");
693:         break;
694:       case FILE_MODE_APPEND:
695:         vascii->fd = fopen(fname, "a");
696:         break;
697:       case FILE_MODE_UPDATE:
698:         vascii->fd = fopen(fname, "r+");
699:         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
700:         break;
701:       case FILE_MODE_APPEND_UPDATE:
702:         /* I really want a file which is opened at the end for updating,
703:            not a+, which opens at the beginning, but makes writes at the end.
704:         */
705:         vascii->fd = fopen(fname, "r+");
706:         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
707:         else {
708:           int ret = fseek(vascii->fd, 0, SEEK_END);
709:           PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
710:         }
711:         break;
712:       default:
713:         SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
714:       }
715:       PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname);
716:     }
717:   }
718: #if defined(PETSC_USE_LOG)
719:   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
720: #endif
721:   PetscFunctionReturn(PETSC_SUCCESS);
722: }

724: PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
725: {
726:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;

728:   PetscFunctionBegin;
729:   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
730:   PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
731:   /*
732:      The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
733:      because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
734:      (since the count never gets to zero) in some examples this displays information that otherwise would be lost

736:      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
737:      PCView_GASM().
738:   */
739:   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
740:   PetscCall(PetscViewerCreate(subcomm, outviewer));
741:   PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
742:   PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
743:   ovascii            = (PetscViewer_ASCII *)(*outviewer)->data;
744:   ovascii->fd        = vascii->fd;
745:   ovascii->tab       = vascii->tab;
746:   ovascii->closefile = PETSC_FALSE;

748:   vascii->sviewer                                      = *outviewer;
749:   (*outviewer)->format                                 = viewer->format;
750:   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
751:   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
752:   PetscFunctionReturn(PETSC_SUCCESS);
753: }

755: PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
756: {
757:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;

759:   PetscFunctionBegin;
760:   PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
761:   PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");

763:   PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
764:   ascii->sviewer             = NULL;
765:   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
766:   PetscCall(PetscViewerDestroy(outviewer));
767:   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
768:   PetscFunctionReturn(PETSC_SUCCESS);
769: }

771: PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
772: {
773:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;

775:   PetscFunctionBegin;
776:   if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
777:   PetscFunctionReturn(PETSC_SUCCESS);
778: }

780: /*MC
781:    PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file

783:   Level: beginner

785: .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
786:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
787:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
788: M*/
789: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
790: {
791:   PetscViewer_ASCII *vascii;

793:   PetscFunctionBegin;
794:   PetscCall(PetscNew(&vascii));
795:   viewer->data = (void *)vascii;

797:   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
798:   viewer->ops->flush            = PetscViewerFlush_ASCII;
799:   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
800:   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
801:   viewer->ops->view             = PetscViewerView_ASCII;
802:   viewer->ops->read             = PetscViewerASCIIRead;

804:   /* defaults to stdout unless set with PetscViewerFileSetName() */
805:   vascii->fd        = PETSC_STDOUT;
806:   vascii->mode      = FILE_MODE_WRITE;
807:   vascii->bviewer   = NULL;
808:   vascii->subviewer = NULL;
809:   vascii->sviewer   = NULL;
810:   vascii->tab       = 0;
811:   vascii->tab_store = 0;
812:   vascii->filename  = NULL;
813:   vascii->closefile = PETSC_TRUE;

815:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
816:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
817:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
818:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
819:   PetscFunctionReturn(PETSC_SUCCESS);
820: }

822: /*@C
823:     PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
824:     several processors.  Output of the first processor is followed by that of the
825:     second, etc.

827:     Not Collective, must call collective `PetscViewerFlush()` to get the results flushed

829:     Input Parameters:
830: +   viewer - the `PETSCVIEWERASCII` `PetscViewer`
831: -   format - the usual printf() format string

833:     Level: intermediate

835:     Notes:
836:     You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
837:     Then you can do multiple independent calls to this routine.

839:     The actual synchronized print is then done using `PetscViewerFlush()`.
840:     `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
841:     to conclude the "synchronized session".

843:     So the typical calling sequence looks like
844: .vb
845:     PetscViewerASCIIPushSynchronized(viewer);
846:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
847:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
848:     ...
849:     PetscViewerFlush(viewer);
850:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
851:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
852:     ...
853:     PetscViewerFlush(viewer);
854:    PetscViewerASCIIPopSynchronized(viewer);
855: .ve

857:     Fortran Note:
858:       Can only print a single character* string

860: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
861:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
862:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
863: @*/
864: PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
865: {
866:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
867:   PetscMPIInt        rank;
868:   PetscInt           tab = vascii->tab;
869:   MPI_Comm           comm;
870:   FILE              *fp;
871:   PetscBool          iascii, hasbviewer = PETSC_FALSE;

873:   PetscFunctionBegin;
876:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
877:   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
878:   PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");

880:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
881:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

883:   if (vascii->bviewer) {
884:     hasbviewer = PETSC_TRUE;
885:     if (rank == 0) {
886:       vascii = (PetscViewer_ASCII *)vascii->bviewer->data;
887:       PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
888:       PetscCallMPI(MPI_Comm_rank(comm, &rank));
889:     }
890:   }

892:   fp = vascii->fd;

894:   if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */
895:     va_list Argp;
896:     /* flush my own messages that I may have queued up */
897:     PrintfQueue next = vascii->petsc_printfqueuebase, previous;
898:     PetscInt    i;
899:     for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
900:       PetscCall(PetscFPrintf(comm, fp, "%s", next->string));
901:       previous = next;
902:       next     = next->next;
903:       PetscCall(PetscFree(previous->string));
904:       PetscCall(PetscFree(previous));
905:     }
906:     vascii->petsc_printfqueue       = NULL;
907:     vascii->petsc_printfqueuelength = 0;

909:     while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, "  "));

911:     va_start(Argp, format);
912:     PetscCall((*PetscVFPrintf)(fp, format, Argp));
913:     va_end(Argp);
914:     PetscCall(PetscFFlush(fp));
915:     if (petsc_history) {
916:       va_start(Argp, format);
917:       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
918:       va_end(Argp);
919:       PetscCall(PetscFFlush(petsc_history));
920:     }
921:     va_end(Argp);
922:   } else { /* other processors add to queue */
923:     char       *string;
924:     va_list     Argp;
925:     size_t      fullLength;
926:     PrintfQueue next;

928:     PetscCall(PetscNew(&next));
929:     if (vascii->petsc_printfqueue) {
930:       vascii->petsc_printfqueue->next = next;
931:       vascii->petsc_printfqueue       = next;
932:     } else {
933:       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
934:     }
935:     vascii->petsc_printfqueuelength++;
936:     next->size = QUEUESTRINGSIZE;
937:     PetscCall(PetscCalloc1(next->size, &next->string));
938:     string = next->string;
939:     tab *= 2;
940:     while (tab--) *string++ = ' ';
941:     va_start(Argp, format);
942:     PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
943:     va_end(Argp);
944:     if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
945:       PetscCall(PetscFree(next->string));
946:       next->size = fullLength + 2 * vascii->tab;
947:       PetscCall(PetscCalloc1(next->size, &next->string));
948:       string = next->string;
949:       tab    = 2 * vascii->tab;
950:       while (tab--) *string++ = ' ';
951:       va_start(Argp, format);
952:       PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
953:       va_end(Argp);
954:     }
955:   }
956:   PetscFunctionReturn(PETSC_SUCCESS);
957: }

959: /*@C
960:    PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file

962:    Only MPI rank 0 in the `PetscViewer` may call this

964:    Input Parameters:
965: +  viewer - the `PETSCVIEWERASCII` viewer
966: .  data - location to write the data, treated as an array of type indicated by `datatype`
967: .  num - number of items of data to read
968: -  datatype - type of data to read

970:    Output Parameter:
971: .  count - number of items of data actually read, or `NULL`

973:    Level: beginner

975: .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
976:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
977:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
978: @*/
979: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
980: {
981:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
982:   FILE              *fd     = vascii->fd;
983:   PetscInt           i;
984:   int                ret = 0;
985:   PetscMPIInt        rank;

987:   PetscFunctionBegin;
989:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
990:   PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
991:   for (i = 0; i < num; i++) {
992:     if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
993:     else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
994:     else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
995:     else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
996:     else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
997:     else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
998:     else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
999:     else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1000: #if defined(PETSC_USE_REAL___FLOAT128)
1001:     else if (dtype == PETSC___FLOAT128) {
1002:       double tmp;
1003:       ret                     = fscanf(fd, "%lg", &tmp);
1004:       ((__float128 *)data)[i] = tmp;
1005:     }
1006: #endif
1007:     else
1008:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
1009:     PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1010:     if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
1011:   }
1012:   if (count) *count = i;
1013:   else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
1014:   PetscFunctionReturn(PETSC_SUCCESS);
1015: }