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 process 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 processor in set 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 processor in set 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 ASCII `PetscViewer`

476:     Not Collective, but only first processor in set 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: /* ----------------------------------------------------------------------- */

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

512:     Not Collective, but only first processor in set has any effect

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

518:     Level: developer

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

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

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

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

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

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

589: /*@C
590:      PetscViewerFileSetName - Sets the name of the file the `PetscViewer` uses.

592:     Collective

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

598:     Level: advanced

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

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

615: /*@C
616:      PetscViewerFileGetName - Gets the name of the file the `PetscViewer` uses.

618:     Not Collective

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

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

626:     Level: advanced

628: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
629: @*/
630: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
631: {
632:   PetscFunctionBegin;
635:   PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
636:   PetscFunctionReturn(PETSC_SUCCESS);
637: }

639: PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
640: {
641:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

643:   PetscFunctionBegin;
644:   *name = vascii->filename;
645:   PetscFunctionReturn(PETSC_SUCCESS);
646: }

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

656:   PetscFunctionBegin;
657:   PetscCall(PetscViewerFileClose_ASCII(viewer));
658:   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
659:   PetscCall(PetscStrallocpy(name, &vascii->filename));

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

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

720: PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
721: {
722:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;

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

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

744:   vascii->sviewer                                      = *outviewer;
745:   (*outviewer)->format                                 = viewer->format;
746:   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
747:   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
748:   PetscFunctionReturn(PETSC_SUCCESS);
749: }

751: PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
752: {
753:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;

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

759:   PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
760:   ascii->sviewer             = NULL;
761:   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
762:   PetscCall(PetscViewerDestroy(outviewer));
763:   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
764:   PetscFunctionReturn(PETSC_SUCCESS);
765: }

767: PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
768: {
769:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;

771:   PetscFunctionBegin;
772:   if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
773:   PetscFunctionReturn(PETSC_SUCCESS);
774: }

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

779:   Level: beginner

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

789:   PetscFunctionBegin;
790:   PetscCall(PetscNew(&vascii));
791:   viewer->data = (void *)vascii;

793:   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
794:   viewer->ops->flush            = PetscViewerFlush_ASCII;
795:   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
796:   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
797:   viewer->ops->view             = PetscViewerView_ASCII;
798:   viewer->ops->read             = PetscViewerASCIIRead;

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

811:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
812:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
813:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
814:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
815:   PetscFunctionReturn(PETSC_SUCCESS);
816: }

818: /*@C
819:     PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified file from
820:     several processors.  Output of the first processor is followed by that of the
821:     second, etc.

823:     Not Collective, must call collective `PetscViewerFlush()` to get the results out

825:     Input Parameters:
826: +   viewer - the `PETSCVIEWERASCII` `PetscViewer`
827: -   format - the usual printf() format string

829:     Level: intermediate

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

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

839:     So the typical calling sequence looks like
840: .vb
841:     PetscViewerASCIIPushSynchronized(viewer);
842:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
843:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
844:     ...
845:     PetscViewerFlush(viewer);
846:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
847:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
848:     ...
849:     PetscViewerFlush(viewer);
850:    PetscViewerASCIIPopSynchronized(viewer);
851: .ve

853:     Fortran Note:
854:       Can only print a single character* string

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

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

876:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
877:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

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

888:   fp = vascii->fd;

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

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

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

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

955: /*@C
956:    PetscViewerASCIIRead - Reads from a ASCII file

958:    Only process 0 in the `PetscViewer` may call this

960:    Input Parameters:
961: +  viewer - the `PETSCVIEWERASCII` viewer
962: .  data - location to write the data
963: .  num - number of items of data to read
964: -  datatype - type of data to read

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

969:    Level: beginner

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

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