Actual source code: filev.c

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

  3: #define QUEUESTRINGSIZE 8192

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

188:   Level: intermediate

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

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

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

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

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

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

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

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

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

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

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

238:   Level: developer

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

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

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

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

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

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

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

272:   Level: developer

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

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

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

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

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

300:   Level: developer

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

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

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

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

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

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

330:   Level: developer

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

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

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

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

355:   Collective

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

360:   Level: intermediate

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

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

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

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

385:   Collective

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

390:   Level: intermediate

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

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

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

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

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

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

424:   Level: developer

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

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

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

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

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

451:   Level: developer

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

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

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

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

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

481:   Level: developer

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

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

505: #if defined(PETSC_USE_FORTRAN_BINDINGS)

507:   #if defined(PETSC_HAVE_FORTRAN_CAPS)
508:     #define petscviewerasciiopenwithfileunit_ PETSCVIEWERASCIIOPENWITHFILEUNIT
509:     #define petscviewerasciisetfilefileunit_  PETSCVIEWERASCIISETFILEUNIT
510:     #define petscfortranprinttounit_          PETSCFORTRANPRINTTOUNIT
511:   #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
512:     #define petscviewerasciiopenwithfileunit_ petscviewerasciiopenwithfileunit
513:     #define petscviewerasciisetfileunit_      petscviewerasciisetfileunit
514:     #define petscfortranprinttounit_          petscfortranprinttounit
515:   #endif

517:   #if defined(__cplusplus)
518: extern "C" void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
519:   #else
520: extern void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
521:   #endif

523:   #define PETSCDEFAULTBUFFERSIZE 8 * 1024

525: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
526: /*MC
527:   PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` to write to a Fortran IO unit

529:   Synopsis:
530: #include <petscviewer.h>
531:   void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr)

533:   Input Parameters:
534: + lab  - the viewer
535: - unit - the unit number

537:   Output Parameter:
538: . ierr - the error code

540:   Level: intermediate

542:   Note:
543:   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`

545:   Fortran Notes:
546:   Only for Fortran, use  `PetscViewerASCIISetFILE()` for C

548: .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`
549: M*/
550: PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, PetscInt *unit, PetscErrorCode *ierr)
551: {
552:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)(*lab)->data;

554:   if (vascii->mode == FILE_MODE_READ) {
555:     *ierr = PETSC_ERR_ARG_WRONGSTATE;
556:     return;
557:   }
558:   vascii->fileunit = *unit;
559: }

561: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
562: /*MC
563:   PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit

565:   Synopsis:
566: #include <petscviewer.h>
567:   void PetscViewerASCIIOpenWithFileUnit(MPI_Comm comm, PetscInt unit, PetscViewer viewer, PetscErrorCode ierr)

569:   Input Parameters:
570: + comm - the `MPI_Comm` to share the viewer
571: - unit - the unit number

573:   Output Parameters:
574: + lab  - the viewer
575: - ierr - the error code

577:   Level: intermediate

579:   Note:
580:   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`

582:   Fortran Notes:
583:   Only for Fortran, use  `PetscViewerASCIIOpenWithFILE()` for C

585: .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()`
586: M*/
587: PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Comm *comm, PetscInt *unit, PetscViewer *lab, PetscErrorCode *ierr)
588: {
589:   *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab);
590:   if (*ierr) return;
591:   *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII);
592:   if (*ierr) return;
593:   *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE);
594:   if (*ierr) return;
595:   petscviewerasciisetfileunit_(lab, unit, ierr);
596: }

598: static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
599: {
600:   PetscErrorCode ierr;
601:   char           str[PETSCDEFAULTBUFFERSIZE];
602:   size_t         len;

604:   PetscFunctionBegin;
605:   PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp));
606:   PetscCall(PetscStrlen(str, &len));
607:   petscfortranprinttounit_(&unit, str, &ierr, (int)len);
608:   PetscFunctionReturn(PETSC_SUCCESS);
609: }

611: static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
612: {
613:   PetscErrorCode ierr;
614:   size_t         len;

616:   PetscFunctionBegin;
617:   PetscCall(PetscStrlen(str, &len));
618:   petscfortranprinttounit_(&unit, str, &ierr, (int)len);
619:   PetscFunctionReturn(PETSC_SUCCESS);
620: }

622: #else

624: /* these will never be used; but are needed to link with */
625: static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
626: {
627:   PetscFunctionBegin;
628:   PetscFunctionReturn(PETSC_SUCCESS);
629: }

