xref: /petsc/src/sys/classes/viewer/impls/ascii/filev.c (revision 377f809a66ddb103acb624d65d678901d378fe03)
1665c2dedSJed Brown #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h> /*I "petscviewer.h" I*/
25c6c1daeSBarry Smith 
35c6c1daeSBarry Smith #define QUEUESTRINGSIZE 8192
45c6c1daeSBarry Smith 
5d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer)
6d71ae5a4SJacob Faibussowitsch {
75c6c1daeSBarry Smith   PetscMPIInt        rank;
85c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
95c6c1daeSBarry Smith   int                err;
105c6c1daeSBarry Smith 
115c6c1daeSBarry Smith   PetscFunctionBegin;
1228b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
14dd400576SPatrick Sanan   if (rank == 0 && vascii->fd != stderr && vascii->fd != PETSC_STDOUT) {
155c6c1daeSBarry Smith     if (vascii->fd && vascii->closefile) {
165c6c1daeSBarry Smith       err = fclose(vascii->fd);
1728b400f6SJacob Faibussowitsch       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
185c6c1daeSBarry Smith     }
195c6c1daeSBarry Smith     if (vascii->storecompressed) {
205c6c1daeSBarry Smith       char  par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN];
215c6c1daeSBarry Smith       FILE *fp;
229566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(par, "gzip ", sizeof(par)));
239566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(par, vascii->filename, sizeof(par)));
245c6c1daeSBarry Smith #if defined(PETSC_HAVE_POPEN)
259566063dSJacob Faibussowitsch       PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp));
2600045ab3SPierre Jolivet       PetscCheck(!fgets(buf, 1024, fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from compression command %s %s", par, buf);
279566063dSJacob Faibussowitsch       PetscCall(PetscPClose(PETSC_COMM_SELF, fp));
285c6c1daeSBarry Smith #else
295c6c1daeSBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
305c6c1daeSBarry Smith #endif
315c6c1daeSBarry Smith     }
325c6c1daeSBarry Smith   }
339566063dSJacob Faibussowitsch   PetscCall(PetscFree(vascii->filename));
343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
355c6c1daeSBarry Smith }
365c6c1daeSBarry Smith 
375c6c1daeSBarry Smith /* ----------------------------------------------------------------------*/
3834e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
39d71ae5a4SJacob Faibussowitsch {
405c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
415c6c1daeSBarry Smith   PetscViewerLink   *vlink;
425c6c1daeSBarry Smith   PetscBool          flg;
435c6c1daeSBarry Smith 
445c6c1daeSBarry Smith   PetscFunctionBegin;
4528b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
469566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileClose_ASCII(viewer));
479566063dSJacob Faibussowitsch   PetscCall(PetscFree(vascii));
485c6c1daeSBarry Smith 
495c6c1daeSBarry Smith   /* remove the viewer from the list in the MPI Communicator */
5048a46eb9SPierre Jolivet   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0));
515c6c1daeSBarry Smith 
529566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
535c6c1daeSBarry Smith   if (flg) {
545c6c1daeSBarry Smith     if (vlink && vlink->viewer == viewer) {
55e5840a18SBarry Smith       if (vlink->next) {
569566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next));
57e5840a18SBarry Smith       } else {
589566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval));
59e5840a18SBarry Smith       }
609566063dSJacob Faibussowitsch       PetscCall(PetscFree(vlink));
615c6c1daeSBarry Smith     } else {
625c6c1daeSBarry Smith       while (vlink && vlink->next) {
635c6c1daeSBarry Smith         if (vlink->next->viewer == viewer) {
645c6c1daeSBarry Smith           PetscViewerLink *nv = vlink->next;
655c6c1daeSBarry Smith           vlink->next         = vlink->next->next;
669566063dSJacob Faibussowitsch           PetscCall(PetscFree(nv));
675c6c1daeSBarry Smith         }
685c6c1daeSBarry Smith         vlink = vlink->next;
695c6c1daeSBarry Smith       }
705c6c1daeSBarry Smith     }
715c6c1daeSBarry Smith   }
72aa139df6SJed Brown 
73aa139df6SJed Brown   if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
74aa139df6SJed Brown     PetscViewer aviewer;
759566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
7648a46eb9SPierre Jolivet     if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval));
77aa139df6SJed Brown   }
78aa139df6SJed Brown   if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
79aa139df6SJed Brown     PetscViewer aviewer;
809566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
8148a46eb9SPierre Jolivet     if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval));
82aa139df6SJed Brown   }
832e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
842e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
852e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
862e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
885c6c1daeSBarry Smith }
895c6c1daeSBarry Smith 
9034e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
91d71ae5a4SJacob Faibussowitsch {
925c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
935fd66863SKarl Rupp 
945c6c1daeSBarry Smith   PetscFunctionBegin;
959566063dSJacob Faibussowitsch   PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer));
963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
975c6c1daeSBarry Smith }
985c6c1daeSBarry Smith 
9934e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
100d71ae5a4SJacob Faibussowitsch {
1015c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
102559f443fSBarry Smith   MPI_Comm           comm;
103559f443fSBarry Smith   PetscMPIInt        rank, size;
104559f443fSBarry Smith   FILE              *fd = vascii->fd;
1055c6c1daeSBarry Smith 
1065c6c1daeSBarry Smith   PetscFunctionBegin;
10728b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
1089566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1099566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
111559f443fSBarry Smith 
112c69effb2SJacob Faibussowitsch   if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd));
1135c6c1daeSBarry Smith 
1145c6c1daeSBarry Smith   if (vascii->allowsynchronized) {
115559f443fSBarry Smith     PetscMPIInt tag, i, j, n = 0, dummy = 0;
116559f443fSBarry Smith     char       *message;
117559f443fSBarry Smith     MPI_Status  status;
118559f443fSBarry Smith 
1199566063dSJacob Faibussowitsch     PetscCall(PetscCommDuplicate(comm, &comm, &tag));
120559f443fSBarry Smith 
121559f443fSBarry Smith     /* First processor waits for messages from all other processors */
122dd400576SPatrick Sanan     if (rank == 0) {
123559f443fSBarry Smith       /* flush my own messages that I may have queued up */
124559f443fSBarry Smith       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
125559f443fSBarry Smith       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
126559f443fSBarry Smith         if (!vascii->bviewer) {
1279566063dSJacob Faibussowitsch           PetscCall(PetscFPrintf(comm, fd, "%s", next->string));
128559f443fSBarry Smith         } else {
1299566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string));
130559f443fSBarry Smith         }
131559f443fSBarry Smith         previous = next;
132559f443fSBarry Smith         next     = next->next;
1339566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous->string));
1349566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous));
135559f443fSBarry Smith       }
13602c9f0b5SLisandro Dalcin       vascii->petsc_printfqueue       = NULL;
137559f443fSBarry Smith       vascii->petsc_printfqueuelength = 0;
138559f443fSBarry Smith       for (i = 1; i < size; i++) {
139559f443fSBarry Smith         /* to prevent a flood of messages to process zero, request each message separately */
1409566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
1419566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
142559f443fSBarry Smith         for (j = 0; j < n; j++) {
143559f443fSBarry Smith           PetscMPIInt size = 0;
144559f443fSBarry Smith 
1459566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
1469566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &message));
1479566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
148559f443fSBarry Smith           if (!vascii->bviewer) {
1499566063dSJacob Faibussowitsch             PetscCall(PetscFPrintf(comm, fd, "%s", message));
150559f443fSBarry Smith           } else {
1519566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message));
152559f443fSBarry Smith           }
1539566063dSJacob Faibussowitsch           PetscCall(PetscFree(message));
154559f443fSBarry Smith         }
155559f443fSBarry Smith       }
156559f443fSBarry Smith     } else { /* other processors send queue to processor 0 */
157559f443fSBarry Smith       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
158559f443fSBarry Smith 
1599566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
1609566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
161559f443fSBarry Smith       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
1629566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
1639566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
164559f443fSBarry Smith         previous = next;
165559f443fSBarry Smith         next     = next->next;
1669566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous->string));
1679566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous));
168559f443fSBarry Smith       }
16902c9f0b5SLisandro Dalcin       vascii->petsc_printfqueue       = NULL;
170559f443fSBarry Smith       vascii->petsc_printfqueuelength = 0;
171559f443fSBarry Smith     }
1729566063dSJacob Faibussowitsch     PetscCall(PetscCommDestroy(&comm));
1735c6c1daeSBarry Smith   }
1743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1755c6c1daeSBarry Smith }
1765c6c1daeSBarry Smith 
1775c6c1daeSBarry Smith /*@C
178811af0c4SBarry Smith   PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`.
1795c6c1daeSBarry Smith 
18035cb6cd3SPierre Jolivet   Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer; No Fortran Support
1815c6c1daeSBarry Smith 
182f8859db6SBarry Smith   Input Parameter:
1833f423023SBarry Smith . viewer - `PetscViewer` context, obtained from `PetscViewerASCIIOpen()`
184f8859db6SBarry Smith 
185f8859db6SBarry Smith   Output Parameter:
186f8859db6SBarry Smith . fd - file pointer
187f8859db6SBarry Smith 
1885c6c1daeSBarry Smith   Level: intermediate
1895c6c1daeSBarry Smith 
190811af0c4SBarry Smith   Note:
191c410d8ccSBarry Smith   For the standard `PETSCVIEWERASCII` the value is valid only on MPI rank 0 of the viewer
192811af0c4SBarry Smith 
1933f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`,
1943f423023SBarry Smith           `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
1955c6c1daeSBarry Smith @*/
196d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
197d71ae5a4SJacob Faibussowitsch {
1985c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1995c6c1daeSBarry Smith 
2005c6c1daeSBarry Smith   PetscFunctionBegin;
201c621c6acSBarry Smith   PetscCheck(!vascii->fileunit, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot request file pointer for viewers that use Fortran files");
2025c6c1daeSBarry Smith   *fd = vascii->fd;
2033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2045c6c1daeSBarry Smith }
2055c6c1daeSBarry Smith 
20634e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
207d71ae5a4SJacob Faibussowitsch {
2085c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
2095c6c1daeSBarry Smith 
2105c6c1daeSBarry Smith   PetscFunctionBegin;
2115c6c1daeSBarry Smith   *mode = vascii->mode;
2123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2135c6c1daeSBarry Smith }
2145c6c1daeSBarry Smith 
21534e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
216d71ae5a4SJacob Faibussowitsch {
2175c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
2185c6c1daeSBarry Smith 
2195c6c1daeSBarry Smith   PetscFunctionBegin;
2205c6c1daeSBarry Smith   vascii->mode = mode;
2213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2225c6c1daeSBarry Smith }
2235c6c1daeSBarry Smith 
2245c6c1daeSBarry Smith /*
2255c6c1daeSBarry Smith    If petsc_history is on, then all Petsc*Printf() results are saved
2265c6c1daeSBarry Smith    if the appropriate (usually .petschistory) file.
2275c6c1daeSBarry Smith */
22895c0884eSLisandro Dalcin PETSC_INTERN FILE *petsc_history;
2295c6c1daeSBarry Smith 
2305c6c1daeSBarry Smith /*@
2313f423023SBarry Smith   PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times before printing
2325c6c1daeSBarry Smith 
233cf53795eSBarry Smith   Not Collective, but only first processor in set has any effect; No Fortran Support
2345c6c1daeSBarry Smith 
2355c6c1daeSBarry Smith   Input Parameters:
236811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
2375c6c1daeSBarry Smith - tabs   - number of tabs
2385c6c1daeSBarry Smith 
2395c6c1daeSBarry Smith   Level: developer
2405c6c1daeSBarry Smith 
2413f423023SBarry Smith   Note:
2423f423023SBarry Smith   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
2433f423023SBarry Smith 
2443f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
2453f423023SBarry Smith           `PetscViewerASCIIGetTab()`,
246db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
2473f423023SBarry Smith           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
2483f423023SBarry Smith           `PetscViewerASCIIPushTab()`
2495c6c1daeSBarry Smith @*/
250d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
251d71ae5a4SJacob Faibussowitsch {
2525c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
2535c6c1daeSBarry Smith   PetscBool          iascii;
2545c6c1daeSBarry Smith 
2555c6c1daeSBarry Smith   PetscFunctionBegin;
2565c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
258a297a907SKarl Rupp   if (iascii) ascii->tab = tabs;
2593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2605c6c1daeSBarry Smith }
2615c6c1daeSBarry Smith 
2625c6c1daeSBarry Smith /*@
263811af0c4SBarry Smith   PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.
2645c6c1daeSBarry Smith 
265cf53795eSBarry Smith   Not Collective, meaningful on first processor only; No Fortran Support
2665c6c1daeSBarry Smith 
26720f4b53cSBarry Smith   Input Parameter:
268811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
269a2b725a8SWilliam Gropp 
27020f4b53cSBarry Smith   Output Parameter:
2715c6c1daeSBarry Smith . tabs - number of tabs
2725c6c1daeSBarry Smith 
2735c6c1daeSBarry Smith   Level: developer
2745c6c1daeSBarry Smith 
2753f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
2763f423023SBarry Smith           `PetscViewerASCIISetTab()`,
277db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
278db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
2795c6c1daeSBarry Smith @*/
280d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
281d71ae5a4SJacob Faibussowitsch {
2825c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
2835c6c1daeSBarry Smith   PetscBool          iascii;
2845c6c1daeSBarry Smith 
2855c6c1daeSBarry Smith   PetscFunctionBegin;
2865c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2879566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
288a297a907SKarl Rupp   if (iascii && tabs) *tabs = ascii->tab;
2893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2905c6c1daeSBarry Smith }
2915c6c1daeSBarry Smith 
2925c6c1daeSBarry Smith /*@
2933f423023SBarry Smith   PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing
2945c6c1daeSBarry Smith 
295cf53795eSBarry Smith   Not Collective, but only first processor in set has any effect; No Fortran Support
2965c6c1daeSBarry Smith 
2975c6c1daeSBarry Smith   Input Parameters:
298811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
2995c6c1daeSBarry Smith - tabs   - number of tabs
3005c6c1daeSBarry Smith 
3015c6c1daeSBarry Smith   Level: developer
3025c6c1daeSBarry Smith 
3033f423023SBarry Smith   Note:
3043f423023SBarry Smith   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
3053f423023SBarry Smith 
3063f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
307db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
308db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
3095c6c1daeSBarry Smith @*/
310d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
311d71ae5a4SJacob Faibussowitsch {
3125c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3135c6c1daeSBarry Smith   PetscBool          iascii;
3145c6c1daeSBarry Smith 
3155c6c1daeSBarry Smith   PetscFunctionBegin;
3165c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
3179566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
318a297a907SKarl Rupp   if (iascii) ascii->tab += tabs;
3193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3205c6c1daeSBarry Smith }
3215c6c1daeSBarry Smith 
3225c6c1daeSBarry Smith /*@
3233f423023SBarry Smith   PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing
3245c6c1daeSBarry Smith 
325cf53795eSBarry Smith   Not Collective, but only first processor in set has any effect; No Fortran Support
3265c6c1daeSBarry Smith 
3275c6c1daeSBarry Smith   Input Parameters:
328811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
3295c6c1daeSBarry Smith - tabs   - number of tabs
3305c6c1daeSBarry Smith 
3315c6c1daeSBarry Smith   Level: developer
3325c6c1daeSBarry Smith 
3333f423023SBarry Smith   Note:
3343f423023SBarry Smith   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
3353f423023SBarry Smith 
3363f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
337db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
3383f423023SBarry Smith           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
3393f423023SBarry Smith           `PetscViewerASCIIPushTab()`
3405c6c1daeSBarry Smith @*/
341d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
342d71ae5a4SJacob Faibussowitsch {
3435c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3445c6c1daeSBarry Smith   PetscBool          iascii;
3455c6c1daeSBarry Smith 
3465c6c1daeSBarry Smith   PetscFunctionBegin;
3475c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
3489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
349a297a907SKarl Rupp   if (iascii) ascii->tab -= tabs;
3503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3515c6c1daeSBarry Smith }
3525c6c1daeSBarry Smith 
3535c6c1daeSBarry Smith /*@C
354811af0c4SBarry Smith   PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer
3555c6c1daeSBarry Smith 
356c3339decSBarry Smith   Collective
3575c6c1daeSBarry Smith 
35820f4b53cSBarry Smith   Input Parameter:
359811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
3605c6c1daeSBarry Smith 
3615c6c1daeSBarry Smith   Level: intermediate
3625c6c1daeSBarry Smith 
363811af0c4SBarry Smith   Note:
364811af0c4SBarry Smith   See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
3655c6c1daeSBarry Smith 
366d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
367db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
368db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
3695c6c1daeSBarry Smith @*/
370d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
371d71ae5a4SJacob Faibussowitsch {
3725c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3735c6c1daeSBarry Smith   PetscBool          iascii;
3745c6c1daeSBarry Smith 
3755c6c1daeSBarry Smith   PetscFunctionBegin;
3765c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
37728b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
3789566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
3791575c14dSBarry Smith   if (iascii) ascii->allowsynchronized++;
3803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3811575c14dSBarry Smith }
3821575c14dSBarry Smith 
3831575c14dSBarry Smith /*@C
384811af0c4SBarry Smith   PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer
3851575c14dSBarry Smith 
386c3339decSBarry Smith   Collective
3871575c14dSBarry Smith 
38820f4b53cSBarry Smith   Input Parameter:
389811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
3901575c14dSBarry Smith 
3911575c14dSBarry Smith   Level: intermediate
3921575c14dSBarry Smith 
393811af0c4SBarry Smith   Note:
394811af0c4SBarry Smith   See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
3951575c14dSBarry Smith 
396d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
397db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
398db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
3991575c14dSBarry Smith @*/
400d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
401d71ae5a4SJacob Faibussowitsch {
4021575c14dSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4031575c14dSBarry Smith   PetscBool          iascii;
4041575c14dSBarry Smith 
4051575c14dSBarry Smith   PetscFunctionBegin;
4061575c14dSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
40728b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
4089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4091575c14dSBarry Smith   if (iascii) {
4101575c14dSBarry Smith     ascii->allowsynchronized--;
41108401ef6SPierre Jolivet     PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()");
4121575c14dSBarry Smith   }
4133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4145c6c1daeSBarry Smith }
4155c6c1daeSBarry Smith 
4161c297824SMatthew G. Knepley /*@C
417811af0c4SBarry Smith   PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
4185c6c1daeSBarry Smith   lines are tabbed.
4195c6c1daeSBarry Smith 
420c410d8ccSBarry Smith   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
4215c6c1daeSBarry Smith 
42220f4b53cSBarry Smith   Input Parameter:
423811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
4245c6c1daeSBarry Smith 
4255c6c1daeSBarry Smith   Level: developer
4265c6c1daeSBarry Smith 
427d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
428db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
429db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
4305c6c1daeSBarry Smith @*/
431d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
432d71ae5a4SJacob Faibussowitsch {
4335c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4345c6c1daeSBarry Smith   PetscBool          iascii;
4355c6c1daeSBarry Smith 
4365c6c1daeSBarry Smith   PetscFunctionBegin;
4375c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
4389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
439a297a907SKarl Rupp   if (iascii) ascii->tab++;
4403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4415c6c1daeSBarry Smith }
4425c6c1daeSBarry Smith 
4431c297824SMatthew G. Knepley /*@C
4443f423023SBarry Smith   PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by
4453f423023SBarry Smith   `PetscViewerASCIIPushTab()`
4465c6c1daeSBarry Smith 
447c410d8ccSBarry Smith   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
4485c6c1daeSBarry Smith 
44920f4b53cSBarry Smith   Input Parameter:
450811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
4515c6c1daeSBarry Smith 
4525c6c1daeSBarry Smith   Level: developer
4535c6c1daeSBarry Smith 
454d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
455db781477SPatrick Sanan           `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
456db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
4575c6c1daeSBarry Smith @*/
458d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
459d71ae5a4SJacob Faibussowitsch {
4605c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4615c6c1daeSBarry Smith   PetscBool          iascii;
4625c6c1daeSBarry Smith 
4635c6c1daeSBarry Smith   PetscFunctionBegin;
4645c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
4659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4665c6c1daeSBarry Smith   if (iascii) {
46708401ef6SPierre Jolivet     PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed");
4685c6c1daeSBarry Smith     ascii->tab--;
4695c6c1daeSBarry Smith   }
4703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4715c6c1daeSBarry Smith }
4725c6c1daeSBarry Smith 
4735c6c1daeSBarry Smith /*@
474c410d8ccSBarry Smith   PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer`
4755c6c1daeSBarry Smith 
476c410d8ccSBarry Smith   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
4775c6c1daeSBarry Smith 
4785c6c1daeSBarry Smith   Input Parameters:
479811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
480811af0c4SBarry Smith - flg    - `PETSC_TRUE` or `PETSC_FALSE`
4815c6c1daeSBarry Smith 
4825c6c1daeSBarry Smith   Level: developer
4835c6c1daeSBarry Smith 
484d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
485db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
486db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
4875c6c1daeSBarry Smith @*/
488d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
489d71ae5a4SJacob Faibussowitsch {
4905c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4915c6c1daeSBarry Smith   PetscBool          iascii;
4925c6c1daeSBarry Smith 
4935c6c1daeSBarry Smith   PetscFunctionBegin;
4945c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
4959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4965c6c1daeSBarry Smith   if (iascii) {
497a297a907SKarl Rupp     if (flg) ascii->tab = ascii->tab_store;
498a297a907SKarl Rupp     else {
4995c6c1daeSBarry Smith       ascii->tab_store = ascii->tab;
5005c6c1daeSBarry Smith       ascii->tab       = 0;
5015c6c1daeSBarry Smith     }
5025c6c1daeSBarry Smith   }
5033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5045c6c1daeSBarry Smith }
5055c6c1daeSBarry Smith 
506e4096674SBarry Smith #if defined(PETSC_USE_FORTRAN_BINDINGS)
507e4096674SBarry Smith 
508e4096674SBarry Smith   #if defined(PETSC_HAVE_FORTRAN_CAPS)
509e4096674SBarry Smith     #define petscviewerasciiopenwithfileunit_ PETSCVIEWERASCIIOPENWITHFILEUNIT
51057b1f488SBarry Smith     #define petscviewerasciisetfileunit_      PETSCVIEWERASCIISETFILEUNIT
51157b1f488SBarry Smith     #define petscviewerasciiworldsetfileunit_ PETSCVIEWERASCIIWORLDSETFILEUNIT
512e4096674SBarry Smith     #define petscfortranprinttounit_          PETSCFORTRANPRINTTOUNIT
513e4096674SBarry Smith   #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
514e4096674SBarry Smith     #define petscviewerasciiopenwithfileunit_ petscviewerasciiopenwithfileunit
515e4096674SBarry Smith     #define petscviewerasciisetfileunit_      petscviewerasciisetfileunit
51657b1f488SBarry Smith     #define petscviewerasciiworldsetfileunit_ petscviewerasciiworldsetfileunit
517e4096674SBarry Smith     #define petscfortranprinttounit_          petscfortranprinttounit
518e4096674SBarry Smith   #endif
519e4096674SBarry Smith 
520e4096674SBarry Smith   #if defined(__cplusplus)
521e4096674SBarry Smith extern "C" void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
522e4096674SBarry Smith   #else
523e4096674SBarry Smith extern void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
524e4096674SBarry Smith   #endif
525e4096674SBarry Smith 
526e4096674SBarry Smith   #define PETSCDEFAULTBUFFERSIZE 8 * 1024
527e4096674SBarry Smith 
52857b1f488SBarry Smith static PetscInt PETSC_VIEWER_ASCII_WORLD_fileunit = 0;
52957b1f488SBarry Smith 
53057b1f488SBarry Smith // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
53157b1f488SBarry Smith /*MC
53257b1f488SBarry Smith   PetscViewerASCIIWORLDSetFileUnit - sets `PETSC_VIEWER_STDOUT_WORLD` to write to a Fortran IO unit
53357b1f488SBarry Smith 
53457b1f488SBarry Smith   Synopsis:
53557b1f488SBarry Smith   #include <petscviewer.h>
53657b1f488SBarry Smith   void PetscViewerASCIIWORLDSetFileUnit(PetscInt unit, PetscErrorCode ierr)
53757b1f488SBarry Smith 
53857b1f488SBarry Smith   Input Parameter:
53957b1f488SBarry Smith . unit - the unit number
54057b1f488SBarry Smith 
54157b1f488SBarry Smith   Output Parameter:
54257b1f488SBarry Smith . ierr - the error code
54357b1f488SBarry Smith 
54457b1f488SBarry Smith   Level: intermediate
54557b1f488SBarry Smith 
54657b1f488SBarry Smith   Notes:
54757b1f488SBarry Smith   Must be called before `PetscInitialize()`
54857b1f488SBarry Smith 
5491d031f67SBarry Smith   This may not work currently with some viewers that (improperly) use the `fd` directly instead of `PetscViewerASCIIPrintf()`
55057b1f488SBarry Smith 
55157b1f488SBarry Smith   With this option, for example, `-log_options` results will be saved to the Fortran file
55257b1f488SBarry Smith 
5531d031f67SBarry Smith   Any process may call this but only the unit passed on the first process is used
55457b1f488SBarry Smith 
55557b1f488SBarry Smith   Fortran Note:
55657b1f488SBarry Smith   Only for Fortran
55757b1f488SBarry Smith 
55857b1f488SBarry Smith   Developer Note:
55957b1f488SBarry Smith   `PetscViewerASCIIWORLDSetFilename()` could be added in the future
56057b1f488SBarry Smith 
56157b1f488SBarry Smith .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIWORLDSetFileUnit()`
56257b1f488SBarry Smith M*/
56357b1f488SBarry Smith PETSC_EXTERN void petscviewerasciiworldsetfileunit_(PetscInt *unit, PetscErrorCode *ierr)
56457b1f488SBarry Smith {
56557b1f488SBarry Smith   PETSC_VIEWER_ASCII_WORLD_fileunit = *unit;
56657b1f488SBarry Smith }
56757b1f488SBarry Smith 
56857b1f488SBarry Smith   #include <petsc/private/fortranimpl.h>
56957b1f488SBarry Smith 
57010450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
571489d2c6aSPierre Jolivet /*MC
572baca6076SPierre Jolivet   PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` to write to a Fortran IO unit
573e4096674SBarry Smith 
57410450e9eSJacob Faibussowitsch   Synopsis:
57510450e9eSJacob Faibussowitsch   #include <petscviewer.h>
576e4096674SBarry Smith   void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr)
577e4096674SBarry Smith 
578e4096674SBarry Smith   Input Parameters:
579e4096674SBarry Smith + lab  - the viewer
580e4096674SBarry Smith - unit - the unit number
581e4096674SBarry Smith 
582e4096674SBarry Smith   Output Parameter:
583e4096674SBarry Smith . ierr - the error code
584e4096674SBarry Smith 
58510450e9eSJacob Faibussowitsch   Level: intermediate
58610450e9eSJacob Faibussowitsch 
587e4096674SBarry Smith   Note:
588e4096674SBarry Smith   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
589e4096674SBarry Smith 
590aec76313SJacob Faibussowitsch   Fortran Notes:
591e4096674SBarry Smith   Only for Fortran, use  `PetscViewerASCIISetFILE()` for C
592e4096674SBarry Smith 
59357b1f488SBarry Smith .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIWORLDSetFileUnit()`
594489d2c6aSPierre Jolivet M*/
595e4096674SBarry Smith PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, PetscInt *unit, PetscErrorCode *ierr)
596e4096674SBarry Smith {
59757b1f488SBarry Smith   PetscViewer_ASCII *vascii;
59857b1f488SBarry Smith   PetscViewer        v;
599e4096674SBarry Smith 
60057b1f488SBarry Smith   PetscPatchDefaultViewers_Fortran(lab, v);
60157b1f488SBarry Smith   vascii = (PetscViewer_ASCII *)v->data;
602e4096674SBarry Smith   if (vascii->mode == FILE_MODE_READ) {
603e4096674SBarry Smith     *ierr = PETSC_ERR_ARG_WRONGSTATE;
604e4096674SBarry Smith     return;
605e4096674SBarry Smith   }
606e4096674SBarry Smith   vascii->fileunit = *unit;
607e4096674SBarry Smith }
608e4096674SBarry Smith 
60910450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
610489d2c6aSPierre Jolivet /*MC
611baca6076SPierre Jolivet   PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit
612e4096674SBarry Smith 
61310450e9eSJacob Faibussowitsch   Synopsis:
61410450e9eSJacob Faibussowitsch   #include <petscviewer.h>
615e4096674SBarry Smith   void PetscViewerASCIIOpenWithFileUnit(MPI_Comm comm, PetscInt unit, PetscViewer viewer, PetscErrorCode ierr)
616e4096674SBarry Smith 
617e4096674SBarry Smith   Input Parameters:
618e4096674SBarry Smith + comm - the `MPI_Comm` to share the viewer
619e4096674SBarry Smith - unit - the unit number
620e4096674SBarry Smith 
621e4096674SBarry Smith   Output Parameters:
622e4096674SBarry Smith + lab  - the viewer
623e4096674SBarry Smith - ierr - the error code
624e4096674SBarry Smith 
62510450e9eSJacob Faibussowitsch   Level: intermediate
62610450e9eSJacob Faibussowitsch 
627e4096674SBarry Smith   Note:
628e4096674SBarry Smith   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
629e4096674SBarry Smith 
630aec76313SJacob Faibussowitsch   Fortran Notes:
631e4096674SBarry Smith   Only for Fortran, use  `PetscViewerASCIIOpenWithFILE()` for C
632e4096674SBarry Smith 
633e4096674SBarry Smith .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()`
634489d2c6aSPierre Jolivet M*/
635e4096674SBarry Smith PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Comm *comm, PetscInt *unit, PetscViewer *lab, PetscErrorCode *ierr)
636e4096674SBarry Smith {
637e4096674SBarry Smith   *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab);
638e4096674SBarry Smith   if (*ierr) return;
639e4096674SBarry Smith   *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII);
640e4096674SBarry Smith   if (*ierr) return;
641e4096674SBarry Smith   *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE);
642e4096674SBarry Smith   if (*ierr) return;
643e4096674SBarry Smith   petscviewerasciisetfileunit_(lab, unit, ierr);
644e4096674SBarry Smith }
645e4096674SBarry Smith 
646e4096674SBarry Smith static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
647e4096674SBarry Smith {
648e4096674SBarry Smith   PetscErrorCode ierr;
649e4096674SBarry Smith   char           str[PETSCDEFAULTBUFFERSIZE];
650e4096674SBarry Smith   size_t         len;
651e4096674SBarry Smith 
652e4096674SBarry Smith   PetscFunctionBegin;
653e4096674SBarry Smith   PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp));
654e4096674SBarry Smith   PetscCall(PetscStrlen(str, &len));
655e4096674SBarry Smith   petscfortranprinttounit_(&unit, str, &ierr, (int)len);
656e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
657e4096674SBarry Smith }
658e4096674SBarry Smith 
659e4096674SBarry Smith static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
660e4096674SBarry Smith {
661e4096674SBarry Smith   PetscErrorCode ierr;
662e4096674SBarry Smith   size_t         len;
663e4096674SBarry Smith 
664e4096674SBarry Smith   PetscFunctionBegin;
665e4096674SBarry Smith   PetscCall(PetscStrlen(str, &len));
666e4096674SBarry Smith   petscfortranprinttounit_(&unit, str, &ierr, (int)len);
667e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
668e4096674SBarry Smith }
669e4096674SBarry Smith 
670e4096674SBarry Smith #else
671e4096674SBarry Smith 
672e4096674SBarry Smith /* these will never be used; but are needed to link with */
673e4096674SBarry Smith static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
674e4096674SBarry Smith {
675e4096674SBarry Smith   PetscFunctionBegin;
676e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
677e4096674SBarry Smith }
678e4096674SBarry Smith 
679e4096674SBarry Smith static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
680e4096674SBarry Smith {
681e4096674SBarry Smith   PetscFunctionBegin;
682e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
683e4096674SBarry Smith }
684e4096674SBarry Smith #endif
685e4096674SBarry Smith 
68657b1f488SBarry Smith /*@
6871d031f67SBarry Smith   PetscViewerASCIIGetStdout - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processes
68857b1f488SBarry Smith   in a communicator. Error returning version of `PETSC_VIEWER_STDOUT_()`
68957b1f488SBarry Smith 
69057b1f488SBarry Smith   Collective
69157b1f488SBarry Smith 
69257b1f488SBarry Smith   Input Parameter:
69357b1f488SBarry Smith . comm - the MPI communicator to share the `PetscViewer`
69457b1f488SBarry Smith 
69557b1f488SBarry Smith   Output Parameter:
69657b1f488SBarry Smith . viewer - the viewer
69757b1f488SBarry Smith 
69857b1f488SBarry Smith   Level: beginner
69957b1f488SBarry Smith 
70057b1f488SBarry Smith   Note:
70157b1f488SBarry Smith   This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it
70257b1f488SBarry Smith 
70357b1f488SBarry Smith   Developer Note:
70457b1f488SBarry Smith   This should be used in all PETSc source code instead of `PETSC_VIEWER_STDOUT_()` since it allows error checking
70557b1f488SBarry Smith 
70657b1f488SBarry Smith .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
70757b1f488SBarry Smith           `PETSC_VIEWER_STDOUT_SELF`
70857b1f488SBarry Smith @*/
70957b1f488SBarry Smith PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm, PetscViewer *viewer)
71057b1f488SBarry Smith {
71157b1f488SBarry Smith   PetscBool flg;
71257b1f488SBarry Smith   MPI_Comm  ncomm;
71357b1f488SBarry Smith 
71457b1f488SBarry Smith   PetscFunctionBegin;
715*377f809aSBarry Smith   PetscAssertPointer(viewer, 2);
71657b1f488SBarry Smith   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout));
71757b1f488SBarry Smith   PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
71857b1f488SBarry Smith   if (Petsc_Viewer_Stdout_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Stdout_keyval, NULL));
71957b1f488SBarry Smith   PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, (PetscMPIInt *)&flg));
72057b1f488SBarry Smith   if (!flg) { /* PetscViewer not yet created */
72157b1f488SBarry Smith #if defined(PETSC_USE_FORTRAN_BINDINGS)
72257b1f488SBarry Smith     PetscMPIInt size, gsize;
72357b1f488SBarry Smith 
72457b1f488SBarry Smith     PetscCallMPI(MPI_Comm_size(comm, &size));
72557b1f488SBarry Smith     PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &gsize));
72657b1f488SBarry Smith     if (size == gsize) { PetscCallMPI(MPI_Bcast(&PETSC_VIEWER_ASCII_WORLD_fileunit, 1, MPIU_INT, 0, comm)); }
72757b1f488SBarry Smith     if (PETSC_VIEWER_ASCII_WORLD_fileunit) {
72857b1f488SBarry Smith       PetscErrorCode ierr;
72957b1f488SBarry Smith 
73057b1f488SBarry Smith       petscviewerasciiopenwithfileunit_(&ncomm, &PETSC_VIEWER_ASCII_WORLD_fileunit, viewer, &ierr);
73157b1f488SBarry Smith     } else
73257b1f488SBarry Smith #endif
73357b1f488SBarry Smith       PetscCall(PetscViewerASCIIOpen(ncomm, "stdout", viewer));
73457b1f488SBarry Smith     ((PetscObject)*viewer)->persistent = PETSC_TRUE;
73557b1f488SBarry Smith     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
73657b1f488SBarry Smith     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer));
73757b1f488SBarry Smith   }
73857b1f488SBarry Smith   PetscCall(PetscCommDestroy(&ncomm));
73957b1f488SBarry Smith   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout));
74057b1f488SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
74157b1f488SBarry Smith }
74257b1f488SBarry Smith 
7435c6c1daeSBarry Smith /*@C
7445c6c1daeSBarry Smith   PetscViewerASCIIPrintf - Prints to a file, only from the first
7453f423023SBarry Smith   processor in the `PetscViewer` of type `PETSCVIEWERASCII`
7465c6c1daeSBarry Smith 
747c410d8ccSBarry Smith   Not Collective, but only the first MPI rank in the viewer has any effect
7485c6c1daeSBarry Smith 
7495c6c1daeSBarry Smith   Input Parameters:
750811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
7515c6c1daeSBarry Smith - format - the usual printf() format string
7525c6c1daeSBarry Smith 
7535c6c1daeSBarry Smith   Level: developer
7545c6c1daeSBarry Smith 
755aec76313SJacob Faibussowitsch   Fortran Notes:
756c410d8ccSBarry Smith   The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran.
7575c6c1daeSBarry Smith   That is, you can only pass a single character string from Fortran.
7585c6c1daeSBarry Smith 
759d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
760db781477SPatrick Sanan           `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
761db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
7625c6c1daeSBarry Smith @*/
763d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
764d71ae5a4SJacob Faibussowitsch {
7655c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
7665c6c1daeSBarry Smith   PetscMPIInt        rank;
767fe8fb074SBarry Smith   PetscInt           tab = 0, intab = ascii->tab;
7685c6c1daeSBarry Smith   FILE              *fd = ascii->fd;
7693f08860eSBarry Smith   PetscBool          iascii;
7705c6c1daeSBarry Smith 
7715c6c1daeSBarry Smith   PetscFunctionBegin;
7725c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
77328b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
7744f572ea9SToby Isaac   PetscAssertPointer(format, 2);
7759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
77628b400f6SJacob Faibussowitsch   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
7779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
7783ba16761SJacob Faibussowitsch   if (rank) PetscFunctionReturn(PETSC_SUCCESS);
7793f08860eSBarry Smith 
7803f08860eSBarry Smith   if (ascii->bviewer) { /* pass string up to parent viewer */
7813f08860eSBarry Smith     char   *string;
7823f08860eSBarry Smith     va_list Argp;
7833f08860eSBarry Smith     size_t  fullLength;
7843f08860eSBarry Smith 
7859566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
786fe8fb074SBarry Smith     for (; tab < ascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; }
7873f08860eSBarry Smith     va_start(Argp, format);
788fe8fb074SBarry Smith     PetscCall(PetscVSNPrintf(string + 2 * intab, QUEUESTRINGSIZE - 2 * intab, format, &fullLength, Argp));
7893f08860eSBarry Smith     va_end(Argp);
790fe8fb074SBarry Smith     PetscCall(PetscViewerASCIISynchronizedPrintf(ascii->bviewer, "%s", string));
7919566063dSJacob Faibussowitsch     PetscCall(PetscFree(string));
7923f08860eSBarry Smith   } else { /* write directly to file */
7935c6c1daeSBarry Smith     va_list Argp;
794fe8fb074SBarry Smith 
795dd2fa690SBarry Smith     tab = intab;
796e4096674SBarry Smith     while (tab--) {
797e4096674SBarry Smith       if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "  "));
798e4096674SBarry Smith       else PetscCall(PetscFPrintfFortran(ascii->fileunit, "   "));
799e4096674SBarry Smith     }
8005c6c1daeSBarry Smith 
8015c6c1daeSBarry Smith     va_start(Argp, format);
802e4096674SBarry Smith     if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
803e4096674SBarry Smith     else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
804eae3dc7dSJacob Faibussowitsch     va_end(Argp);
805c69effb2SJacob Faibussowitsch     PetscCall(PetscFFlush(fd));
8065c6c1daeSBarry Smith   }
8073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8085c6c1daeSBarry Smith }
8095c6c1daeSBarry Smith 
8105c6c1daeSBarry Smith /*@C
811c410d8ccSBarry Smith   PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.
8125c6c1daeSBarry Smith 
813c3339decSBarry Smith   Collective
8145c6c1daeSBarry Smith 
8155c6c1daeSBarry Smith   Input Parameters:
8163f423023SBarry Smith + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
8175c6c1daeSBarry Smith - name   - the name of the file it should use
8185c6c1daeSBarry Smith 
8195c6c1daeSBarry Smith   Level: advanced
8205c6c1daeSBarry Smith 
821c410d8ccSBarry Smith   Note:
822c410d8ccSBarry Smith   This will have no effect on viewers that are not related to files
823c410d8ccSBarry Smith 
824d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
825db781477SPatrick Sanan           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
8265c6c1daeSBarry Smith @*/
827d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
828d71ae5a4SJacob Faibussowitsch {
829cc843e7aSLisandro Dalcin   char filename[PETSC_MAX_PATH_LEN];
8305c6c1daeSBarry Smith 
8315c6c1daeSBarry Smith   PetscFunctionBegin;
8325c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8334f572ea9SToby Isaac   PetscAssertPointer(name, 2);
8349566063dSJacob Faibussowitsch   PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
835cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
8363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8375c6c1daeSBarry Smith }
8385c6c1daeSBarry Smith 
8395c6c1daeSBarry Smith /*@C
840c410d8ccSBarry Smith   PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using
8415c6c1daeSBarry Smith 
8425c6c1daeSBarry Smith   Not Collective
8435c6c1daeSBarry Smith 
8445c6c1daeSBarry Smith   Input Parameter:
8453f423023SBarry Smith . viewer - the `PetscViewer`
8465c6c1daeSBarry Smith 
8475c6c1daeSBarry Smith   Output Parameter:
8485c6c1daeSBarry Smith . name - the name of the file it is using
8495c6c1daeSBarry Smith 
8505c6c1daeSBarry Smith   Level: advanced
8515c6c1daeSBarry Smith 
852c410d8ccSBarry Smith   Note:
853c410d8ccSBarry Smith   This will have no effect on viewers that are not related to files
854c410d8ccSBarry Smith 
855d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
8565c6c1daeSBarry Smith @*/
857d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
858d71ae5a4SJacob Faibussowitsch {
8595c6c1daeSBarry Smith   PetscFunctionBegin;
8605c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8614f572ea9SToby Isaac   PetscAssertPointer(name, 2);
862cac4c232SBarry Smith   PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
8633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8645c6c1daeSBarry Smith }
8655c6c1daeSBarry Smith 
86634e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
867d71ae5a4SJacob Faibussowitsch {
8685c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
8695c6c1daeSBarry Smith 
8705c6c1daeSBarry Smith   PetscFunctionBegin;
8715c6c1daeSBarry Smith   *name = vascii->filename;
8723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8735c6c1daeSBarry Smith }
8745c6c1daeSBarry Smith 
875bf31d2d3SBarry Smith #include <errno.h>
87634e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
877d71ae5a4SJacob Faibussowitsch {
8785c6c1daeSBarry Smith   size_t             len;
879bbcf679cSJacob Faibussowitsch   char               fname[PETSC_MAX_PATH_LEN], *gz = NULL;
8805c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
8815c6c1daeSBarry Smith   PetscBool          isstderr, isstdout;
8825c6c1daeSBarry Smith   PetscMPIInt        rank;
8835c6c1daeSBarry Smith 
8845c6c1daeSBarry Smith   PetscFunctionBegin;
8859566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileClose_ASCII(viewer));
8863ba16761SJacob Faibussowitsch   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
8879566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &vascii->filename));
8885c6c1daeSBarry Smith 
8895c6c1daeSBarry Smith   /* Is this file to be compressed */
8905c6c1daeSBarry Smith   vascii->storecompressed = PETSC_FALSE;
891a297a907SKarl Rupp 
8929566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
8935c6c1daeSBarry Smith   if (gz) {
8949566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(gz, &len));
8955c6c1daeSBarry Smith     if (len == 3) {
89608401ef6SPierre Jolivet       PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first");
8975c6c1daeSBarry Smith       *gz                     = 0;
8985c6c1daeSBarry Smith       vascii->storecompressed = PETSC_TRUE;
8995c6c1daeSBarry Smith     }
9005c6c1daeSBarry Smith   }
9019566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
902dd400576SPatrick Sanan   if (rank == 0) {
9039566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
9049566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
9055c6c1daeSBarry Smith     /* empty filename means stdout */
9065c6c1daeSBarry Smith     if (name[0] == 0) isstdout = PETSC_TRUE;
9075c6c1daeSBarry Smith     if (isstderr) vascii->fd = PETSC_STDERR;
9085c6c1daeSBarry Smith     else if (isstdout) vascii->fd = PETSC_STDOUT;
9095c6c1daeSBarry Smith     else {
9109566063dSJacob Faibussowitsch       PetscCall(PetscFixFilename(name, fname));
9115c6c1daeSBarry Smith       switch (vascii->mode) {
912d71ae5a4SJacob Faibussowitsch       case FILE_MODE_READ:
913d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "r");
914d71ae5a4SJacob Faibussowitsch         break;
915d71ae5a4SJacob Faibussowitsch       case FILE_MODE_WRITE:
916d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "w");
917d71ae5a4SJacob Faibussowitsch         break;
918d71ae5a4SJacob Faibussowitsch       case FILE_MODE_APPEND:
919d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "a");
920d71ae5a4SJacob Faibussowitsch         break;
9215c6c1daeSBarry Smith       case FILE_MODE_UPDATE:
9225c6c1daeSBarry Smith         vascii->fd = fopen(fname, "r+");
923a297a907SKarl Rupp         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
9245c6c1daeSBarry Smith         break;
9255c6c1daeSBarry Smith       case FILE_MODE_APPEND_UPDATE:
9265c6c1daeSBarry Smith         /* I really want a file which is opened at the end for updating,
9275c6c1daeSBarry Smith            not a+, which opens at the beginning, but makes writes at the end.
9285c6c1daeSBarry Smith         */
9295c6c1daeSBarry Smith         vascii->fd = fopen(fname, "r+");
930a297a907SKarl Rupp         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
9313ba16761SJacob Faibussowitsch         else {
9323ba16761SJacob Faibussowitsch           int ret = fseek(vascii->fd, 0, SEEK_END);
9333ba16761SJacob Faibussowitsch           PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
9343ba16761SJacob Faibussowitsch         }
9355c6c1daeSBarry Smith         break;
936d71ae5a4SJacob Faibussowitsch       default:
937d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
9385c6c1daeSBarry Smith       }
939bf31d2d3SBarry Smith       PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
9405c6c1daeSBarry Smith     }
9415c6c1daeSBarry Smith   }
9423ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
9433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9445c6c1daeSBarry Smith }
9455c6c1daeSBarry Smith 
94634e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
947d71ae5a4SJacob Faibussowitsch {
9485c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
9495c6c1daeSBarry Smith 
9505c6c1daeSBarry Smith   PetscFunctionBegin;
95128b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
952fe8fb074SBarry Smith   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
953e5afcf28SBarry Smith   /*
9549530cbd7SBarry Smith      The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
9559530cbd7SBarry Smith      because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
9569530cbd7SBarry Smith      (since the count never gets to zero) in some examples this displays information that otherwise would be lost
9579530cbd7SBarry Smith 
9589530cbd7SBarry Smith      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
9599530cbd7SBarry Smith      PCView_GASM().
960e5afcf28SBarry Smith   */
9619566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
962b4025f61SBarry Smith   PetscCall(PetscViewerFlush(viewer));
9639566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(subcomm, outviewer));
9649566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
9659566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
9665c6c1daeSBarry Smith   ovascii            = (PetscViewer_ASCII *)(*outviewer)->data;
9675c6c1daeSBarry Smith   ovascii->fd        = vascii->fd;
968ba5a0b41SBarry Smith   ovascii->closefile = PETSC_FALSE;
9695c6c1daeSBarry Smith 
9705c6c1daeSBarry Smith   vascii->sviewer                                      = *outviewer;
9715c6c1daeSBarry Smith   (*outviewer)->format                                 = viewer->format;
9725c6c1daeSBarry Smith   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
9733f08860eSBarry Smith   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
9743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9755c6c1daeSBarry Smith }
9765c6c1daeSBarry Smith 
97734e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
978d71ae5a4SJacob Faibussowitsch {
9795c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
9805c6c1daeSBarry Smith 
9815c6c1daeSBarry Smith   PetscFunctionBegin;
98228b400f6SJacob Faibussowitsch   PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
98308401ef6SPierre Jolivet   PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");
9845c6c1daeSBarry Smith 
9859566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
986e5afcf28SBarry Smith   ascii->sviewer             = NULL;
9875c6c1daeSBarry Smith   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
9889566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(outviewer));
989fe8fb074SBarry Smith   PetscCall(PetscViewerFlush(viewer));
9909566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
9913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9925c6c1daeSBarry Smith }
9935c6c1daeSBarry Smith 
99434e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
995d71ae5a4SJacob Faibussowitsch {
9962bf49c77SBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
9972bf49c77SBarry Smith 
9982bf49c77SBarry Smith   PetscFunctionBegin;
9991d031f67SBarry Smith   if (ascii->fileunit) PetscCall(PetscViewerASCIIPrintf(viewer, "Fortran FILE UNIT: %" PetscInt_FMT "\n", ascii->fileunit));
100057b1f488SBarry Smith   else if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
10013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10022bf49c77SBarry Smith }
10032bf49c77SBarry Smith 
10048556b5ebSBarry Smith /*MC
10058556b5ebSBarry Smith    PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file
10068556b5ebSBarry Smith 
1007811af0c4SBarry Smith   Level: beginner
1008811af0c4SBarry Smith 
1009d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1010db781477SPatrick Sanan           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
1011db781477SPatrick Sanan           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
10128556b5ebSBarry Smith M*/
1013d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
1014d71ae5a4SJacob Faibussowitsch {
10155c6c1daeSBarry Smith   PetscViewer_ASCII *vascii;
10165c6c1daeSBarry Smith 
10175c6c1daeSBarry Smith   PetscFunctionBegin;
10184dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&vascii));
10195c6c1daeSBarry Smith   viewer->data = (void *)vascii;
10205c6c1daeSBarry Smith 
10215c6c1daeSBarry Smith   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
10225c6c1daeSBarry Smith   viewer->ops->flush            = PetscViewerFlush_ASCII;
1023559f443fSBarry Smith   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
1024559f443fSBarry Smith   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
10252bf49c77SBarry Smith   viewer->ops->view             = PetscViewerView_ASCII;
10261d641e7bSMichael Lange   viewer->ops->read             = PetscViewerASCIIRead;
10275c6c1daeSBarry Smith 
10285c6c1daeSBarry Smith   /* defaults to stdout unless set with PetscViewerFileSetName() */
10295c6c1daeSBarry Smith   vascii->fd        = PETSC_STDOUT;
10305c6c1daeSBarry Smith   vascii->mode      = FILE_MODE_WRITE;
103102c9f0b5SLisandro Dalcin   vascii->bviewer   = NULL;
103202c9f0b5SLisandro Dalcin   vascii->subviewer = NULL;
103302c9f0b5SLisandro Dalcin   vascii->sviewer   = NULL;
10345c6c1daeSBarry Smith   vascii->tab       = 0;
10355c6c1daeSBarry Smith   vascii->tab_store = 0;
103602c9f0b5SLisandro Dalcin   vascii->filename  = NULL;
10375c6c1daeSBarry Smith   vascii->closefile = PETSC_TRUE;
10385c6c1daeSBarry Smith 
10399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
10409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
10419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
10429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
10433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10445c6c1daeSBarry Smith }
10455c6c1daeSBarry Smith 
10465c6c1daeSBarry Smith /*@C
1047c410d8ccSBarry Smith   PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
10485c6c1daeSBarry Smith   several processors.  Output of the first processor is followed by that of the
10495c6c1daeSBarry Smith   second, etc.
10505c6c1daeSBarry Smith 
1051c410d8ccSBarry Smith   Not Collective, must call collective `PetscViewerFlush()` to get the results flushed
10525c6c1daeSBarry Smith 
10535c6c1daeSBarry Smith   Input Parameters:
1054811af0c4SBarry Smith + viewer - the `PETSCVIEWERASCII` `PetscViewer`
10555c6c1daeSBarry Smith - format - the usual printf() format string
10565c6c1daeSBarry Smith 
10575c6c1daeSBarry Smith   Level: intermediate
10585c6c1daeSBarry Smith 
105995452b02SPatrick Sanan   Notes:
1060811af0c4SBarry Smith   You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
1061e6abc3ddSVáclav Hapla   Then you can do multiple independent calls to this routine.
1062811af0c4SBarry Smith 
1063811af0c4SBarry Smith   The actual synchronized print is then done using `PetscViewerFlush()`.
1064811af0c4SBarry Smith   `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
1065e6abc3ddSVáclav Hapla   to conclude the "synchronized session".
1066811af0c4SBarry Smith 
1067e6abc3ddSVáclav Hapla   So the typical calling sequence looks like
1068811af0c4SBarry Smith .vb
1069811af0c4SBarry Smith     PetscViewerASCIIPushSynchronized(viewer);
1070811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1071811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1072811af0c4SBarry Smith     ...
1073811af0c4SBarry Smith     PetscViewerFlush(viewer);
1074811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1075811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1076811af0c4SBarry Smith     ...
1077811af0c4SBarry Smith     PetscViewerFlush(viewer);
1078811af0c4SBarry Smith     PetscViewerASCIIPopSynchronized(viewer);
1079811af0c4SBarry Smith .ve
10805c6c1daeSBarry Smith 
1081aec76313SJacob Faibussowitsch   Fortran Notes:
10825c6c1daeSBarry Smith   Can only print a single character* string
10835c6c1daeSBarry Smith 
1084d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
1085db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
1086db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
10875c6c1daeSBarry Smith @*/
1088d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
1089d71ae5a4SJacob Faibussowitsch {
10905c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
10913f08860eSBarry Smith   PetscMPIInt        rank;
1092fe8fb074SBarry Smith   PetscInt           tab = 0;
10935c6c1daeSBarry Smith   MPI_Comm           comm;
1094fe8fb074SBarry Smith   PetscBool          iascii;
10955c6c1daeSBarry Smith 
10965c6c1daeSBarry Smith   PetscFunctionBegin;
10975c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
10984f572ea9SToby Isaac   PetscAssertPointer(format, 2);
10999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
110028b400f6SJacob Faibussowitsch   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
110128b400f6SJacob Faibussowitsch   PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");
11025c6c1daeSBarry Smith 
11039566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
11049566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11055c6c1daeSBarry Smith 
1106559f443fSBarry Smith   if (vascii->bviewer) {
1107fe8fb074SBarry Smith     char   *string;
11085c6c1daeSBarry Smith     va_list Argp;
1109fe8fb074SBarry Smith     size_t  fullLength;
11105c6c1daeSBarry Smith 
1111fe8fb074SBarry Smith     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
1112fe8fb074SBarry Smith     for (; tab < vascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; }
1113fe8fb074SBarry Smith     va_start(Argp, format);
1114fe8fb074SBarry Smith     PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp));
1115fe8fb074SBarry Smith     va_end(Argp);
1116fe8fb074SBarry Smith     PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string));
1117fe8fb074SBarry Smith     PetscCall(PetscFree(string));
1118fe8fb074SBarry Smith   } else if (rank == 0) { /* First processor prints immediately to fp */
1119fe8fb074SBarry Smith     va_list Argp;
1120fe8fb074SBarry Smith     FILE   *fp = vascii->fd;
1121fe8fb074SBarry Smith 
1122fe8fb074SBarry Smith     tab = vascii->tab;
112348a46eb9SPierre Jolivet     while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, "  "));
11245c6c1daeSBarry Smith 
11255c6c1daeSBarry Smith     va_start(Argp, format);
11269566063dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(fp, format, Argp));
1127eae3dc7dSJacob Faibussowitsch     va_end(Argp);
1128c69effb2SJacob Faibussowitsch     PetscCall(PetscFFlush(fp));
11295c6c1daeSBarry Smith     if (petsc_history) {
11305c6c1daeSBarry Smith       va_start(Argp, format);
11319566063dSJacob Faibussowitsch       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1132eae3dc7dSJacob Faibussowitsch       va_end(Argp);
1133c69effb2SJacob Faibussowitsch       PetscCall(PetscFFlush(petsc_history));
11345c6c1daeSBarry Smith     }
11355c6c1daeSBarry Smith     va_end(Argp);
1136559f443fSBarry Smith   } else { /* other processors add to queue */
11375c6c1daeSBarry Smith     char       *string;
11385c6c1daeSBarry Smith     va_list     Argp;
11395c6c1daeSBarry Smith     size_t      fullLength;
11405c6c1daeSBarry Smith     PrintfQueue next;
11415c6c1daeSBarry Smith 
11429566063dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
1143559f443fSBarry Smith     if (vascii->petsc_printfqueue) {
1144559f443fSBarry Smith       vascii->petsc_printfqueue->next = next;
1145559f443fSBarry Smith       vascii->petsc_printfqueue       = next;
1146a297a907SKarl Rupp     } else {
1147559f443fSBarry Smith       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1148a297a907SKarl Rupp     }
1149559f443fSBarry Smith     vascii->petsc_printfqueuelength++;
11505c6c1daeSBarry Smith     next->size = QUEUESTRINGSIZE;
11519566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(next->size, &next->string));
11525c6c1daeSBarry Smith     string = next->string;
1153f15bb73eSStefano Zampini 
1154f15bb73eSStefano Zampini     tab = vascii->tab;
11555c6c1daeSBarry Smith     tab *= 2;
1156ad540459SPierre Jolivet     while (tab--) *string++ = ' ';
11575c6c1daeSBarry Smith     va_start(Argp, format);
11589566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
11595c6c1daeSBarry Smith     va_end(Argp);
1160cb500232SBarry Smith     if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
11619566063dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
116214416c0eSBarry Smith       next->size = fullLength + 2 * vascii->tab;
11639566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(next->size, &next->string));
116414416c0eSBarry Smith       string = next->string;
116514416c0eSBarry Smith       tab    = 2 * vascii->tab;
1166ad540459SPierre Jolivet       while (tab--) *string++ = ' ';
116714416c0eSBarry Smith       va_start(Argp, format);
11689566063dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
116914416c0eSBarry Smith       va_end(Argp);
117014416c0eSBarry Smith     }
11715c6c1daeSBarry Smith   }
11723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11735c6c1daeSBarry Smith }
11745c6c1daeSBarry Smith 
11752655f987SMichael Lange /*@C
1176c410d8ccSBarry Smith   PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file
11772655f987SMichael Lange 
1178c410d8ccSBarry Smith   Only MPI rank 0 in the `PetscViewer` may call this
11792655f987SMichael Lange 
11802655f987SMichael Lange   Input Parameters:
11813f423023SBarry Smith + viewer - the `PETSCVIEWERASCII` viewer
1182c410d8ccSBarry Smith . data   - location to write the data, treated as an array of type indicated by `datatype`
1183060da220SMatthew G. Knepley . num    - number of items of data to read
1184aec76313SJacob Faibussowitsch - dtype  - type of data to read
11852655f987SMichael Lange 
118620f4b53cSBarry Smith   Output Parameter:
11873f423023SBarry Smith . count - number of items of data actually read, or `NULL`
1188f8e4bde8SMatthew G. Knepley 
11892655f987SMichael Lange   Level: beginner
11902655f987SMichael Lange 
1191d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1192db781477SPatrick Sanan           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1193db781477SPatrick Sanan           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
11942655f987SMichael Lange @*/
1195d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1196d71ae5a4SJacob Faibussowitsch {
11972655f987SMichael Lange   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
11982655f987SMichael Lange   FILE              *fd     = vascii->fd;
11992655f987SMichael Lange   PetscInt           i;
12003b7fe8c3SMatthew G. Knepley   int                ret = 0;
1201f8859db6SBarry Smith   PetscMPIInt        rank;
12022655f987SMichael Lange 
12032655f987SMichael Lange   PetscFunctionBegin;
12042655f987SMichael Lange   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
12059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1206c5853193SPierre Jolivet   PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1207060da220SMatthew G. Knepley   for (i = 0; i < num; i++) {
1208f8e4bde8SMatthew G. Knepley     if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1209f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1210a05e1a72SSatish Balay     else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1211f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
12129e3e4c22SLisandro Dalcin     else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1213972064b6SLisandro Dalcin     else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1214f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1215f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1216a6e181c6SToby Isaac #if defined(PETSC_USE_REAL___FLOAT128)
1217fba955ccSBarry Smith     else if (dtype == PETSC___FLOAT128) {
1218fba955ccSBarry Smith       double tmp;
1219fba955ccSBarry Smith       ret                     = fscanf(fd, "%lg", &tmp);
1220a6e181c6SToby Isaac       ((__float128 *)data)[i] = tmp;
1221a6e181c6SToby Isaac     }
1222fba955ccSBarry Smith #endif
12239371c9d4SSatish Balay     else
12249371c9d4SSatish Balay       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
122528b400f6SJacob Faibussowitsch     PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1226f7d195e4SLawrence Mitchell     if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
12272655f987SMichael Lange   }
1228060da220SMatthew G. Knepley   if (count) *count = i;
122908401ef6SPierre Jolivet   else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
12303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12312655f987SMichael Lange }
1232