xref: /petsc/src/sys/classes/viewer/impls/ascii/filev.c (revision c3339decea92175325d9368fa13196bcd0e0e58b)
15c6c1daeSBarry Smith 
2665c2dedSJed Brown #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h> /*I "petscviewer.h" I*/
35c6c1daeSBarry Smith 
45c6c1daeSBarry Smith #define QUEUESTRINGSIZE 8192
55c6c1daeSBarry Smith 
6d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer)
7d71ae5a4SJacob Faibussowitsch {
85c6c1daeSBarry Smith   PetscMPIInt        rank;
95c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
105c6c1daeSBarry Smith   int                err;
115c6c1daeSBarry Smith 
125c6c1daeSBarry Smith   PetscFunctionBegin;
1328b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
149566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
15dd400576SPatrick Sanan   if (rank == 0 && vascii->fd != stderr && vascii->fd != PETSC_STDOUT) {
165c6c1daeSBarry Smith     if (vascii->fd && vascii->closefile) {
175c6c1daeSBarry Smith       err = fclose(vascii->fd);
1828b400f6SJacob Faibussowitsch       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
195c6c1daeSBarry Smith     }
205c6c1daeSBarry Smith     if (vascii->storecompressed) {
215c6c1daeSBarry Smith       char  par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN];
225c6c1daeSBarry Smith       FILE *fp;
239566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(par, "gzip ", sizeof(par)));
249566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(par, vascii->filename, sizeof(par)));
255c6c1daeSBarry Smith #if defined(PETSC_HAVE_POPEN)
269566063dSJacob Faibussowitsch       PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp));
27cc73adaaSBarry Smith       PetscCheck(!fgets(buf, 1024, fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from compression command %s\n%s", par, buf);
289566063dSJacob Faibussowitsch       PetscCall(PetscPClose(PETSC_COMM_SELF, fp));
295c6c1daeSBarry Smith #else
305c6c1daeSBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
315c6c1daeSBarry Smith #endif
325c6c1daeSBarry Smith     }
335c6c1daeSBarry Smith   }
349566063dSJacob Faibussowitsch   PetscCall(PetscFree(vascii->filename));
355c6c1daeSBarry Smith   PetscFunctionReturn(0);
365c6c1daeSBarry Smith }
375c6c1daeSBarry Smith 
385c6c1daeSBarry Smith /* ----------------------------------------------------------------------*/
39d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
40d71ae5a4SJacob Faibussowitsch {
415c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
425c6c1daeSBarry Smith   PetscViewerLink   *vlink;
435c6c1daeSBarry Smith   PetscBool          flg;
445c6c1daeSBarry Smith 
455c6c1daeSBarry Smith   PetscFunctionBegin;
4628b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
479566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileClose_ASCII(viewer));
489566063dSJacob Faibussowitsch   PetscCall(PetscFree(vascii));
495c6c1daeSBarry Smith 
505c6c1daeSBarry Smith   /* remove the viewer from the list in the MPI Communicator */
5148a46eb9SPierre 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));
525c6c1daeSBarry Smith 
539566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
545c6c1daeSBarry Smith   if (flg) {
555c6c1daeSBarry Smith     if (vlink && vlink->viewer == viewer) {
56e5840a18SBarry Smith       if (vlink->next) {
579566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next));
58e5840a18SBarry Smith       } else {
599566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval));
60e5840a18SBarry Smith       }
619566063dSJacob Faibussowitsch       PetscCall(PetscFree(vlink));
625c6c1daeSBarry Smith     } else {
635c6c1daeSBarry Smith       while (vlink && vlink->next) {
645c6c1daeSBarry Smith         if (vlink->next->viewer == viewer) {
655c6c1daeSBarry Smith           PetscViewerLink *nv = vlink->next;
665c6c1daeSBarry Smith           vlink->next         = vlink->next->next;
679566063dSJacob Faibussowitsch           PetscCall(PetscFree(nv));
685c6c1daeSBarry Smith         }
695c6c1daeSBarry Smith         vlink = vlink->next;
705c6c1daeSBarry Smith       }
715c6c1daeSBarry Smith     }
725c6c1daeSBarry Smith   }
73aa139df6SJed Brown 
74aa139df6SJed Brown   if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
75aa139df6SJed Brown     PetscViewer aviewer;
769566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
7748a46eb9SPierre Jolivet     if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval));
78aa139df6SJed Brown   }
79aa139df6SJed Brown   if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
80aa139df6SJed Brown     PetscViewer aviewer;
819566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
8248a46eb9SPierre Jolivet     if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval));
83aa139df6SJed Brown   }
842e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
852e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
862e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
872e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
885c6c1daeSBarry Smith   PetscFunctionReturn(0);
895c6c1daeSBarry Smith }
905c6c1daeSBarry Smith 
91d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
92d71ae5a4SJacob Faibussowitsch {
935c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
945fd66863SKarl Rupp 
955c6c1daeSBarry Smith   PetscFunctionBegin;
969566063dSJacob Faibussowitsch   PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer));
975c6c1daeSBarry Smith   PetscFunctionReturn(0);
985c6c1daeSBarry Smith }
995c6c1daeSBarry Smith 
100d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
101d71ae5a4SJacob Faibussowitsch {
1025c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1035c6c1daeSBarry Smith   int                err;
104559f443fSBarry Smith   MPI_Comm           comm;
105559f443fSBarry Smith   PetscMPIInt        rank, size;
106559f443fSBarry Smith   FILE              *fd = vascii->fd;
1075c6c1daeSBarry Smith 
1085c6c1daeSBarry Smith   PetscFunctionBegin;
10928b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
1109566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
113559f443fSBarry Smith 
114dd400576SPatrick Sanan   if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) {
1155c6c1daeSBarry Smith     err = fflush(vascii->fd);
11628b400f6SJacob Faibussowitsch     PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() call failed");
1175c6c1daeSBarry Smith   }
1185c6c1daeSBarry Smith 
1195c6c1daeSBarry Smith   if (vascii->allowsynchronized) {
120559f443fSBarry Smith     PetscMPIInt tag, i, j, n = 0, dummy = 0;
121559f443fSBarry Smith     char       *message;
122559f443fSBarry Smith     MPI_Status  status;
123559f443fSBarry Smith 
1249566063dSJacob Faibussowitsch     PetscCall(PetscCommDuplicate(comm, &comm, &tag));
125559f443fSBarry Smith 
126559f443fSBarry Smith     /* First processor waits for messages from all other processors */
127dd400576SPatrick Sanan     if (rank == 0) {
128559f443fSBarry Smith       /* flush my own messages that I may have queued up */
129559f443fSBarry Smith       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
130559f443fSBarry Smith       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
131559f443fSBarry Smith         if (!vascii->bviewer) {
1329566063dSJacob Faibussowitsch           PetscCall(PetscFPrintf(comm, fd, "%s", next->string));
133559f443fSBarry Smith         } else {
1349566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string));
135559f443fSBarry Smith         }
136559f443fSBarry Smith         previous = next;
137559f443fSBarry Smith         next     = next->next;
1389566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous->string));
1399566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous));
140559f443fSBarry Smith       }
14102c9f0b5SLisandro Dalcin       vascii->petsc_printfqueue       = NULL;
142559f443fSBarry Smith       vascii->petsc_printfqueuelength = 0;
143559f443fSBarry Smith       for (i = 1; i < size; i++) {
144559f443fSBarry Smith         /* to prevent a flood of messages to process zero, request each message separately */
1459566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
1469566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
147559f443fSBarry Smith         for (j = 0; j < n; j++) {
148559f443fSBarry Smith           PetscMPIInt size = 0;
149559f443fSBarry Smith 
1509566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
1519566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &message));
1529566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
153559f443fSBarry Smith           if (!vascii->bviewer) {
1549566063dSJacob Faibussowitsch             PetscCall(PetscFPrintf(comm, fd, "%s", message));
155559f443fSBarry Smith           } else {
1569566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message));
157559f443fSBarry Smith           }
1589566063dSJacob Faibussowitsch           PetscCall(PetscFree(message));
159559f443fSBarry Smith         }
160559f443fSBarry Smith       }
161559f443fSBarry Smith     } else { /* other processors send queue to processor 0 */
162559f443fSBarry Smith       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
163559f443fSBarry Smith 
1649566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
1659566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
166559f443fSBarry Smith       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
1679566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
1689566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
169559f443fSBarry Smith         previous = next;
170559f443fSBarry Smith         next     = next->next;
1719566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous->string));
1729566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous));
173559f443fSBarry Smith       }
17402c9f0b5SLisandro Dalcin       vascii->petsc_printfqueue       = NULL;
175559f443fSBarry Smith       vascii->petsc_printfqueuelength = 0;
176559f443fSBarry Smith     }
1779566063dSJacob Faibussowitsch     PetscCall(PetscCommDestroy(&comm));
1785c6c1daeSBarry Smith   }
1795c6c1daeSBarry Smith   PetscFunctionReturn(0);
1805c6c1daeSBarry Smith }
1815c6c1daeSBarry Smith 
1825c6c1daeSBarry Smith /*@C
183811af0c4SBarry Smith     PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`.
1845c6c1daeSBarry Smith 
185f8859db6SBarry Smith     Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer
1865c6c1daeSBarry Smith 
187f8859db6SBarry Smith     Input Parameter:
188811af0c4SBarry Smith .    viewer - PetscViewer context, obtained from `PetscViewerASCIIOpen()`
189f8859db6SBarry Smith 
190f8859db6SBarry Smith     Output Parameter:
191f8859db6SBarry Smith .    fd - file pointer
192f8859db6SBarry Smith 
1935c6c1daeSBarry Smith     Level: intermediate
1945c6c1daeSBarry Smith 
195811af0c4SBarry Smith     Note:
196811af0c4SBarry Smith     For the standard `PETSCVIEWERASCII` the value is valid only on process 0 of the viewer
197811af0c4SBarry Smith 
1985c6c1daeSBarry Smith     Fortran Note:
1995c6c1daeSBarry Smith     This routine is not supported in Fortran.
2005c6c1daeSBarry Smith 
201811af0c4SBarry Smith .seealso: `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`,
202db781477SPatrick Sanan           `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
2035c6c1daeSBarry Smith @*/
204d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
205d71ae5a4SJacob Faibussowitsch {
2065c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
2075c6c1daeSBarry Smith 
2085c6c1daeSBarry Smith   PetscFunctionBegin;
2095c6c1daeSBarry Smith   *fd = vascii->fd;
2105c6c1daeSBarry Smith   PetscFunctionReturn(0);
2115c6c1daeSBarry Smith }
2125c6c1daeSBarry Smith 
213d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
214d71ae5a4SJacob Faibussowitsch {
2155c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
2165c6c1daeSBarry Smith 
2175c6c1daeSBarry Smith   PetscFunctionBegin;
2185c6c1daeSBarry Smith   *mode = vascii->mode;
2195c6c1daeSBarry Smith   PetscFunctionReturn(0);
2205c6c1daeSBarry Smith }
2215c6c1daeSBarry Smith 
222d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
223d71ae5a4SJacob Faibussowitsch {
2245c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
2255c6c1daeSBarry Smith 
2265c6c1daeSBarry Smith   PetscFunctionBegin;
2275c6c1daeSBarry Smith   vascii->mode = mode;
2285c6c1daeSBarry Smith   PetscFunctionReturn(0);
2295c6c1daeSBarry Smith }
2305c6c1daeSBarry Smith 
2315c6c1daeSBarry Smith /*
2325c6c1daeSBarry Smith    If petsc_history is on, then all Petsc*Printf() results are saved
2335c6c1daeSBarry Smith    if the appropriate (usually .petschistory) file.
2345c6c1daeSBarry Smith */
23595c0884eSLisandro Dalcin PETSC_INTERN FILE *petsc_history;
2365c6c1daeSBarry Smith 
2375c6c1daeSBarry Smith /*@
238811af0c4SBarry Smith     PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times
2395c6c1daeSBarry Smith 
2405c6c1daeSBarry Smith     Not Collective, but only first processor in set has any effect
2415c6c1daeSBarry Smith 
2425c6c1daeSBarry Smith     Input Parameters:
243811af0c4SBarry Smith +    viewer - obtained with `PetscViewerASCIIOpen()`
2445c6c1daeSBarry Smith -    tabs - number of tabs
2455c6c1daeSBarry Smith 
2465c6c1daeSBarry Smith     Level: developer
2475c6c1daeSBarry Smith 
2485c6c1daeSBarry Smith     Fortran Note:
2495c6c1daeSBarry Smith     This routine is not supported in Fortran.
2505c6c1daeSBarry Smith 
251db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIGetTab()`,
252db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
253db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
2545c6c1daeSBarry Smith @*/
255d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
256d71ae5a4SJacob Faibussowitsch {
2575c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
2585c6c1daeSBarry Smith   PetscBool          iascii;
2595c6c1daeSBarry Smith 
2605c6c1daeSBarry Smith   PetscFunctionBegin;
2615c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
263a297a907SKarl Rupp   if (iascii) ascii->tab = tabs;
2645c6c1daeSBarry Smith   PetscFunctionReturn(0);
2655c6c1daeSBarry Smith }
2665c6c1daeSBarry Smith 
2675c6c1daeSBarry Smith /*@
268811af0c4SBarry Smith     PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.
2695c6c1daeSBarry Smith 
2705c6c1daeSBarry Smith     Not Collective, meaningful on first processor only.
2715c6c1daeSBarry Smith 
2725c6c1daeSBarry Smith     Input Parameters:
273811af0c4SBarry Smith .    viewer - obtained with `PetscViewerASCIIOpen()`
274a2b725a8SWilliam Gropp 
2755c6c1daeSBarry Smith     Output Parameters:
2765c6c1daeSBarry Smith .    tabs - number of tabs
2775c6c1daeSBarry Smith 
2785c6c1daeSBarry Smith     Level: developer
2795c6c1daeSBarry Smith 
2805c6c1daeSBarry Smith     Fortran Note:
2815c6c1daeSBarry Smith     This routine is not supported in Fortran.
2825c6c1daeSBarry Smith 
283db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISetTab()`,
284db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
285db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
2865c6c1daeSBarry Smith @*/
287d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
288d71ae5a4SJacob Faibussowitsch {
2895c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
2905c6c1daeSBarry Smith   PetscBool          iascii;
2915c6c1daeSBarry Smith 
2925c6c1daeSBarry Smith   PetscFunctionBegin;
2935c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2949566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
295a297a907SKarl Rupp   if (iascii && tabs) *tabs = ascii->tab;
2965c6c1daeSBarry Smith   PetscFunctionReturn(0);
2975c6c1daeSBarry Smith }
2985c6c1daeSBarry Smith 
2995c6c1daeSBarry Smith /*@
3005c6c1daeSBarry Smith     PetscViewerASCIIAddTab - Add to the number of times an ASCII viewer tabs before printing
3015c6c1daeSBarry Smith 
3025c6c1daeSBarry Smith     Not Collective, but only first processor in set has any effect
3035c6c1daeSBarry Smith 
3045c6c1daeSBarry Smith     Input Parameters:
305811af0c4SBarry Smith +    viewer - obtained with `PetscViewerASCIIOpen()`
3065c6c1daeSBarry Smith -    tabs - number of tabs
3075c6c1daeSBarry Smith 
3085c6c1daeSBarry Smith     Level: developer
3095c6c1daeSBarry Smith 
3105c6c1daeSBarry Smith     Fortran Note:
3115c6c1daeSBarry Smith     This routine is not supported in Fortran.
3125c6c1daeSBarry Smith 
313db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
314db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
315db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
3165c6c1daeSBarry Smith @*/
317d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
318d71ae5a4SJacob Faibussowitsch {
3195c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3205c6c1daeSBarry Smith   PetscBool          iascii;
3215c6c1daeSBarry Smith 
3225c6c1daeSBarry Smith   PetscFunctionBegin;
3235c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
3249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
325a297a907SKarl Rupp   if (iascii) ascii->tab += tabs;
3265c6c1daeSBarry Smith   PetscFunctionReturn(0);
3275c6c1daeSBarry Smith }
3285c6c1daeSBarry Smith 
3295c6c1daeSBarry Smith /*@
3305c6c1daeSBarry Smith     PetscViewerASCIISubtractTab - Subtracts from the number of times an ASCII viewer tabs before printing
3315c6c1daeSBarry Smith 
3325c6c1daeSBarry Smith     Not Collective, but only first processor in set has any effect
3335c6c1daeSBarry Smith 
3345c6c1daeSBarry Smith     Input Parameters:
335811af0c4SBarry Smith +    viewer - obtained with `PetscViewerASCIIOpen()`
3365c6c1daeSBarry Smith -    tabs - number of tabs
3375c6c1daeSBarry Smith 
3385c6c1daeSBarry Smith     Level: developer
3395c6c1daeSBarry Smith 
3405c6c1daeSBarry Smith     Fortran Note:
3415c6c1daeSBarry Smith     This routine is not supported in Fortran.
3425c6c1daeSBarry Smith 
343db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
344db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
345db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
3465c6c1daeSBarry Smith @*/
347d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
348d71ae5a4SJacob Faibussowitsch {
3495c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3505c6c1daeSBarry Smith   PetscBool          iascii;
3515c6c1daeSBarry Smith 
3525c6c1daeSBarry Smith   PetscFunctionBegin;
3535c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
3549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
355a297a907SKarl Rupp   if (iascii) ascii->tab -= tabs;
3565c6c1daeSBarry Smith   PetscFunctionReturn(0);
3575c6c1daeSBarry Smith }
3585c6c1daeSBarry Smith 
3595c6c1daeSBarry Smith /*@C
360811af0c4SBarry Smith     PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer
3615c6c1daeSBarry Smith 
362*c3339decSBarry Smith     Collective
3635c6c1daeSBarry Smith 
3645c6c1daeSBarry Smith     Input Parameters:
365811af0c4SBarry Smith .    viewer - obtained with `PetscViewerASCIIOpen()`
3665c6c1daeSBarry Smith 
3675c6c1daeSBarry Smith     Level: intermediate
3685c6c1daeSBarry Smith 
369811af0c4SBarry Smith     Note:
370811af0c4SBarry Smith     See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
3715c6c1daeSBarry Smith 
372db781477SPatrick Sanan .seealso: `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
373db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
374db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
3755c6c1daeSBarry Smith @*/
376d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
377d71ae5a4SJacob Faibussowitsch {
3785c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3795c6c1daeSBarry Smith   PetscBool          iascii;
3805c6c1daeSBarry Smith 
3815c6c1daeSBarry Smith   PetscFunctionBegin;
3825c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
38328b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
3849566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
3851575c14dSBarry Smith   if (iascii) ascii->allowsynchronized++;
3861575c14dSBarry Smith   PetscFunctionReturn(0);
3871575c14dSBarry Smith }
3881575c14dSBarry Smith 
3891575c14dSBarry Smith /*@C
390811af0c4SBarry Smith     PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer
3911575c14dSBarry Smith 
392*c3339decSBarry Smith     Collective
3931575c14dSBarry Smith 
3941575c14dSBarry Smith     Input Parameters:
395811af0c4SBarry Smith .    viewer - obtained with `PetscViewerASCIIOpen()`
3961575c14dSBarry Smith 
3971575c14dSBarry Smith     Level: intermediate
3981575c14dSBarry Smith 
399811af0c4SBarry Smith     Note:
400811af0c4SBarry Smith     See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
4011575c14dSBarry Smith 
402db781477SPatrick Sanan .seealso: `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
403db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
404db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
4051575c14dSBarry Smith @*/
406d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
407d71ae5a4SJacob Faibussowitsch {
4081575c14dSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4091575c14dSBarry Smith   PetscBool          iascii;
4101575c14dSBarry Smith 
4111575c14dSBarry Smith   PetscFunctionBegin;
4121575c14dSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
41328b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
4149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4151575c14dSBarry Smith   if (iascii) {
4161575c14dSBarry Smith     ascii->allowsynchronized--;
41708401ef6SPierre Jolivet     PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()");
4181575c14dSBarry Smith   }
4195c6c1daeSBarry Smith   PetscFunctionReturn(0);
4205c6c1daeSBarry Smith }
4215c6c1daeSBarry Smith 
4221c297824SMatthew G. Knepley /*@C
423811af0c4SBarry Smith     PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
4245c6c1daeSBarry Smith      lines are tabbed.
4255c6c1daeSBarry Smith 
4265c6c1daeSBarry Smith     Not Collective, but only first processor in set has any effect
4275c6c1daeSBarry Smith 
4285c6c1daeSBarry Smith     Input Parameters:
429811af0c4SBarry Smith .    viewer - obtained with `PetscViewerASCIIOpen()`
4305c6c1daeSBarry Smith 
4315c6c1daeSBarry Smith     Level: developer
4325c6c1daeSBarry Smith 
4335c6c1daeSBarry Smith     Fortran Note:
4345c6c1daeSBarry Smith     This routine is not supported in Fortran.
4355c6c1daeSBarry Smith 
436db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
437db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
438db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
4395c6c1daeSBarry Smith @*/
440d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
441d71ae5a4SJacob Faibussowitsch {
4425c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4435c6c1daeSBarry Smith   PetscBool          iascii;
4445c6c1daeSBarry Smith 
4455c6c1daeSBarry Smith   PetscFunctionBegin;
4465c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
4479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
448a297a907SKarl Rupp   if (iascii) ascii->tab++;
4495c6c1daeSBarry Smith   PetscFunctionReturn(0);
4505c6c1daeSBarry Smith }
4515c6c1daeSBarry Smith 
4521c297824SMatthew G. Knepley /*@C
453811af0c4SBarry Smith     PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by `PetscViewerASCIIPushTab()`
4545c6c1daeSBarry Smith 
4555c6c1daeSBarry Smith     Not Collective, but only first processor in set has any effect
4565c6c1daeSBarry Smith 
4575c6c1daeSBarry Smith     Input Parameters:
458811af0c4SBarry Smith .    viewer - obtained with `PetscViewerASCIIOpen()`
4595c6c1daeSBarry Smith 
4605c6c1daeSBarry Smith     Level: developer
4615c6c1daeSBarry Smith 
4625c6c1daeSBarry Smith     Fortran Note:
4635c6c1daeSBarry Smith     This routine is not supported in Fortran.
4645c6c1daeSBarry Smith 
465db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
466db781477SPatrick Sanan           `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
467db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
4685c6c1daeSBarry Smith @*/
469d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
470d71ae5a4SJacob Faibussowitsch {
4715c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4725c6c1daeSBarry Smith   PetscBool          iascii;
4735c6c1daeSBarry Smith 
4745c6c1daeSBarry Smith   PetscFunctionBegin;
4755c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
4769566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4775c6c1daeSBarry Smith   if (iascii) {
47808401ef6SPierre Jolivet     PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed");
4795c6c1daeSBarry Smith     ascii->tab--;
4805c6c1daeSBarry Smith   }
4815c6c1daeSBarry Smith   PetscFunctionReturn(0);
4825c6c1daeSBarry Smith }
4835c6c1daeSBarry Smith 
4845c6c1daeSBarry Smith /*@
485811af0c4SBarry Smith     PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the ASCII `PetscViewer`
4865c6c1daeSBarry Smith 
4875c6c1daeSBarry Smith     Not Collective, but only first processor in set has any effect
4885c6c1daeSBarry Smith 
4895c6c1daeSBarry Smith     Input Parameters:
490811af0c4SBarry Smith +    viewer - obtained with `PetscViewerASCIIOpen()`
491811af0c4SBarry Smith -    flg - `PETSC_TRUE` or `PETSC_FALSE`
4925c6c1daeSBarry Smith 
4935c6c1daeSBarry Smith     Level: developer
4945c6c1daeSBarry Smith 
4955c6c1daeSBarry Smith     Fortran Note:
4965c6c1daeSBarry Smith     This routine is not supported in Fortran.
4975c6c1daeSBarry Smith 
498db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
499db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
500db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
5015c6c1daeSBarry Smith @*/
502d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
503d71ae5a4SJacob Faibussowitsch {
5045c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
5055c6c1daeSBarry Smith   PetscBool          iascii;
5065c6c1daeSBarry Smith 
5075c6c1daeSBarry Smith   PetscFunctionBegin;
5085c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
5099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
5105c6c1daeSBarry Smith   if (iascii) {
511a297a907SKarl Rupp     if (flg) ascii->tab = ascii->tab_store;
512a297a907SKarl Rupp     else {
5135c6c1daeSBarry Smith       ascii->tab_store = ascii->tab;
5145c6c1daeSBarry Smith       ascii->tab       = 0;
5155c6c1daeSBarry Smith     }
5165c6c1daeSBarry Smith   }
5175c6c1daeSBarry Smith   PetscFunctionReturn(0);
5185c6c1daeSBarry Smith }
5195c6c1daeSBarry Smith 
5205c6c1daeSBarry Smith /* ----------------------------------------------------------------------- */
5215c6c1daeSBarry Smith 
5225c6c1daeSBarry Smith /*@C
5235c6c1daeSBarry Smith     PetscViewerASCIIPrintf - Prints to a file, only from the first
5245c6c1daeSBarry Smith     processor in the PetscViewer
5255c6c1daeSBarry Smith 
5265c6c1daeSBarry Smith     Not Collective, but only first processor in set has any effect
5275c6c1daeSBarry Smith 
5285c6c1daeSBarry Smith     Input Parameters:
529811af0c4SBarry Smith +    viewer - obtained with `PetscViewerASCIIOpen()`
5305c6c1daeSBarry Smith -    format - the usual printf() format string
5315c6c1daeSBarry Smith 
5325c6c1daeSBarry Smith     Level: developer
5335c6c1daeSBarry Smith 
5345c6c1daeSBarry Smith     Fortran Note:
535811af0c4SBarry Smith     The call sequence is `PetscViewerASCIIPrintf`(PetscViewer, character(*), int ierr) from Fortran.
5365c6c1daeSBarry Smith     That is, you can only pass a single character string from Fortran.
5375c6c1daeSBarry Smith 
538db781477SPatrick Sanan .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
539db781477SPatrick Sanan           `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
540db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
5415c6c1daeSBarry Smith @*/
542d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
543d71ae5a4SJacob Faibussowitsch {
5445c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
5455c6c1daeSBarry Smith   PetscMPIInt        rank;
546dd2fa690SBarry Smith   PetscInt           tab, intab = ascii->tab;
5475c6c1daeSBarry Smith   FILE              *fd = ascii->fd;
5483f08860eSBarry Smith   PetscBool          iascii;
5495c6c1daeSBarry Smith   int                err;
5505c6c1daeSBarry Smith 
5515c6c1daeSBarry Smith   PetscFunctionBegin;
5525c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
55328b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
5545c6c1daeSBarry Smith   PetscValidCharPointer(format, 2);
5559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
55628b400f6SJacob Faibussowitsch   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
5579566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
558559f443fSBarry Smith   if (rank) PetscFunctionReturn(0);
5593f08860eSBarry Smith 
5603f08860eSBarry Smith   if (ascii->bviewer) { /* pass string up to parent viewer */
5613f08860eSBarry Smith     char   *string;
5623f08860eSBarry Smith     va_list Argp;
5633f08860eSBarry Smith     size_t  fullLength;
5643f08860eSBarry Smith 
5659566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
5663f08860eSBarry Smith     va_start(Argp, format);
5679566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(string, QUEUESTRINGSIZE, format, &fullLength, Argp));
5683f08860eSBarry Smith     va_end(Argp);
5699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%s", string));
5709566063dSJacob Faibussowitsch     PetscCall(PetscFree(string));
5713f08860eSBarry Smith   } else { /* write directly to file */
5725c6c1daeSBarry Smith     va_list Argp;
573559f443fSBarry Smith     /* flush my own messages that I may have queued up */
574559f443fSBarry Smith     PrintfQueue next = ascii->petsc_printfqueuebase, previous;
575559f443fSBarry Smith     PetscInt    i;
576559f443fSBarry Smith     for (i = 0; i < ascii->petsc_printfqueuelength; i++) {
5779566063dSJacob Faibussowitsch       PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "%s", next->string));
578559f443fSBarry Smith       previous = next;
579559f443fSBarry Smith       next     = next->next;
5809566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
5819566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
582559f443fSBarry Smith     }
58302c9f0b5SLisandro Dalcin     ascii->petsc_printfqueue       = NULL;
584559f443fSBarry Smith     ascii->petsc_printfqueuelength = 0;
585dd2fa690SBarry Smith     tab                            = intab;
58648a46eb9SPierre Jolivet     while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "  "));
5875c6c1daeSBarry Smith 
5885c6c1daeSBarry Smith     va_start(Argp, format);
5899566063dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(fd, format, Argp));
5905c6c1daeSBarry Smith     err = fflush(fd);
59128b400f6SJacob Faibussowitsch     PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
5925c6c1daeSBarry Smith     if (petsc_history) {
5935c6c1daeSBarry Smith       va_start(Argp, format);
594dd2fa690SBarry Smith       tab = intab;
59548a46eb9SPierre Jolivet       while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, petsc_history, "  "));
5969566063dSJacob Faibussowitsch       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
5975c6c1daeSBarry Smith       err = fflush(petsc_history);
59828b400f6SJacob Faibussowitsch       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
5995c6c1daeSBarry Smith     }
6005c6c1daeSBarry Smith     va_end(Argp);
6015c6c1daeSBarry Smith   }
6025c6c1daeSBarry Smith   PetscFunctionReturn(0);
6035c6c1daeSBarry Smith }
6045c6c1daeSBarry Smith 
6055c6c1daeSBarry Smith /*@C
606811af0c4SBarry Smith      PetscViewerFileSetName - Sets the name of the file the `PetscViewer` uses.
6075c6c1daeSBarry Smith 
608*c3339decSBarry Smith     Collective
6095c6c1daeSBarry Smith 
6105c6c1daeSBarry Smith   Input Parameters:
611811af0c4SBarry Smith +  viewer - the PetscViewer; either `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
6125c6c1daeSBarry Smith -  name - the name of the file it should use
6135c6c1daeSBarry Smith 
6145c6c1daeSBarry Smith     Level: advanced
6155c6c1daeSBarry Smith 
616db781477SPatrick Sanan .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
617db781477SPatrick Sanan           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
6185c6c1daeSBarry Smith @*/
619d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
620d71ae5a4SJacob Faibussowitsch {
621cc843e7aSLisandro Dalcin   char filename[PETSC_MAX_PATH_LEN];
6225c6c1daeSBarry Smith 
6235c6c1daeSBarry Smith   PetscFunctionBegin;
6245c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
6255c6c1daeSBarry Smith   PetscValidCharPointer(name, 2);
6269566063dSJacob Faibussowitsch   PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
627cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
6285c6c1daeSBarry Smith   PetscFunctionReturn(0);
6295c6c1daeSBarry Smith }
6305c6c1daeSBarry Smith 
6315c6c1daeSBarry Smith /*@C
632811af0c4SBarry Smith      PetscViewerFileGetName - Gets the name of the file the `PetscViewer` uses.
6335c6c1daeSBarry Smith 
6345c6c1daeSBarry Smith     Not Collective
6355c6c1daeSBarry Smith 
6365c6c1daeSBarry Smith   Input Parameter:
637811af0c4SBarry Smith .  viewer - the `PetscViewer`; either `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
6385c6c1daeSBarry Smith 
6395c6c1daeSBarry Smith   Output Parameter:
6405c6c1daeSBarry Smith .  name - the name of the file it is using
6415c6c1daeSBarry Smith 
6425c6c1daeSBarry Smith     Level: advanced
6435c6c1daeSBarry Smith 
644db781477SPatrick Sanan .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
6455c6c1daeSBarry Smith @*/
646d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
647d71ae5a4SJacob Faibussowitsch {
6485c6c1daeSBarry Smith   PetscFunctionBegin;
6495c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
6506e05b1faSLisandro Dalcin   PetscValidPointer(name, 2);
651cac4c232SBarry Smith   PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
6525c6c1daeSBarry Smith   PetscFunctionReturn(0);
6535c6c1daeSBarry Smith }
6545c6c1daeSBarry Smith 
655d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
656d71ae5a4SJacob Faibussowitsch {
6575c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
6585c6c1daeSBarry Smith 
6595c6c1daeSBarry Smith   PetscFunctionBegin;
6605c6c1daeSBarry Smith   *name = vascii->filename;
6615c6c1daeSBarry Smith   PetscFunctionReturn(0);
6625c6c1daeSBarry Smith }
6635c6c1daeSBarry Smith 
664d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
665d71ae5a4SJacob Faibussowitsch {
6665c6c1daeSBarry Smith   size_t             len;
6675c6c1daeSBarry Smith   char               fname[PETSC_MAX_PATH_LEN], *gz;
6685c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
6695c6c1daeSBarry Smith   PetscBool          isstderr, isstdout;
6705c6c1daeSBarry Smith   PetscMPIInt        rank;
6715c6c1daeSBarry Smith 
6725c6c1daeSBarry Smith   PetscFunctionBegin;
6739566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileClose_ASCII(viewer));
6745c6c1daeSBarry Smith   if (!name) PetscFunctionReturn(0);
6759566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &vascii->filename));
6765c6c1daeSBarry Smith 
6775c6c1daeSBarry Smith   /* Is this file to be compressed */
6785c6c1daeSBarry Smith   vascii->storecompressed = PETSC_FALSE;
679a297a907SKarl Rupp 
6809566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
6815c6c1daeSBarry Smith   if (gz) {
6829566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(gz, &len));
6835c6c1daeSBarry Smith     if (len == 3) {
68408401ef6SPierre 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");
6855c6c1daeSBarry Smith       *gz                     = 0;
6865c6c1daeSBarry Smith       vascii->storecompressed = PETSC_TRUE;
6875c6c1daeSBarry Smith     }
6885c6c1daeSBarry Smith   }
6899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
690dd400576SPatrick Sanan   if (rank == 0) {
6919566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
6929566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
6935c6c1daeSBarry Smith     /* empty filename means stdout */
6945c6c1daeSBarry Smith     if (name[0] == 0) isstdout = PETSC_TRUE;
6955c6c1daeSBarry Smith     if (isstderr) vascii->fd = PETSC_STDERR;
6965c6c1daeSBarry Smith     else if (isstdout) vascii->fd = PETSC_STDOUT;
6975c6c1daeSBarry Smith     else {
6989566063dSJacob Faibussowitsch       PetscCall(PetscFixFilename(name, fname));
6995c6c1daeSBarry Smith       switch (vascii->mode) {
700d71ae5a4SJacob Faibussowitsch       case FILE_MODE_READ:
701d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "r");
702d71ae5a4SJacob Faibussowitsch         break;
703d71ae5a4SJacob Faibussowitsch       case FILE_MODE_WRITE:
704d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "w");
705d71ae5a4SJacob Faibussowitsch         break;
706d71ae5a4SJacob Faibussowitsch       case FILE_MODE_APPEND:
707d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "a");
708d71ae5a4SJacob Faibussowitsch         break;
7095c6c1daeSBarry Smith       case FILE_MODE_UPDATE:
7105c6c1daeSBarry Smith         vascii->fd = fopen(fname, "r+");
711a297a907SKarl Rupp         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
7125c6c1daeSBarry Smith         break;
7135c6c1daeSBarry Smith       case FILE_MODE_APPEND_UPDATE:
7145c6c1daeSBarry Smith         /* I really want a file which is opened at the end for updating,
7155c6c1daeSBarry Smith            not a+, which opens at the beginning, but makes writes at the end.
7165c6c1daeSBarry Smith         */
7175c6c1daeSBarry Smith         vascii->fd = fopen(fname, "r+");
718a297a907SKarl Rupp         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
71948a46eb9SPierre Jolivet         else PetscCall(fseek(vascii->fd, 0, SEEK_END));
7205c6c1daeSBarry Smith         break;
721d71ae5a4SJacob Faibussowitsch       default:
722d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
7235c6c1daeSBarry Smith       }
72428b400f6SJacob Faibussowitsch       PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname);
7255c6c1daeSBarry Smith     }
7265c6c1daeSBarry Smith   }
7275c6c1daeSBarry Smith #if defined(PETSC_USE_LOG)
7285c6c1daeSBarry Smith   PetscLogObjectState((PetscObject)viewer, "File: %s", name);
7295c6c1daeSBarry Smith #endif
7305c6c1daeSBarry Smith   PetscFunctionReturn(0);
7315c6c1daeSBarry Smith }
7325c6c1daeSBarry Smith 
733d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
734d71ae5a4SJacob Faibussowitsch {
7355c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
7365c6c1daeSBarry Smith 
7375c6c1daeSBarry Smith   PetscFunctionBegin;
7389566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
73928b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
740e5afcf28SBarry Smith   /*
7419530cbd7SBarry Smith      The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
7429530cbd7SBarry 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
7439530cbd7SBarry Smith      (since the count never gets to zero) in some examples this displays information that otherwise would be lost
7449530cbd7SBarry Smith 
7459530cbd7SBarry Smith      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
7469530cbd7SBarry Smith      PCView_GASM().
747e5afcf28SBarry Smith   */
7489566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
7499566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(subcomm, outviewer));
7509566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
7519566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
7525c6c1daeSBarry Smith   ovascii            = (PetscViewer_ASCII *)(*outviewer)->data;
7535c6c1daeSBarry Smith   ovascii->fd        = vascii->fd;
7545c6c1daeSBarry Smith   ovascii->tab       = vascii->tab;
755ba5a0b41SBarry Smith   ovascii->closefile = PETSC_FALSE;
7565c6c1daeSBarry Smith 
7575c6c1daeSBarry Smith   vascii->sviewer                                      = *outviewer;
7585c6c1daeSBarry Smith   (*outviewer)->format                                 = viewer->format;
7595c6c1daeSBarry Smith   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
7603f08860eSBarry Smith   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
7615c6c1daeSBarry Smith   PetscFunctionReturn(0);
7625c6c1daeSBarry Smith }
7635c6c1daeSBarry Smith 
764d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
765d71ae5a4SJacob Faibussowitsch {
7665c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
7675c6c1daeSBarry Smith 
7685c6c1daeSBarry Smith   PetscFunctionBegin;
76928b400f6SJacob Faibussowitsch   PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
77008401ef6SPierre Jolivet   PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");
7715c6c1daeSBarry Smith 
7729566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
773e5afcf28SBarry Smith   ascii->sviewer             = NULL;
7745c6c1daeSBarry Smith   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
7759566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(outviewer));
7769566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
7775c6c1daeSBarry Smith   PetscFunctionReturn(0);
7785c6c1daeSBarry Smith }
7795c6c1daeSBarry Smith 
780d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
781d71ae5a4SJacob Faibussowitsch {
7822bf49c77SBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
7832bf49c77SBarry Smith 
7842bf49c77SBarry Smith   PetscFunctionBegin;
78548a46eb9SPierre Jolivet   if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
7862bf49c77SBarry Smith   PetscFunctionReturn(0);
7872bf49c77SBarry Smith }
7882bf49c77SBarry Smith 
7898556b5ebSBarry Smith /*MC
7908556b5ebSBarry Smith    PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file
7918556b5ebSBarry Smith 
792811af0c4SBarry Smith   Level: beginner
793811af0c4SBarry Smith 
794c2e3fba1SPatrick Sanan .seealso: `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
795db781477SPatrick Sanan           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
796db781477SPatrick Sanan           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
7978556b5ebSBarry Smith M*/
798d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
799d71ae5a4SJacob Faibussowitsch {
8005c6c1daeSBarry Smith   PetscViewer_ASCII *vascii;
8015c6c1daeSBarry Smith 
8025c6c1daeSBarry Smith   PetscFunctionBegin;
8034dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&vascii));
8045c6c1daeSBarry Smith   viewer->data = (void *)vascii;
8055c6c1daeSBarry Smith 
8065c6c1daeSBarry Smith   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
8075c6c1daeSBarry Smith   viewer->ops->flush            = PetscViewerFlush_ASCII;
808559f443fSBarry Smith   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
809559f443fSBarry Smith   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
8102bf49c77SBarry Smith   viewer->ops->view             = PetscViewerView_ASCII;
8111d641e7bSMichael Lange   viewer->ops->read             = PetscViewerASCIIRead;
8125c6c1daeSBarry Smith 
8135c6c1daeSBarry Smith   /* defaults to stdout unless set with PetscViewerFileSetName() */
8145c6c1daeSBarry Smith   vascii->fd        = PETSC_STDOUT;
8155c6c1daeSBarry Smith   vascii->mode      = FILE_MODE_WRITE;
81602c9f0b5SLisandro Dalcin   vascii->bviewer   = NULL;
81702c9f0b5SLisandro Dalcin   vascii->subviewer = NULL;
81802c9f0b5SLisandro Dalcin   vascii->sviewer   = NULL;
8195c6c1daeSBarry Smith   vascii->tab       = 0;
8205c6c1daeSBarry Smith   vascii->tab_store = 0;
82102c9f0b5SLisandro Dalcin   vascii->filename  = NULL;
8225c6c1daeSBarry Smith   vascii->closefile = PETSC_TRUE;
8235c6c1daeSBarry Smith 
8249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
8259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
8269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
8279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
8285c6c1daeSBarry Smith   PetscFunctionReturn(0);
8295c6c1daeSBarry Smith }
8305c6c1daeSBarry Smith 
8315c6c1daeSBarry Smith /*@C
8325c6c1daeSBarry Smith     PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified file from
8335c6c1daeSBarry Smith     several processors.  Output of the first processor is followed by that of the
8345c6c1daeSBarry Smith     second, etc.
8355c6c1daeSBarry Smith 
836811af0c4SBarry Smith     Not Collective, must call collective `PetscViewerFlush()` to get the results out
8375c6c1daeSBarry Smith 
8385c6c1daeSBarry Smith     Input Parameters:
839811af0c4SBarry Smith +   viewer - the `PETSCVIEWERASCII` `PetscViewer`
8405c6c1daeSBarry Smith -   format - the usual printf() format string
8415c6c1daeSBarry Smith 
8425c6c1daeSBarry Smith     Level: intermediate
8435c6c1daeSBarry Smith 
84495452b02SPatrick Sanan     Notes:
845811af0c4SBarry Smith     You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
846e6abc3ddSVáclav Hapla     Then you can do multiple independent calls to this routine.
847811af0c4SBarry Smith 
848811af0c4SBarry Smith     The actual synchronized print is then done using `PetscViewerFlush()`.
849811af0c4SBarry Smith     `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
850e6abc3ddSVáclav Hapla     to conclude the "synchronized session".
851811af0c4SBarry Smith 
852e6abc3ddSVáclav Hapla     So the typical calling sequence looks like
853811af0c4SBarry Smith .vb
854811af0c4SBarry Smith     PetscViewerASCIIPushSynchronized(viewer);
855811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
856811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
857811af0c4SBarry Smith     ...
858811af0c4SBarry Smith     PetscViewerFlush(viewer);
859811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
860811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
861811af0c4SBarry Smith     ...
862811af0c4SBarry Smith     PetscViewerFlush(viewer);
863811af0c4SBarry Smith    PetscViewerASCIIPopSynchronized(viewer);
864811af0c4SBarry Smith .ve
8655c6c1daeSBarry Smith 
8665c6c1daeSBarry Smith     Fortran Note:
8675c6c1daeSBarry Smith       Can only print a single character* string
8685c6c1daeSBarry Smith 
869db781477SPatrick Sanan .seealso: `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
870db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
871db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
8725c6c1daeSBarry Smith @*/
873d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
874d71ae5a4SJacob Faibussowitsch {
8755c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
8763f08860eSBarry Smith   PetscMPIInt        rank;
8775c6c1daeSBarry Smith   PetscInt           tab = vascii->tab;
8785c6c1daeSBarry Smith   MPI_Comm           comm;
8795c6c1daeSBarry Smith   FILE              *fp;
880559f443fSBarry Smith   PetscBool          iascii, hasbviewer = PETSC_FALSE;
8815c6c1daeSBarry Smith   int                err;
8825c6c1daeSBarry Smith 
8835c6c1daeSBarry Smith   PetscFunctionBegin;
8845c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8855c6c1daeSBarry Smith   PetscValidCharPointer(format, 2);
8869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
88728b400f6SJacob Faibussowitsch   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
88828b400f6SJacob Faibussowitsch   PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");
8895c6c1daeSBarry Smith 
8909566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
8919566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8925c6c1daeSBarry Smith 
893559f443fSBarry Smith   if (vascii->bviewer) {
894559f443fSBarry Smith     hasbviewer = PETSC_TRUE;
895dd400576SPatrick Sanan     if (rank == 0) {
896559f443fSBarry Smith       vascii = (PetscViewer_ASCII *)vascii->bviewer->data;
8979566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
8989566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
899559f443fSBarry Smith     }
900559f443fSBarry Smith   }
9013f08860eSBarry Smith 
902559f443fSBarry Smith   fp = vascii->fd;
903559f443fSBarry Smith 
904dd400576SPatrick Sanan   if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */
9055c6c1daeSBarry Smith     va_list Argp;
906559f443fSBarry Smith     /* flush my own messages that I may have queued up */
907559f443fSBarry Smith     PrintfQueue next = vascii->petsc_printfqueuebase, previous;
908559f443fSBarry Smith     PetscInt    i;
909559f443fSBarry Smith     for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
9109566063dSJacob Faibussowitsch       PetscCall(PetscFPrintf(comm, fp, "%s", next->string));
911559f443fSBarry Smith       previous = next;
912559f443fSBarry Smith       next     = next->next;
9139566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
9149566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
915559f443fSBarry Smith     }
91602c9f0b5SLisandro Dalcin     vascii->petsc_printfqueue       = NULL;
917559f443fSBarry Smith     vascii->petsc_printfqueuelength = 0;
9185c6c1daeSBarry Smith 
91948a46eb9SPierre Jolivet     while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, "  "));
9205c6c1daeSBarry Smith 
9215c6c1daeSBarry Smith     va_start(Argp, format);
9229566063dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(fp, format, Argp));
9235c6c1daeSBarry Smith     err = fflush(fp);
92428b400f6SJacob Faibussowitsch     PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
9255c6c1daeSBarry Smith     if (petsc_history) {
9265c6c1daeSBarry Smith       va_start(Argp, format);
9279566063dSJacob Faibussowitsch       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
9285c6c1daeSBarry Smith       err = fflush(petsc_history);
92928b400f6SJacob Faibussowitsch       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
9305c6c1daeSBarry Smith     }
9315c6c1daeSBarry Smith     va_end(Argp);
932559f443fSBarry Smith   } else { /* other processors add to queue */
9335c6c1daeSBarry Smith     char       *string;
9345c6c1daeSBarry Smith     va_list     Argp;
9355c6c1daeSBarry Smith     size_t      fullLength;
9365c6c1daeSBarry Smith     PrintfQueue next;
9375c6c1daeSBarry Smith 
9389566063dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
939559f443fSBarry Smith     if (vascii->petsc_printfqueue) {
940559f443fSBarry Smith       vascii->petsc_printfqueue->next = next;
941559f443fSBarry Smith       vascii->petsc_printfqueue       = next;
942a297a907SKarl Rupp     } else {
943559f443fSBarry Smith       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
944a297a907SKarl Rupp     }
945559f443fSBarry Smith     vascii->petsc_printfqueuelength++;
9465c6c1daeSBarry Smith     next->size = QUEUESTRINGSIZE;
9479566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(next->size, &next->string));
9485c6c1daeSBarry Smith     string = next->string;
9495c6c1daeSBarry Smith     tab *= 2;
950ad540459SPierre Jolivet     while (tab--) *string++ = ' ';
9515c6c1daeSBarry Smith     va_start(Argp, format);
9529566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
9535c6c1daeSBarry Smith     va_end(Argp);
954cb500232SBarry Smith     if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
9559566063dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
95614416c0eSBarry Smith       next->size = fullLength + 2 * vascii->tab;
9579566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(next->size, &next->string));
95814416c0eSBarry Smith       string = next->string;
95914416c0eSBarry Smith       tab    = 2 * vascii->tab;
960ad540459SPierre Jolivet       while (tab--) *string++ = ' ';
96114416c0eSBarry Smith       va_start(Argp, format);
9629566063dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
96314416c0eSBarry Smith       va_end(Argp);
96414416c0eSBarry Smith     }
9655c6c1daeSBarry Smith   }
9665c6c1daeSBarry Smith   PetscFunctionReturn(0);
9675c6c1daeSBarry Smith }
9685c6c1daeSBarry Smith 
9692655f987SMichael Lange /*@C
970f8859db6SBarry Smith    PetscViewerASCIIRead - Reads from a ASCII file
9712655f987SMichael Lange 
972811af0c4SBarry Smith    Only process 0 in the `PetscViewer` may call this
9732655f987SMichael Lange 
9742655f987SMichael Lange    Input Parameters:
9752655f987SMichael Lange +  viewer - the ascii viewer
9762655f987SMichael Lange .  data - location to write the data
977060da220SMatthew G. Knepley .  num - number of items of data to read
9782655f987SMichael Lange -  datatype - type of data to read
9792655f987SMichael Lange 
980f8e4bde8SMatthew G. Knepley    Output Parameters:
981060da220SMatthew G. Knepley .  count - number of items of data actually read, or NULL
982f8e4bde8SMatthew G. Knepley 
9832655f987SMichael Lange    Level: beginner
9842655f987SMichael Lange 
985db781477SPatrick Sanan .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
986db781477SPatrick Sanan           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
987db781477SPatrick Sanan           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
9882655f987SMichael Lange @*/
989d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
990d71ae5a4SJacob Faibussowitsch {
9912655f987SMichael Lange   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
9922655f987SMichael Lange   FILE              *fd     = vascii->fd;
9932655f987SMichael Lange   PetscInt           i;
9943b7fe8c3SMatthew G. Knepley   int                ret = 0;
995f8859db6SBarry Smith   PetscMPIInt        rank;
9962655f987SMichael Lange 
9972655f987SMichael Lange   PetscFunctionBegin;
9982655f987SMichael Lange   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
9999566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1000c5853193SPierre Jolivet   PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1001060da220SMatthew G. Knepley   for (i = 0; i < num; i++) {
1002f8e4bde8SMatthew G. Knepley     if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1003f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1004a05e1a72SSatish Balay     else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1005f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
10069e3e4c22SLisandro Dalcin     else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1007972064b6SLisandro Dalcin     else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1008f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1009f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1010a6e181c6SToby Isaac #if defined(PETSC_USE_REAL___FLOAT128)
1011fba955ccSBarry Smith     else if (dtype == PETSC___FLOAT128) {
1012fba955ccSBarry Smith       double tmp;
1013fba955ccSBarry Smith       ret                     = fscanf(fd, "%lg", &tmp);
1014a6e181c6SToby Isaac       ((__float128 *)data)[i] = tmp;
1015a6e181c6SToby Isaac     }
1016fba955ccSBarry Smith #endif
10179371c9d4SSatish Balay     else
10189371c9d4SSatish Balay       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
101928b400f6SJacob Faibussowitsch     PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1020f7d195e4SLawrence Mitchell     if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
10212655f987SMichael Lange   }
1022060da220SMatthew G. Knepley   if (count) *count = i;
102308401ef6SPierre Jolivet   else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
10242655f987SMichael Lange   PetscFunctionReturn(0);
10252655f987SMichael Lange }
1026