631: static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
632: {
633:   PetscFunctionBegin;
634:   PetscFunctionReturn(PETSC_SUCCESS);
635: }
636: #endif

638: /*@C
639:   PetscViewerASCIIPrintf - Prints to a file, only from the first
640:   processor in the `PetscViewer` of type `PETSCVIEWERASCII`

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

644:   Input Parameters:
645: + viewer - obtained with `PetscViewerASCIIOpen()`
646: - format - the usual printf() format string

648:   Level: developer

650:   Fortran Notes:
651:   The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran.
652:   That is, you can only pass a single character string from Fortran.

654: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
655:           `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
656:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
657: @*/
658: PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
659: {
660:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
661:   PetscMPIInt        rank;
662:   PetscInt           tab, intab = ascii->tab;
663:   FILE              *fd = ascii->fd;
664:   PetscBool          iascii;

666:   PetscFunctionBegin;
668:   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
669:   PetscAssertPointer(format, 2);
670:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
671:   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
672:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
673:   if (rank) PetscFunctionReturn(PETSC_SUCCESS);

675:   if (ascii->bviewer) { /* pass string up to parent viewer */
676:     char   *string;
677:     va_list Argp;
678:     size_t  fullLength;

680:     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
681:     va_start(Argp, format);
682:     PetscCall(PetscVSNPrintf(string, QUEUESTRINGSIZE, format, &fullLength, Argp));
683:     va_end(Argp);
684:     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%s", string));
685:     PetscCall(PetscFree(string));
686:   } else { /* write directly to file */
687:     va_list Argp;
688:     /* flush my own messages that I may have queued up */
689:     PrintfQueue next = ascii->petsc_printfqueuebase, previous;
690:     PetscInt    i;
691:     for (i = 0; i < ascii->petsc_printfqueuelength; i++) {
692:       if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "%s", next->string));
693:       else PetscCall(PetscFPrintfFortran(ascii->fileunit, next->string));
694:       previous = next;
695:       next     = next->next;
696:       PetscCall(PetscFree(previous->string));
697:       PetscCall(PetscFree(previous));
698:     }
699:     ascii->petsc_printfqueue       = NULL;
700:     ascii->petsc_printfqueuelength = 0;
701:     tab                            = intab;
702:     while (tab--) {
703:       if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "  "));
704:       else PetscCall(PetscFPrintfFortran(ascii->fileunit, "   "));
705:     }

707:     va_start(Argp, format);
708:     if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
709:     else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
710:     va_end(Argp);
711:     PetscCall(PetscFFlush(fd));
712:   }
713:   PetscFunctionReturn(PETSC_SUCCESS);
714: }

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

719:   Collective

721:   Input Parameters:
722: + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
723: - name   - the name of the file it should use

725:   Level: advanced

727:   Note:
728:   This will have no effect on viewers that are not related to files

730: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
731:           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
732: @*/
733: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
734: {
735:   char filename[PETSC_MAX_PATH_LEN];

737:   PetscFunctionBegin;
739:   PetscAssertPointer(name, 2);
740:   PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
741:   PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
742:   PetscFunctionReturn(PETSC_SUCCESS);
743: }

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

748:   Not Collective

750:   Input Parameter:
751: . viewer - the `PetscViewer`

753:   Output Parameter:
754: . name - the name of the file it is using

756:   Level: advanced

758:   Note:
759:   This will have no effect on viewers that are not related to files

761: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
762: @*/
763: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
764: {
765:   PetscFunctionBegin;
767:   PetscAssertPointer(name, 2);
768:   PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
769:   PetscFunctionReturn(PETSC_SUCCESS);
770: }

772: static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
773: {
774:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

776:   PetscFunctionBegin;
777:   *name = vascii->filename;
778:   PetscFunctionReturn(PETSC_SUCCESS);
779: }

