xref: /petsc/src/sys/classes/viewer/impls/ascii/filev.c (revision baca6076736e385493fd849a2765fd1676cb8d6d)
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));
26cc73adaaSBarry Smith       PetscCheck(!fgets(buf, 1024, fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from compression command %s\n%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;
2015c6c1daeSBarry Smith   *fd = vascii->fd;
2023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2035c6c1daeSBarry Smith }
2045c6c1daeSBarry Smith 
20534e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
206d71ae5a4SJacob Faibussowitsch {
2075c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
2085c6c1daeSBarry Smith 
2095c6c1daeSBarry Smith   PetscFunctionBegin;
2105c6c1daeSBarry Smith   *mode = vascii->mode;
2113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2125c6c1daeSBarry Smith }
2135c6c1daeSBarry Smith 
21434e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
215d71ae5a4SJacob Faibussowitsch {
2165c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
2175c6c1daeSBarry Smith 
2185c6c1daeSBarry Smith   PetscFunctionBegin;
2195c6c1daeSBarry Smith   vascii->mode = mode;
2203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2215c6c1daeSBarry Smith }
2225c6c1daeSBarry Smith 
2235c6c1daeSBarry Smith /*
2245c6c1daeSBarry Smith    If petsc_history is on, then all Petsc*Printf() results are saved
2255c6c1daeSBarry Smith    if the appropriate (usually .petschistory) file.
2265c6c1daeSBarry Smith */
22795c0884eSLisandro Dalcin PETSC_INTERN FILE *petsc_history;
2285c6c1daeSBarry Smith 
2295c6c1daeSBarry Smith /*@
2303f423023SBarry Smith   PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times before printing
2315c6c1daeSBarry Smith 
232cf53795eSBarry Smith   Not Collective, but only first processor in set has any effect; No Fortran Support
2335c6c1daeSBarry Smith 
2345c6c1daeSBarry Smith   Input Parameters:
235811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
2365c6c1daeSBarry Smith - tabs   - number of tabs
2375c6c1daeSBarry Smith 
2385c6c1daeSBarry Smith   Level: developer
2395c6c1daeSBarry Smith 
2403f423023SBarry Smith   Note:
2413f423023SBarry Smith   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
2423f423023SBarry Smith 
2433f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
2443f423023SBarry Smith           `PetscViewerASCIIGetTab()`,
245db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
2463f423023SBarry Smith           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
2473f423023SBarry Smith           `PetscViewerASCIIPushTab()`
2485c6c1daeSBarry Smith @*/
249d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
250d71ae5a4SJacob Faibussowitsch {
2515c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
2525c6c1daeSBarry Smith   PetscBool          iascii;
2535c6c1daeSBarry Smith 
2545c6c1daeSBarry Smith   PetscFunctionBegin;
2555c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
257a297a907SKarl Rupp   if (iascii) ascii->tab = tabs;
2583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2595c6c1daeSBarry Smith }
2605c6c1daeSBarry Smith 
2615c6c1daeSBarry Smith /*@
262811af0c4SBarry Smith   PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.
2635c6c1daeSBarry Smith 
264cf53795eSBarry Smith   Not Collective, meaningful on first processor only; No Fortran Support
2655c6c1daeSBarry Smith 
26620f4b53cSBarry Smith   Input Parameter:
267811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
268a2b725a8SWilliam Gropp 
26920f4b53cSBarry Smith   Output Parameter:
2705c6c1daeSBarry Smith . tabs - number of tabs
2715c6c1daeSBarry Smith 
2725c6c1daeSBarry Smith   Level: developer
2735c6c1daeSBarry Smith 
2743f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
2753f423023SBarry Smith           `PetscViewerASCIISetTab()`,
276db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
277db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
2785c6c1daeSBarry Smith @*/
279d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
280d71ae5a4SJacob Faibussowitsch {
2815c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
2825c6c1daeSBarry Smith   PetscBool          iascii;
2835c6c1daeSBarry Smith 
2845c6c1daeSBarry Smith   PetscFunctionBegin;
2855c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
287a297a907SKarl Rupp   if (iascii && tabs) *tabs = ascii->tab;
2883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2895c6c1daeSBarry Smith }
2905c6c1daeSBarry Smith 
2915c6c1daeSBarry Smith /*@
2923f423023SBarry Smith   PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing
2935c6c1daeSBarry Smith 
294cf53795eSBarry Smith   Not Collective, but only first processor in set has any effect; No Fortran Support
2955c6c1daeSBarry Smith 
2965c6c1daeSBarry Smith   Input Parameters:
297811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
2985c6c1daeSBarry Smith - tabs   - number of tabs
2995c6c1daeSBarry Smith 
3005c6c1daeSBarry Smith   Level: developer
3015c6c1daeSBarry Smith 
3023f423023SBarry Smith   Note:
3033f423023SBarry Smith   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
3043f423023SBarry Smith 
3053f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
306db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
307db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
3085c6c1daeSBarry Smith @*/
309d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
310d71ae5a4SJacob Faibussowitsch {
3115c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3125c6c1daeSBarry Smith   PetscBool          iascii;
3135c6c1daeSBarry Smith 
3145c6c1daeSBarry Smith   PetscFunctionBegin;
3155c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
3169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
317a297a907SKarl Rupp   if (iascii) ascii->tab += tabs;
3183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3195c6c1daeSBarry Smith }
3205c6c1daeSBarry Smith 
3215c6c1daeSBarry Smith /*@
3223f423023SBarry Smith   PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing
3235c6c1daeSBarry Smith 
324cf53795eSBarry Smith   Not Collective, but only first processor in set has any effect; No Fortran Support
3255c6c1daeSBarry Smith 
3265c6c1daeSBarry Smith   Input Parameters:
327811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
3285c6c1daeSBarry Smith - tabs   - number of tabs
3295c6c1daeSBarry Smith 
3305c6c1daeSBarry Smith   Level: developer
3315c6c1daeSBarry Smith 
3323f423023SBarry Smith   Note:
3333f423023SBarry Smith   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
3343f423023SBarry Smith 
3353f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
336db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
3373f423023SBarry Smith           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
3383f423023SBarry Smith           `PetscViewerASCIIPushTab()`
3395c6c1daeSBarry Smith @*/
340d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
341d71ae5a4SJacob Faibussowitsch {
3425c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3435c6c1daeSBarry Smith   PetscBool          iascii;
3445c6c1daeSBarry Smith 
3455c6c1daeSBarry Smith   PetscFunctionBegin;
3465c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
3479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
348a297a907SKarl Rupp   if (iascii) ascii->tab -= tabs;
3493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3505c6c1daeSBarry Smith }
3515c6c1daeSBarry Smith 
3525c6c1daeSBarry Smith /*@C
353811af0c4SBarry Smith   PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer
3545c6c1daeSBarry Smith 
355c3339decSBarry Smith   Collective
3565c6c1daeSBarry Smith 
35720f4b53cSBarry Smith   Input Parameter:
358811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
3595c6c1daeSBarry Smith 
3605c6c1daeSBarry Smith   Level: intermediate
3615c6c1daeSBarry Smith 
362811af0c4SBarry Smith   Note:
363811af0c4SBarry Smith   See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
3645c6c1daeSBarry Smith 
365d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
366db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
367db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
3685c6c1daeSBarry Smith @*/
369d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
370d71ae5a4SJacob Faibussowitsch {
3715c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3725c6c1daeSBarry Smith   PetscBool          iascii;
3735c6c1daeSBarry Smith 
3745c6c1daeSBarry Smith   PetscFunctionBegin;
3755c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
37628b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
3779566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
3781575c14dSBarry Smith   if (iascii) ascii->allowsynchronized++;
3793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3801575c14dSBarry Smith }
3811575c14dSBarry Smith 
3821575c14dSBarry Smith /*@C
383811af0c4SBarry Smith   PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer
3841575c14dSBarry Smith 
385c3339decSBarry Smith   Collective
3861575c14dSBarry Smith 
38720f4b53cSBarry Smith   Input Parameter:
388811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
3891575c14dSBarry Smith 
3901575c14dSBarry Smith   Level: intermediate
3911575c14dSBarry Smith 
392811af0c4SBarry Smith   Note:
393811af0c4SBarry Smith   See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
3941575c14dSBarry Smith 
395d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
396db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
397db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
3981575c14dSBarry Smith @*/
399d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
400d71ae5a4SJacob Faibussowitsch {
4011575c14dSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4021575c14dSBarry Smith   PetscBool          iascii;
4031575c14dSBarry Smith 
4041575c14dSBarry Smith   PetscFunctionBegin;
4051575c14dSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
40628b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
4079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4081575c14dSBarry Smith   if (iascii) {
4091575c14dSBarry Smith     ascii->allowsynchronized--;
41008401ef6SPierre Jolivet     PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()");
4111575c14dSBarry Smith   }
4123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4135c6c1daeSBarry Smith }
4145c6c1daeSBarry Smith 
4151c297824SMatthew G. Knepley /*@C
416811af0c4SBarry Smith   PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
4175c6c1daeSBarry Smith   lines are tabbed.
4185c6c1daeSBarry Smith 
419c410d8ccSBarry Smith   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
4205c6c1daeSBarry Smith 
42120f4b53cSBarry Smith   Input Parameter:
422811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
4235c6c1daeSBarry Smith 
4245c6c1daeSBarry Smith   Level: developer
4255c6c1daeSBarry Smith 
426d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
427db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
428db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
4295c6c1daeSBarry Smith @*/
430d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
431d71ae5a4SJacob Faibussowitsch {
4325c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4335c6c1daeSBarry Smith   PetscBool          iascii;
4345c6c1daeSBarry Smith 
4355c6c1daeSBarry Smith   PetscFunctionBegin;
4365c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
4379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
438a297a907SKarl Rupp   if (iascii) ascii->tab++;
4393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4405c6c1daeSBarry Smith }
4415c6c1daeSBarry Smith 
4421c297824SMatthew G. Knepley /*@C
4433f423023SBarry Smith   PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by
4443f423023SBarry Smith   `PetscViewerASCIIPushTab()`
4455c6c1daeSBarry Smith 
446c410d8ccSBarry Smith   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
4475c6c1daeSBarry Smith 
44820f4b53cSBarry Smith   Input Parameter:
449811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
4505c6c1daeSBarry Smith 
4515c6c1daeSBarry Smith   Level: developer
4525c6c1daeSBarry Smith 
453d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
454db781477SPatrick Sanan           `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
455db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
4565c6c1daeSBarry Smith @*/
457d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
458d71ae5a4SJacob Faibussowitsch {
4595c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4605c6c1daeSBarry Smith   PetscBool          iascii;
4615c6c1daeSBarry Smith 
4625c6c1daeSBarry Smith   PetscFunctionBegin;
4635c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
4649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4655c6c1daeSBarry Smith   if (iascii) {
46608401ef6SPierre Jolivet     PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed");
4675c6c1daeSBarry Smith     ascii->tab--;
4685c6c1daeSBarry Smith   }
4693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4705c6c1daeSBarry Smith }
4715c6c1daeSBarry Smith 
4725c6c1daeSBarry Smith /*@
473c410d8ccSBarry Smith   PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer`
4745c6c1daeSBarry Smith 
475c410d8ccSBarry Smith   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
4765c6c1daeSBarry Smith 
4775c6c1daeSBarry Smith   Input Parameters:
478811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
479811af0c4SBarry Smith - flg    - `PETSC_TRUE` or `PETSC_FALSE`
4805c6c1daeSBarry Smith 
4815c6c1daeSBarry Smith   Level: developer
4825c6c1daeSBarry Smith 
483d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
484db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
485db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
4865c6c1daeSBarry Smith @*/
487d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
488d71ae5a4SJacob Faibussowitsch {
4895c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4905c6c1daeSBarry Smith   PetscBool          iascii;
4915c6c1daeSBarry Smith 
4925c6c1daeSBarry Smith   PetscFunctionBegin;
4935c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
4949566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4955c6c1daeSBarry Smith   if (iascii) {
496a297a907SKarl Rupp     if (flg) ascii->tab = ascii->tab_store;
497a297a907SKarl Rupp     else {
4985c6c1daeSBarry Smith       ascii->tab_store = ascii->tab;
4995c6c1daeSBarry Smith       ascii->tab       = 0;
5005c6c1daeSBarry Smith     }
5015c6c1daeSBarry Smith   }
5023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5035c6c1daeSBarry Smith }
5045c6c1daeSBarry Smith 
505e4096674SBarry Smith #if defined(PETSC_USE_FORTRAN_BINDINGS)
506e4096674SBarry Smith 
507e4096674SBarry Smith   #if defined(PETSC_HAVE_FORTRAN_CAPS)
508e4096674SBarry Smith     #define petscviewerasciiopenwithfileunit_ PETSCVIEWERASCIIOPENWITHFILEUNIT
509e4096674SBarry Smith     #define petscviewerasciisetfilefileunit_  PETSCVIEWERASCIISETFILEUNIT
510e4096674SBarry Smith     #define petscfortranprinttounit_          PETSCFORTRANPRINTTOUNIT
511e4096674SBarry Smith   #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
512e4096674SBarry Smith     #define petscviewerasciiopenwithfileunit_ petscviewerasciiopenwithfileunit
513e4096674SBarry Smith     #define petscviewerasciisetfileunit_      petscviewerasciisetfileunit
514e4096674SBarry Smith     #define petscfortranprinttounit_          petscfortranprinttounit
515e4096674SBarry Smith   #endif
516e4096674SBarry Smith 
517e4096674SBarry Smith   #if defined(__cplusplus)
518e4096674SBarry Smith extern "C" void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
519e4096674SBarry Smith   #else
520e4096674SBarry Smith extern void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
521e4096674SBarry Smith   #endif
522e4096674SBarry Smith 
523e4096674SBarry Smith   #define PETSCDEFAULTBUFFERSIZE 8 * 1024
524e4096674SBarry Smith 
52510450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
526489d2c6aSPierre Jolivet /*MC
527*baca6076SPierre Jolivet   PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` to write to a Fortran IO unit
528e4096674SBarry Smith 
52910450e9eSJacob Faibussowitsch   Synopsis:
53010450e9eSJacob Faibussowitsch   #include <petscviewer.h>
531e4096674SBarry Smith   void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr)
532e4096674SBarry Smith 
533e4096674SBarry Smith   Input Parameters:
534e4096674SBarry Smith + lab  - the viewer
535e4096674SBarry Smith - unit - the unit number
536e4096674SBarry Smith 
537e4096674SBarry Smith   Output Parameter:
538e4096674SBarry Smith . ierr - the error code
539e4096674SBarry Smith 
54010450e9eSJacob Faibussowitsch   Level: intermediate
54110450e9eSJacob Faibussowitsch 
542e4096674SBarry Smith   Note:
543e4096674SBarry Smith   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
544e4096674SBarry Smith 
545aec76313SJacob Faibussowitsch   Fortran Notes:
546e4096674SBarry Smith   Only for Fortran, use  `PetscViewerASCIISetFILE()` for C
547e4096674SBarry Smith 
548e4096674SBarry Smith .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`
549489d2c6aSPierre Jolivet M*/
550e4096674SBarry Smith PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, PetscInt *unit, PetscErrorCode *ierr)
551e4096674SBarry Smith {
552e4096674SBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)(*lab)->data;
553e4096674SBarry Smith 
554e4096674SBarry Smith   if (vascii->mode == FILE_MODE_READ) {
555e4096674SBarry Smith     *ierr = PETSC_ERR_ARG_WRONGSTATE;
556e4096674SBarry Smith     return;
557e4096674SBarry Smith   }
558e4096674SBarry Smith   vascii->fileunit = *unit;
559e4096674SBarry Smith }
560e4096674SBarry Smith 
56110450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
562489d2c6aSPierre Jolivet /*MC
563*baca6076SPierre Jolivet   PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit
564e4096674SBarry Smith 
56510450e9eSJacob Faibussowitsch   Synopsis:
56610450e9eSJacob Faibussowitsch   #include <petscviewer.h>
567e4096674SBarry Smith   void PetscViewerASCIIOpenWithFileUnit(MPI_Comm comm, PetscInt unit, PetscViewer viewer, PetscErrorCode ierr)
568e4096674SBarry Smith 
569e4096674SBarry Smith   Input Parameters:
570e4096674SBarry Smith + comm - the `MPI_Comm` to share the viewer
571e4096674SBarry Smith - unit - the unit number
572e4096674SBarry Smith 
573e4096674SBarry Smith   Output Parameters:
574e4096674SBarry Smith + lab  - the viewer
575e4096674SBarry Smith - ierr - the error code
576e4096674SBarry Smith 
57710450e9eSJacob Faibussowitsch   Level: intermediate
57810450e9eSJacob Faibussowitsch 
579e4096674SBarry Smith   Note:
580e4096674SBarry Smith   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
581e4096674SBarry Smith 
582aec76313SJacob Faibussowitsch   Fortran Notes:
583e4096674SBarry Smith   Only for Fortran, use  `PetscViewerASCIIOpenWithFILE()` for C
584e4096674SBarry Smith 
585e4096674SBarry Smith .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()`
586489d2c6aSPierre Jolivet M*/
587e4096674SBarry Smith PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Comm *comm, PetscInt *unit, PetscViewer *lab, PetscErrorCode *ierr)
588e4096674SBarry Smith {
589e4096674SBarry Smith   *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab);
590e4096674SBarry Smith   if (*ierr) return;
591e4096674SBarry Smith   *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII);
592e4096674SBarry Smith   if (*ierr) return;
593e4096674SBarry Smith   *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE);
594e4096674SBarry Smith   if (*ierr) return;
595e4096674SBarry Smith   petscviewerasciisetfileunit_(lab, unit, ierr);
596e4096674SBarry Smith }
597e4096674SBarry Smith 
598e4096674SBarry Smith static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
599e4096674SBarry Smith {
600e4096674SBarry Smith   PetscErrorCode ierr;
601e4096674SBarry Smith   char           str[PETSCDEFAULTBUFFERSIZE];
602e4096674SBarry Smith   size_t         len;
603e4096674SBarry Smith 
604e4096674SBarry Smith   PetscFunctionBegin;
605e4096674SBarry Smith   PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp));
606e4096674SBarry Smith   PetscCall(PetscStrlen(str, &len));
607e4096674SBarry Smith   petscfortranprinttounit_(&unit, str, &ierr, (int)len);
608e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
609e4096674SBarry Smith }
610e4096674SBarry Smith 
611e4096674SBarry Smith static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
612e4096674SBarry Smith {
613e4096674SBarry Smith   PetscErrorCode ierr;
614e4096674SBarry Smith   size_t         len;
615e4096674SBarry Smith 
616e4096674SBarry Smith   PetscFunctionBegin;
617e4096674SBarry Smith   PetscCall(PetscStrlen(str, &len));
618e4096674SBarry Smith   petscfortranprinttounit_(&unit, str, &ierr, (int)len);
619e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
620e4096674SBarry Smith }
621e4096674SBarry Smith 
622e4096674SBarry Smith #else
623e4096674SBarry Smith 
624e4096674SBarry Smith /* these will never be used; but are needed to link with */
625e4096674SBarry Smith static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
626e4096674SBarry Smith {
627e4096674SBarry Smith   PetscFunctionBegin;
628e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
629e4096674SBarry Smith }
630e4096674SBarry Smith 
631e4096674SBarry Smith static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
632e4096674SBarry Smith {
633e4096674SBarry Smith   PetscFunctionBegin;
634e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
635e4096674SBarry Smith }
636e4096674SBarry Smith #endif
637e4096674SBarry Smith 
6385c6c1daeSBarry Smith /*@C
6395c6c1daeSBarry Smith   PetscViewerASCIIPrintf - Prints to a file, only from the first
6403f423023SBarry Smith   processor in the `PetscViewer` of type `PETSCVIEWERASCII`
6415c6c1daeSBarry Smith 
642c410d8ccSBarry Smith   Not Collective, but only the first MPI rank in the viewer has any effect
6435c6c1daeSBarry Smith 
6445c6c1daeSBarry Smith   Input Parameters:
645811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
6465c6c1daeSBarry Smith - format - the usual printf() format string
6475c6c1daeSBarry Smith 
6485c6c1daeSBarry Smith   Level: developer
6495c6c1daeSBarry Smith 
650aec76313SJacob Faibussowitsch   Fortran Notes:
651c410d8ccSBarry Smith   The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran.
6525c6c1daeSBarry Smith   That is, you can only pass a single character string from Fortran.
6535c6c1daeSBarry Smith 
654d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
655db781477SPatrick Sanan           `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
656db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
6575c6c1daeSBarry Smith @*/
658d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
659d71ae5a4SJacob Faibussowitsch {
6605c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
6615c6c1daeSBarry Smith   PetscMPIInt        rank;
662dd2fa690SBarry Smith   PetscInt           tab, intab = ascii->tab;
6635c6c1daeSBarry Smith   FILE              *fd = ascii->fd;
6643f08860eSBarry Smith   PetscBool          iascii;
6655c6c1daeSBarry Smith 
6665c6c1daeSBarry Smith   PetscFunctionBegin;
6675c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
66828b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
6694f572ea9SToby Isaac   PetscAssertPointer(format, 2);
6709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
67128b400f6SJacob Faibussowitsch   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
6729566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
6733ba16761SJacob Faibussowitsch   if (rank) PetscFunctionReturn(PETSC_SUCCESS);
6743f08860eSBarry Smith 
6753f08860eSBarry Smith   if (ascii->bviewer) { /* pass string up to parent viewer */
6763f08860eSBarry Smith     char   *string;
6773f08860eSBarry Smith     va_list Argp;
6783f08860eSBarry Smith     size_t  fullLength;
6793f08860eSBarry Smith 
6809566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
6813f08860eSBarry Smith     va_start(Argp, format);
6829566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(string, QUEUESTRINGSIZE, format, &fullLength, Argp));
6833f08860eSBarry Smith     va_end(Argp);
6849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%s", string));
6859566063dSJacob Faibussowitsch     PetscCall(PetscFree(string));
6863f08860eSBarry Smith   } else { /* write directly to file */
6875c6c1daeSBarry Smith     va_list Argp;
688559f443fSBarry Smith     /* flush my own messages that I may have queued up */
689559f443fSBarry Smith     PrintfQueue next = ascii->petsc_printfqueuebase, previous;
690559f443fSBarry Smith     PetscInt    i;
691559f443fSBarry Smith     for (i = 0; i < ascii->petsc_printfqueuelength; i++) {
692e4096674SBarry Smith       if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "%s", next->string));
693e4096674SBarry Smith       else PetscCall(PetscFPrintfFortran(ascii->fileunit, next->string));
694559f443fSBarry Smith       previous = next;
695559f443fSBarry Smith       next     = next->next;
6969566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
6979566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
698559f443fSBarry Smith     }
69902c9f0b5SLisandro Dalcin     ascii->petsc_printfqueue       = NULL;
700559f443fSBarry Smith     ascii->petsc_printfqueuelength = 0;
701dd2fa690SBarry Smith     tab                            = intab;
702e4096674SBarry Smith     while (tab--) {
703e4096674SBarry Smith       if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "  "));
704e4096674SBarry Smith       else PetscCall(PetscFPrintfFortran(ascii->fileunit, "   "));
705e4096674SBarry Smith     }
7065c6c1daeSBarry Smith 
7075c6c1daeSBarry Smith     va_start(Argp, format);
708e4096674SBarry Smith     if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
709e4096674SBarry Smith     else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
710eae3dc7dSJacob Faibussowitsch     va_end(Argp);
711c69effb2SJacob Faibussowitsch     PetscCall(PetscFFlush(fd));
7125c6c1daeSBarry Smith   }
7133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7145c6c1daeSBarry Smith }
7155c6c1daeSBarry Smith 
7165c6c1daeSBarry Smith /*@C
717c410d8ccSBarry Smith   PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.
7185c6c1daeSBarry Smith 
719c3339decSBarry Smith   Collective
7205c6c1daeSBarry Smith 
7215c6c1daeSBarry Smith   Input Parameters:
7223f423023SBarry Smith + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
7235c6c1daeSBarry Smith - name   - the name of the file it should use
7245c6c1daeSBarry Smith 
7255c6c1daeSBarry Smith   Level: advanced
7265c6c1daeSBarry Smith 
727c410d8ccSBarry Smith   Note:
728c410d8ccSBarry Smith   This will have no effect on viewers that are not related to files
729c410d8ccSBarry Smith 
730d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
731db781477SPatrick Sanan           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
7325c6c1daeSBarry Smith @*/
733d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
734d71ae5a4SJacob Faibussowitsch {
735cc843e7aSLisandro Dalcin   char filename[PETSC_MAX_PATH_LEN];
7365c6c1daeSBarry Smith 
7375c6c1daeSBarry Smith   PetscFunctionBegin;
7385c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
7394f572ea9SToby Isaac   PetscAssertPointer(name, 2);
7409566063dSJacob Faibussowitsch   PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
741cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
7423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7435c6c1daeSBarry Smith }
7445c6c1daeSBarry Smith 
7455c6c1daeSBarry Smith /*@C
746c410d8ccSBarry Smith   PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using
7475c6c1daeSBarry Smith 
7485c6c1daeSBarry Smith   Not Collective
7495c6c1daeSBarry Smith 
7505c6c1daeSBarry Smith   Input Parameter:
7513f423023SBarry Smith . viewer - the `PetscViewer`
7525c6c1daeSBarry Smith 
7535c6c1daeSBarry Smith   Output Parameter:
7545c6c1daeSBarry Smith . name - the name of the file it is using
7555c6c1daeSBarry Smith 
7565c6c1daeSBarry Smith   Level: advanced
7575c6c1daeSBarry Smith 
758c410d8ccSBarry Smith   Note:
759c410d8ccSBarry Smith   This will have no effect on viewers that are not related to files
760c410d8ccSBarry Smith 
761d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
7625c6c1daeSBarry Smith @*/
763d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
764d71ae5a4SJacob Faibussowitsch {
7655c6c1daeSBarry Smith   PetscFunctionBegin;
7665c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
7674f572ea9SToby Isaac   PetscAssertPointer(name, 2);
768cac4c232SBarry Smith   PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
7693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7705c6c1daeSBarry Smith }
7715c6c1daeSBarry Smith 
77234e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
773d71ae5a4SJacob Faibussowitsch {
7745c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
7755c6c1daeSBarry Smith 
7765c6c1daeSBarry Smith   PetscFunctionBegin;
7775c6c1daeSBarry Smith   *name = vascii->filename;
7783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7795c6c1daeSBarry Smith }
7805c6c1daeSBarry Smith 
781bf31d2d3SBarry Smith #include <errno.h>
78234e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
783d71ae5a4SJacob Faibussowitsch {
7845c6c1daeSBarry Smith   size_t             len;
785bbcf679cSJacob Faibussowitsch   char               fname[PETSC_MAX_PATH_LEN], *gz = NULL;
7865c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
7875c6c1daeSBarry Smith   PetscBool          isstderr, isstdout;
7885c6c1daeSBarry Smith   PetscMPIInt        rank;
7895c6c1daeSBarry Smith 
7905c6c1daeSBarry Smith   PetscFunctionBegin;
7919566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileClose_ASCII(viewer));
7923ba16761SJacob Faibussowitsch   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
7939566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &vascii->filename));
7945c6c1daeSBarry Smith 
7955c6c1daeSBarry Smith   /* Is this file to be compressed */
7965c6c1daeSBarry Smith   vascii->storecompressed = PETSC_FALSE;
797a297a907SKarl Rupp 
7989566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
7995c6c1daeSBarry Smith   if (gz) {
8009566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(gz, &len));
8015c6c1daeSBarry Smith     if (len == 3) {
80208401ef6SPierre 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");
8035c6c1daeSBarry Smith       *gz                     = 0;
8045c6c1daeSBarry Smith       vascii->storecompressed = PETSC_TRUE;
8055c6c1daeSBarry Smith     }
8065c6c1daeSBarry Smith   }
8079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
808dd400576SPatrick Sanan   if (rank == 0) {
8099566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
8109566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
8115c6c1daeSBarry Smith     /* empty filename means stdout */
8125c6c1daeSBarry Smith     if (name[0] == 0) isstdout = PETSC_TRUE;
8135c6c1daeSBarry Smith     if (isstderr) vascii->fd = PETSC_STDERR;
8145c6c1daeSBarry Smith     else if (isstdout) vascii->fd = PETSC_STDOUT;
8155c6c1daeSBarry Smith     else {
8169566063dSJacob Faibussowitsch       PetscCall(PetscFixFilename(name, fname));
8175c6c1daeSBarry Smith       switch (vascii->mode) {
818d71ae5a4SJacob Faibussowitsch       case FILE_MODE_READ:
819d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "r");
820d71ae5a4SJacob Faibussowitsch         break;
821d71ae5a4SJacob Faibussowitsch       case FILE_MODE_WRITE:
822d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "w");
823d71ae5a4SJacob Faibussowitsch         break;
824d71ae5a4SJacob Faibussowitsch       case FILE_MODE_APPEND:
825d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "a");
826d71ae5a4SJacob Faibussowitsch         break;
8275c6c1daeSBarry Smith       case FILE_MODE_UPDATE:
8285c6c1daeSBarry Smith         vascii->fd = fopen(fname, "r+");
829a297a907SKarl Rupp         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
8305c6c1daeSBarry Smith         break;
8315c6c1daeSBarry Smith       case FILE_MODE_APPEND_UPDATE:
8325c6c1daeSBarry Smith         /* I really want a file which is opened at the end for updating,
8335c6c1daeSBarry Smith            not a+, which opens at the beginning, but makes writes at the end.
8345c6c1daeSBarry Smith         */
8355c6c1daeSBarry Smith         vascii->fd = fopen(fname, "r+");
836a297a907SKarl Rupp         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
8373ba16761SJacob Faibussowitsch         else {
8383ba16761SJacob Faibussowitsch           int ret = fseek(vascii->fd, 0, SEEK_END);
8393ba16761SJacob Faibussowitsch           PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
8403ba16761SJacob Faibussowitsch         }
8415c6c1daeSBarry Smith         break;
842d71ae5a4SJacob Faibussowitsch       default:
843d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
8445c6c1daeSBarry Smith       }
845bf31d2d3SBarry Smith       PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
8465c6c1daeSBarry Smith     }
8475c6c1daeSBarry Smith   }
8483ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
8493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8505c6c1daeSBarry Smith }
8515c6c1daeSBarry Smith 
85234e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
853d71ae5a4SJacob Faibussowitsch {
8545c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
8555c6c1daeSBarry Smith 
8565c6c1daeSBarry Smith   PetscFunctionBegin;
8579566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
85828b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
859e5afcf28SBarry Smith   /*
8609530cbd7SBarry Smith      The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
8619530cbd7SBarry 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
8629530cbd7SBarry Smith      (since the count never gets to zero) in some examples this displays information that otherwise would be lost
8639530cbd7SBarry Smith 
8649530cbd7SBarry Smith      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
8659530cbd7SBarry Smith      PCView_GASM().
866e5afcf28SBarry Smith   */
8679566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
8689566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(subcomm, outviewer));
8699566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
8709566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
8715c6c1daeSBarry Smith   ovascii            = (PetscViewer_ASCII *)(*outviewer)->data;
8725c6c1daeSBarry Smith   ovascii->fd        = vascii->fd;
8735c6c1daeSBarry Smith   ovascii->tab       = vascii->tab;
874ba5a0b41SBarry Smith   ovascii->closefile = PETSC_FALSE;
8755c6c1daeSBarry Smith 
8765c6c1daeSBarry Smith   vascii->sviewer                                      = *outviewer;
8775c6c1daeSBarry Smith   (*outviewer)->format                                 = viewer->format;
8785c6c1daeSBarry Smith   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
8793f08860eSBarry Smith   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
8803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8815c6c1daeSBarry Smith }
8825c6c1daeSBarry Smith 
88334e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
884d71ae5a4SJacob Faibussowitsch {
8855c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
8865c6c1daeSBarry Smith 
8875c6c1daeSBarry Smith   PetscFunctionBegin;
88828b400f6SJacob Faibussowitsch   PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
88908401ef6SPierre Jolivet   PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");
8905c6c1daeSBarry Smith 
8919566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
892e5afcf28SBarry Smith   ascii->sviewer             = NULL;
8935c6c1daeSBarry Smith   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
8949566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(outviewer));
8959566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8975c6c1daeSBarry Smith }
8985c6c1daeSBarry Smith 
89934e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
900d71ae5a4SJacob Faibussowitsch {
9012bf49c77SBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
9022bf49c77SBarry Smith 
9032bf49c77SBarry Smith   PetscFunctionBegin;
90448a46eb9SPierre Jolivet   if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
9053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9062bf49c77SBarry Smith }
9072bf49c77SBarry Smith 
9088556b5ebSBarry Smith /*MC
9098556b5ebSBarry Smith    PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file
9108556b5ebSBarry Smith 
911811af0c4SBarry Smith   Level: beginner
912811af0c4SBarry Smith 
913d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
914db781477SPatrick Sanan           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
915db781477SPatrick Sanan           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
9168556b5ebSBarry Smith M*/
917d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
918d71ae5a4SJacob Faibussowitsch {
9195c6c1daeSBarry Smith   PetscViewer_ASCII *vascii;
9205c6c1daeSBarry Smith 
9215c6c1daeSBarry Smith   PetscFunctionBegin;
9224dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&vascii));
9235c6c1daeSBarry Smith   viewer->data = (void *)vascii;
9245c6c1daeSBarry Smith 
9255c6c1daeSBarry Smith   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
9265c6c1daeSBarry Smith   viewer->ops->flush            = PetscViewerFlush_ASCII;
927559f443fSBarry Smith   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
928559f443fSBarry Smith   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
9292bf49c77SBarry Smith   viewer->ops->view             = PetscViewerView_ASCII;
9301d641e7bSMichael Lange   viewer->ops->read             = PetscViewerASCIIRead;
9315c6c1daeSBarry Smith 
9325c6c1daeSBarry Smith   /* defaults to stdout unless set with PetscViewerFileSetName() */
9335c6c1daeSBarry Smith   vascii->fd        = PETSC_STDOUT;
9345c6c1daeSBarry Smith   vascii->mode      = FILE_MODE_WRITE;
93502c9f0b5SLisandro Dalcin   vascii->bviewer   = NULL;
93602c9f0b5SLisandro Dalcin   vascii->subviewer = NULL;
93702c9f0b5SLisandro Dalcin   vascii->sviewer   = NULL;
9385c6c1daeSBarry Smith   vascii->tab       = 0;
9395c6c1daeSBarry Smith   vascii->tab_store = 0;
94002c9f0b5SLisandro Dalcin   vascii->filename  = NULL;
9415c6c1daeSBarry Smith   vascii->closefile = PETSC_TRUE;
9425c6c1daeSBarry Smith 
9439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
9449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
9459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
9469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
9473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9485c6c1daeSBarry Smith }
9495c6c1daeSBarry Smith 
9505c6c1daeSBarry Smith /*@C
951c410d8ccSBarry Smith   PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
9525c6c1daeSBarry Smith   several processors.  Output of the first processor is followed by that of the
9535c6c1daeSBarry Smith   second, etc.
9545c6c1daeSBarry Smith 
955c410d8ccSBarry Smith   Not Collective, must call collective `PetscViewerFlush()` to get the results flushed
9565c6c1daeSBarry Smith 
9575c6c1daeSBarry Smith   Input Parameters:
958811af0c4SBarry Smith + viewer - the `PETSCVIEWERASCII` `PetscViewer`
9595c6c1daeSBarry Smith - format - the usual printf() format string
9605c6c1daeSBarry Smith 
9615c6c1daeSBarry Smith   Level: intermediate
9625c6c1daeSBarry Smith 
96395452b02SPatrick Sanan   Notes:
964811af0c4SBarry Smith   You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
965e6abc3ddSVáclav Hapla   Then you can do multiple independent calls to this routine.
966811af0c4SBarry Smith 
967811af0c4SBarry Smith   The actual synchronized print is then done using `PetscViewerFlush()`.
968811af0c4SBarry Smith   `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
969e6abc3ddSVáclav Hapla   to conclude the "synchronized session".
970811af0c4SBarry Smith 
971e6abc3ddSVáclav Hapla   So the typical calling sequence looks like
972811af0c4SBarry Smith .vb
973811af0c4SBarry Smith     PetscViewerASCIIPushSynchronized(viewer);
974811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
975811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
976811af0c4SBarry Smith     ...
977811af0c4SBarry Smith     PetscViewerFlush(viewer);
978811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
979811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
980811af0c4SBarry Smith     ...
981811af0c4SBarry Smith     PetscViewerFlush(viewer);
982811af0c4SBarry Smith    PetscViewerASCIIPopSynchronized(viewer);
983811af0c4SBarry Smith .ve
9845c6c1daeSBarry Smith 
985aec76313SJacob Faibussowitsch   Fortran Notes:
9865c6c1daeSBarry Smith   Can only print a single character* string
9875c6c1daeSBarry Smith 
988d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
989db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
990db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
9915c6c1daeSBarry Smith @*/
992d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
993d71ae5a4SJacob Faibussowitsch {
9945c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
9953f08860eSBarry Smith   PetscMPIInt        rank;
9965c6c1daeSBarry Smith   PetscInt           tab = vascii->tab;
9975c6c1daeSBarry Smith   MPI_Comm           comm;
9985c6c1daeSBarry Smith   FILE              *fp;
999559f443fSBarry Smith   PetscBool          iascii, hasbviewer = PETSC_FALSE;
10005c6c1daeSBarry Smith 
10015c6c1daeSBarry Smith   PetscFunctionBegin;
10025c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
10034f572ea9SToby Isaac   PetscAssertPointer(format, 2);
10049566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
100528b400f6SJacob Faibussowitsch   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
100628b400f6SJacob Faibussowitsch   PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");
10075c6c1daeSBarry Smith 
10089566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
10099566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10105c6c1daeSBarry Smith 
1011559f443fSBarry Smith   if (vascii->bviewer) {
1012559f443fSBarry Smith     hasbviewer = PETSC_TRUE;
1013dd400576SPatrick Sanan     if (rank == 0) {
1014559f443fSBarry Smith       vascii = (PetscViewer_ASCII *)vascii->bviewer->data;
10159566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
10169566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
1017559f443fSBarry Smith     }
1018559f443fSBarry Smith   }
10193f08860eSBarry Smith 
1020559f443fSBarry Smith   fp = vascii->fd;
1021559f443fSBarry Smith 
1022dd400576SPatrick Sanan   if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */
10235c6c1daeSBarry Smith     va_list Argp;
1024559f443fSBarry Smith     /* flush my own messages that I may have queued up */
1025559f443fSBarry Smith     PrintfQueue next = vascii->petsc_printfqueuebase, previous;
1026559f443fSBarry Smith     PetscInt    i;
1027559f443fSBarry Smith     for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
10289566063dSJacob Faibussowitsch       PetscCall(PetscFPrintf(comm, fp, "%s", next->string));
1029559f443fSBarry Smith       previous = next;
1030559f443fSBarry Smith       next     = next->next;
10319566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
10329566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
1033559f443fSBarry Smith     }
103402c9f0b5SLisandro Dalcin     vascii->petsc_printfqueue       = NULL;
1035559f443fSBarry Smith     vascii->petsc_printfqueuelength = 0;
10365c6c1daeSBarry Smith 
103748a46eb9SPierre Jolivet     while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, "  "));
10385c6c1daeSBarry Smith 
10395c6c1daeSBarry Smith     va_start(Argp, format);
10409566063dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(fp, format, Argp));
1041eae3dc7dSJacob Faibussowitsch     va_end(Argp);
1042c69effb2SJacob Faibussowitsch     PetscCall(PetscFFlush(fp));
10435c6c1daeSBarry Smith     if (petsc_history) {
10445c6c1daeSBarry Smith       va_start(Argp, format);
10459566063dSJacob Faibussowitsch       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1046eae3dc7dSJacob Faibussowitsch       va_end(Argp);
1047c69effb2SJacob Faibussowitsch       PetscCall(PetscFFlush(petsc_history));
10485c6c1daeSBarry Smith     }
10495c6c1daeSBarry Smith     va_end(Argp);
1050559f443fSBarry Smith   } else { /* other processors add to queue */
10515c6c1daeSBarry Smith     char       *string;
10525c6c1daeSBarry Smith     va_list     Argp;
10535c6c1daeSBarry Smith     size_t      fullLength;
10545c6c1daeSBarry Smith     PrintfQueue next;
10555c6c1daeSBarry Smith 
10569566063dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
1057559f443fSBarry Smith     if (vascii->petsc_printfqueue) {
1058559f443fSBarry Smith       vascii->petsc_printfqueue->next = next;
1059559f443fSBarry Smith       vascii->petsc_printfqueue       = next;
1060a297a907SKarl Rupp     } else {
1061559f443fSBarry Smith       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1062a297a907SKarl Rupp     }
1063559f443fSBarry Smith     vascii->petsc_printfqueuelength++;
10645c6c1daeSBarry Smith     next->size = QUEUESTRINGSIZE;
10659566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(next->size, &next->string));
10665c6c1daeSBarry Smith     string = next->string;
10675c6c1daeSBarry Smith     tab *= 2;
1068ad540459SPierre Jolivet     while (tab--) *string++ = ' ';
10695c6c1daeSBarry Smith     va_start(Argp, format);
10709566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
10715c6c1daeSBarry Smith     va_end(Argp);
1072cb500232SBarry Smith     if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
10739566063dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
107414416c0eSBarry Smith       next->size = fullLength + 2 * vascii->tab;
10759566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(next->size, &next->string));
107614416c0eSBarry Smith       string = next->string;
107714416c0eSBarry Smith       tab    = 2 * vascii->tab;
1078ad540459SPierre Jolivet       while (tab--) *string++ = ' ';
107914416c0eSBarry Smith       va_start(Argp, format);
10809566063dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
108114416c0eSBarry Smith       va_end(Argp);
108214416c0eSBarry Smith     }
10835c6c1daeSBarry Smith   }
10843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10855c6c1daeSBarry Smith }
10865c6c1daeSBarry Smith 
10872655f987SMichael Lange /*@C
1088c410d8ccSBarry Smith   PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file
10892655f987SMichael Lange 
1090c410d8ccSBarry Smith   Only MPI rank 0 in the `PetscViewer` may call this
10912655f987SMichael Lange 
10922655f987SMichael Lange   Input Parameters:
10933f423023SBarry Smith + viewer - the `PETSCVIEWERASCII` viewer
1094c410d8ccSBarry Smith . data   - location to write the data, treated as an array of type indicated by `datatype`
1095060da220SMatthew G. Knepley . num    - number of items of data to read
1096aec76313SJacob Faibussowitsch - dtype  - type of data to read
10972655f987SMichael Lange 
109820f4b53cSBarry Smith   Output Parameter:
10993f423023SBarry Smith . count - number of items of data actually read, or `NULL`
1100f8e4bde8SMatthew G. Knepley 
11012655f987SMichael Lange   Level: beginner
11022655f987SMichael Lange 
1103d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1104db781477SPatrick Sanan           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1105db781477SPatrick Sanan           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
11062655f987SMichael Lange @*/
1107d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1108d71ae5a4SJacob Faibussowitsch {
11092655f987SMichael Lange   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
11102655f987SMichael Lange   FILE              *fd     = vascii->fd;
11112655f987SMichael Lange   PetscInt           i;
11123b7fe8c3SMatthew G. Knepley   int                ret = 0;
1113f8859db6SBarry Smith   PetscMPIInt        rank;
11142655f987SMichael Lange 
11152655f987SMichael Lange   PetscFunctionBegin;
11162655f987SMichael Lange   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
11179566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1118c5853193SPierre Jolivet   PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1119060da220SMatthew G. Knepley   for (i = 0; i < num; i++) {
1120f8e4bde8SMatthew G. Knepley     if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1121f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1122a05e1a72SSatish Balay     else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1123f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
11249e3e4c22SLisandro Dalcin     else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1125972064b6SLisandro Dalcin     else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1126f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1127f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1128a6e181c6SToby Isaac #if defined(PETSC_USE_REAL___FLOAT128)
1129fba955ccSBarry Smith     else if (dtype == PETSC___FLOAT128) {
1130fba955ccSBarry Smith       double tmp;
1131fba955ccSBarry Smith       ret                     = fscanf(fd, "%lg", &tmp);
1132a6e181c6SToby Isaac       ((__float128 *)data)[i] = tmp;
1133a6e181c6SToby Isaac     }
1134fba955ccSBarry Smith #endif
11359371c9d4SSatish Balay     else
11369371c9d4SSatish Balay       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
113728b400f6SJacob Faibussowitsch     PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1138f7d195e4SLawrence Mitchell     if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
11392655f987SMichael Lange   }
1140060da220SMatthew G. Knepley   if (count) *count = i;
114108401ef6SPierre Jolivet   else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
11423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11432655f987SMichael Lange }
1144