781: #include <errno.h>
782: static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
783: {
784:   size_t             len;
785:   char               fname[PETSC_MAX_PATH_LEN], *gz = NULL;
786:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
787:   PetscBool          isstderr, isstdout;
788:   PetscMPIInt        rank;

790:   PetscFunctionBegin;
791:   PetscCall(PetscViewerFileClose_ASCII(viewer));
792:   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
793:   PetscCall(PetscStrallocpy(name, &vascii->filename));

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

798:   PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
799:   if (gz) {
800:     PetscCall(PetscStrlen(gz, &len));
801:     if (len == 3) {
802:       PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first");
803:       *gz                     = 0;
804:       vascii->storecompressed = PETSC_TRUE;
805:     }
806:   }
807:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
808:   if (rank == 0) {
809:     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
810:     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
811:     /* empty filename means stdout */
812:     if (name[0] == 0) isstdout = PETSC_TRUE;
813:     if (isstderr) vascii->fd = PETSC_STDERR;
814:     else if (isstdout) vascii->fd = PETSC_STDOUT;
815:     else {
816:       PetscCall(PetscFixFilename(name, fname));
817:       switch (vascii->mode) {
818:       case FILE_MODE_READ:
819:         vascii->fd = fopen(fname, "r");
820:         break;
821:       case FILE_MODE_WRITE:
822:         vascii->fd = fopen(fname, "w");
823:         break;
824:       case FILE_MODE_APPEND:
825:         vascii->fd = fopen(fname, "a");
826:         break;
827:       case FILE_MODE_UPDATE:
828:         vascii->fd = fopen(fname, "r+");
829:         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
830:         break;
831:       case FILE_MODE_APPEND_UPDATE:
832:         /* I really want a file which is opened at the end for updating,
833:            not a+, which opens at the beginning, but makes writes at the end.
834:         */
835:         vascii->fd = fopen(fname, "r+");
836:         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
837:         else {
838:           int ret = fseek(vascii->fd, 0, SEEK_END);
839:           PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
840:         }
841:         break;
842:       default:
843:         SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
844:       }
845:       PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
846:     }
847:   }
848:   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
849:   PetscFunctionReturn(PETSC_SUCCESS);
850: }

852: static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
853: {
854:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;

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

864:      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
865:      PCView_GASM().
866:   */
867:   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
868:   PetscCall(PetscViewerCreate(subcomm, outviewer));
869:   PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
870:   PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
871:   ovascii            = (PetscViewer_ASCII *)(*outviewer)->data;
872:   ovascii->fd        = vascii->fd;
873:   ovascii->tab       = vascii->tab;
874:   ovascii->closefile = PETSC_FALSE;

876:   vascii->sviewer                                      = *outviewer;
877:   (*outviewer)->format                                 = viewer->format;
878:   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
879:   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
880:   PetscFunctionReturn(PETSC_SUCCESS);
881: }

883: static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
884: {
885:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;

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

891:   PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
892:   ascii->sviewer             = NULL;
893:   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
894:   PetscCall(PetscViewerDestroy(outviewer));
895:   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
896:   PetscFunctionReturn(PETSC_SUCCESS);
897: }

899: static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
900: {
901:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;

903:   PetscFunctionBegin;
904:   if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
905:   PetscFunctionReturn(PETSC_SUCCESS);
906: }

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

911:   Level: beginner

913: .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
914:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
915:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
916: M*/
917: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
918: {
919:   PetscViewer_ASCII *vascii;

921:   PetscFunctionBegin;
922:   PetscCall(PetscNew(&vascii));
923:   viewer->data = (void *)vascii;

925:   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
926:   viewer->ops->flush            = PetscViewerFlush_ASCII;
927:   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
928:   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
929:   viewer->ops->view             = PetscViewerView_ASCII;
930:   viewer->ops->read             = PetscViewerASCIIRead;

932:   /* defaults to stdout unless set with PetscViewerFileSetName() */
933:   vascii->fd        = PETSC_STDOUT;
934:   vascii->mode      = FILE_MODE_WRITE;
935:   vascii->bviewer   = NULL;
936:   vascii->subviewer = NULL;
937:   vascii->sviewer   = NULL;
938:   vascii->tab       = 0;
939:   vascii->tab_store = 0;
940:   vascii->filename  = NULL;
941:   vascii->closefile = PETSC_TRUE;

943:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
944:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
945:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
946:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
947:   PetscFunctionReturn(PETSC_SUCCESS);
948: }

950: /*@C
951:   PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
952:   several processors.  Output of the first processor is followed by that of the
953:   second, etc.

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

957:   Input Parameters:
958: + viewer - the `PETSCVIEWERASCII` `PetscViewer`
959: - format - the usual printf() format string

961:   Level: intermediate

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

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

971:   So the typical calling sequence looks like
972: .vb
973:     PetscViewerASCIIPushSynchronized(viewer);
974:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
975:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
976:     ...
977:     PetscViewerFlush(viewer);
978:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
979:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
980:     ...
981:     PetscViewerFlush(viewer);
982:    PetscViewerASCIIPopSynchronized(viewer);
983: .ve

985:   Fortran Notes:
986:   Can only print a single character* string

988: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
989:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
990:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
991: @*/
992: PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
993: {
994:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
995:   PetscMPIInt        rank;
996:   PetscInt           tab = vascii->tab;
997:   MPI_Comm           comm;
998:   FILE              *fp;
999:   PetscBool          iascii, hasbviewer = PETSC_FALSE;

1001:   PetscFunctionBegin;
1003:   PetscAssertPointer(format, 2);
1004:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1005:   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
1006:   PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");

1008:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1009:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

1011:   if (vascii->bviewer) {
1012:     hasbviewer = PETSC_TRUE;
1013:     if (rank == 0) {
1014:       vascii = (PetscViewer_ASCII *)vascii->bviewer->data;
1015:       PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1016:       PetscCallMPI(MPI_Comm_rank(comm, &rank));
1017:     }
1018:   }

1020:   fp = vascii->fd;

1022:   if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */
1023:     va_list Argp;
1024:     /* flush my own messages that I may have queued up */
1025:     PrintfQueue next = vascii->petsc_printfqueuebase, previous;
1026:     PetscInt    i;
1027:     for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
1028:       PetscCall(PetscFPrintf(comm, fp, "%s", next->string));
1029:       previous = next;
1030:       next     = next->next;
1031:       PetscCall(PetscFree(previous->string));
1032:       PetscCall(PetscFree(previous));
1033:     }
1034:     vascii->petsc_printfqueue       = NULL;
1035:     vascii->petsc_printfqueuelength = 0;

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

1039:     va_start(Argp, format);
1040:     PetscCall((*PetscVFPrintf)(fp, format, Argp));
1041:     va_end(Argp);
1042:     PetscCall(PetscFFlush(fp));
1043:     if (petsc_history) {
1044:       va_start(Argp, format);
1045:       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1046:       va_end(Argp);
1047:       PetscCall(PetscFFlush(petsc_history));
1048:     }
1049:     va_end(Argp);
1050:   } else { /* other processors add to queue */
1051:     char       *string;
1052:     va_list     Argp;
1053:     size_t      fullLength;
1054:     PrintfQueue next;

1056:     PetscCall(PetscNew(&next));
1057:     if (vascii->petsc_printfqueue) {
1058:       vascii->petsc_printfqueue->next = next;
1059:       vascii->petsc_printfqueue       = next;
1060:     } else {
1061:       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1062:     }
1063:     vascii->petsc_printfqueuelength++;
1064:     next->size = QUEUESTRINGSIZE;
1065:     PetscCall(PetscCalloc1(next->size, &next->string));
1066:     string = next->string;
1067:     tab *= 2;
1068:     while (tab--) *string++ = ' ';
1069:     va_start(Argp, format);
1070:     PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
1071:     va_end(Argp);
1072:     if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
1073:       PetscCall(PetscFree(next->string));
1074:       next->size = fullLength + 2 * vascii->tab;
1075:       PetscCall(PetscCalloc1(next->size, &next->string));
1076:       string = next->string;
1077:       tab    = 2 * vascii->tab;
1078:       while (tab--) *string++ = ' ';
1079:       va_start(Argp, format);
1080:       PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
1081:       va_end(Argp);
1082:     }
1083:   }
1084:   PetscFunctionReturn(PETSC_SUCCESS);
1085: }

1087: /*@C
1088:   PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file

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

1092:   Input Parameters:
1093: + viewer - the `PETSCVIEWERASCII` viewer
1094: . data   - location to write the data, treated as an array of type indicated by `datatype`
1095: . num    - number of items of data to read
1096: - dtype  - type of data to read

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

1101:   Level: beginner

1103: .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1104:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1105:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1106: @*/
1107: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1108: {
1109:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1110:   FILE              *fd     = vascii->fd;
1111:   PetscInt           i;
1112:   int                ret = 0;
1113:   PetscMPIInt        rank;

1115:   PetscFunctionBegin;
1117:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1118:   PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1119:   for (i = 0; i < num; i++) {
1120:     if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1121:     else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1122:     else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1123:     else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
1124:     else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1125:     else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1126:     else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1127:     else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1128: #if defined(PETSC_USE_REAL___FLOAT128)
1129:     else if (dtype == PETSC___FLOAT128) {
1130:       double tmp;
1131:       ret                     = fscanf(fd, "%lg", &tmp);
1132:       ((__float128 *)data)[i] = tmp;
1133:     }
1134: #endif
1135:     else
1136:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
1137:     PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1138:     if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
1139:   }
1140:   if (count) *count = i;
1141:   else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
1142:   PetscFunctionReturn(PETSC_SUCCESS);
1143: }