xref: /petsc/src/sys/classes/viewer/impls/ascii/filev.c (revision 648c30bcb65f74c3cbd15d7a91a7ed7c1890e25b)
1665c2dedSJed Brown #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h> /*I "petscviewer.h" I*/
25c6c1daeSBarry Smith 
35c6c1daeSBarry Smith #define QUEUESTRINGSIZE 8192
45c6c1daeSBarry Smith 
5d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer)
6d71ae5a4SJacob Faibussowitsch {
75c6c1daeSBarry Smith   PetscMPIInt        rank;
85c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
95c6c1daeSBarry Smith   int                err;
105c6c1daeSBarry Smith 
115c6c1daeSBarry Smith   PetscFunctionBegin;
1228b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
14dd400576SPatrick Sanan   if (rank == 0 && vascii->fd != stderr && vascii->fd != PETSC_STDOUT) {
155c6c1daeSBarry Smith     if (vascii->fd && vascii->closefile) {
165c6c1daeSBarry Smith       err = fclose(vascii->fd);
1728b400f6SJacob Faibussowitsch       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
185c6c1daeSBarry Smith     }
195c6c1daeSBarry Smith     if (vascii->storecompressed) {
205c6c1daeSBarry Smith       char  par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN];
215c6c1daeSBarry Smith       FILE *fp;
229566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(par, "gzip ", sizeof(par)));
239566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(par, vascii->filename, sizeof(par)));
245c6c1daeSBarry Smith #if defined(PETSC_HAVE_POPEN)
259566063dSJacob Faibussowitsch       PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp));
2600045ab3SPierre Jolivet       PetscCheck(!fgets(buf, 1024, fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from compression command %s %s", par, buf);
279566063dSJacob Faibussowitsch       PetscCall(PetscPClose(PETSC_COMM_SELF, fp));
285c6c1daeSBarry Smith #else
295c6c1daeSBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
305c6c1daeSBarry Smith #endif
315c6c1daeSBarry Smith     }
325c6c1daeSBarry Smith   }
339566063dSJacob Faibussowitsch   PetscCall(PetscFree(vascii->filename));
343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
355c6c1daeSBarry Smith }
365c6c1daeSBarry Smith 
3734e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
38d71ae5a4SJacob Faibussowitsch {
395c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
405c6c1daeSBarry Smith   PetscViewerLink   *vlink;
415c6c1daeSBarry Smith   PetscBool          flg;
425c6c1daeSBarry Smith 
435c6c1daeSBarry Smith   PetscFunctionBegin;
4428b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
459566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileClose_ASCII(viewer));
469566063dSJacob Faibussowitsch   PetscCall(PetscFree(vascii));
475c6c1daeSBarry Smith 
485c6c1daeSBarry Smith   /* remove the viewer from the list in the MPI Communicator */
4948a46eb9SPierre 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));
505c6c1daeSBarry Smith 
519566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
525c6c1daeSBarry Smith   if (flg) {
535c6c1daeSBarry Smith     if (vlink && vlink->viewer == viewer) {
54e5840a18SBarry Smith       if (vlink->next) {
559566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next));
56e5840a18SBarry Smith       } else {
579566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval));
58e5840a18SBarry Smith       }
599566063dSJacob Faibussowitsch       PetscCall(PetscFree(vlink));
605c6c1daeSBarry Smith     } else {
615c6c1daeSBarry Smith       while (vlink && vlink->next) {
625c6c1daeSBarry Smith         if (vlink->next->viewer == viewer) {
635c6c1daeSBarry Smith           PetscViewerLink *nv = vlink->next;
645c6c1daeSBarry Smith           vlink->next         = vlink->next->next;
659566063dSJacob Faibussowitsch           PetscCall(PetscFree(nv));
665c6c1daeSBarry Smith         }
675c6c1daeSBarry Smith         vlink = vlink->next;
685c6c1daeSBarry Smith       }
695c6c1daeSBarry Smith     }
705c6c1daeSBarry Smith   }
71aa139df6SJed Brown 
72aa139df6SJed Brown   if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
73aa139df6SJed Brown     PetscViewer aviewer;
749566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
7548a46eb9SPierre Jolivet     if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval));
76aa139df6SJed Brown   }
77aa139df6SJed Brown   if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
78aa139df6SJed Brown     PetscViewer aviewer;
799566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
8048a46eb9SPierre Jolivet     if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval));
81aa139df6SJed Brown   }
822e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
832e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
842e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
852e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
875c6c1daeSBarry Smith }
885c6c1daeSBarry Smith 
8934e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
90d71ae5a4SJacob Faibussowitsch {
915c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
925fd66863SKarl Rupp 
935c6c1daeSBarry Smith   PetscFunctionBegin;
949566063dSJacob Faibussowitsch   PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer));
953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
965c6c1daeSBarry Smith }
975c6c1daeSBarry Smith 
9834e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
99d71ae5a4SJacob Faibussowitsch {
1005c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
101559f443fSBarry Smith   MPI_Comm           comm;
102559f443fSBarry Smith   PetscMPIInt        rank, size;
103559f443fSBarry Smith   FILE              *fd = vascii->fd;
1045c6c1daeSBarry Smith 
1055c6c1daeSBarry Smith   PetscFunctionBegin;
10628b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
1079566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1089566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1099566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
110559f443fSBarry Smith 
111c69effb2SJacob Faibussowitsch   if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd));
1125c6c1daeSBarry Smith 
1135c6c1daeSBarry Smith   if (vascii->allowsynchronized) {
114559f443fSBarry Smith     PetscMPIInt tag, i, j, n = 0, dummy = 0;
115559f443fSBarry Smith     char       *message;
116559f443fSBarry Smith     MPI_Status  status;
117559f443fSBarry Smith 
1189566063dSJacob Faibussowitsch     PetscCall(PetscCommDuplicate(comm, &comm, &tag));
119559f443fSBarry Smith 
120559f443fSBarry Smith     /* First processor waits for messages from all other processors */
121dd400576SPatrick Sanan     if (rank == 0) {
122559f443fSBarry Smith       /* flush my own messages that I may have queued up */
123559f443fSBarry Smith       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
124559f443fSBarry Smith       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
125559f443fSBarry Smith         if (!vascii->bviewer) {
1269566063dSJacob Faibussowitsch           PetscCall(PetscFPrintf(comm, fd, "%s", next->string));
127559f443fSBarry Smith         } else {
1289566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string));
129559f443fSBarry Smith         }
130559f443fSBarry Smith         previous = next;
131559f443fSBarry Smith         next     = next->next;
1329566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous->string));
1339566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous));
134559f443fSBarry Smith       }
13502c9f0b5SLisandro Dalcin       vascii->petsc_printfqueue       = NULL;
136559f443fSBarry Smith       vascii->petsc_printfqueuelength = 0;
137559f443fSBarry Smith       for (i = 1; i < size; i++) {
138559f443fSBarry Smith         /* to prevent a flood of messages to process zero, request each message separately */
1399566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
1409566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
141559f443fSBarry Smith         for (j = 0; j < n; j++) {
142559f443fSBarry Smith           PetscMPIInt size = 0;
143559f443fSBarry Smith 
1449566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
1459566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &message));
1469566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
147559f443fSBarry Smith           if (!vascii->bviewer) {
1489566063dSJacob Faibussowitsch             PetscCall(PetscFPrintf(comm, fd, "%s", message));
149559f443fSBarry Smith           } else {
1509566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message));
151559f443fSBarry Smith           }
1529566063dSJacob Faibussowitsch           PetscCall(PetscFree(message));
153559f443fSBarry Smith         }
154559f443fSBarry Smith       }
155559f443fSBarry Smith     } else { /* other processors send queue to processor 0 */
156559f443fSBarry Smith       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
157559f443fSBarry Smith 
1589566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
1599566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
160559f443fSBarry Smith       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
1619566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
1629566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
163559f443fSBarry Smith         previous = next;
164559f443fSBarry Smith         next     = next->next;
1659566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous->string));
1669566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous));
167559f443fSBarry Smith       }
16802c9f0b5SLisandro Dalcin       vascii->petsc_printfqueue       = NULL;
169559f443fSBarry Smith       vascii->petsc_printfqueuelength = 0;
170559f443fSBarry Smith     }
1719566063dSJacob Faibussowitsch     PetscCall(PetscCommDestroy(&comm));
1725c6c1daeSBarry Smith   }
1733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1745c6c1daeSBarry Smith }
1755c6c1daeSBarry Smith 
1765c6c1daeSBarry Smith /*@C
177811af0c4SBarry Smith   PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`.
1785c6c1daeSBarry Smith 
17935cb6cd3SPierre Jolivet   Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer; No Fortran Support
1805c6c1daeSBarry Smith 
181f8859db6SBarry Smith   Input Parameter:
1823f423023SBarry Smith . viewer - `PetscViewer` context, obtained from `PetscViewerASCIIOpen()`
183f8859db6SBarry Smith 
184f8859db6SBarry Smith   Output Parameter:
185f8859db6SBarry Smith . fd - file pointer
186f8859db6SBarry Smith 
1875c6c1daeSBarry Smith   Level: intermediate
1885c6c1daeSBarry Smith 
189811af0c4SBarry Smith   Note:
190c410d8ccSBarry Smith   For the standard `PETSCVIEWERASCII` the value is valid only on MPI rank 0 of the viewer
191811af0c4SBarry Smith 
1923f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`,
1933f423023SBarry Smith           `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
1945c6c1daeSBarry Smith @*/
195d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
196d71ae5a4SJacob Faibussowitsch {
1975c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1985c6c1daeSBarry Smith 
1995c6c1daeSBarry Smith   PetscFunctionBegin;
200c621c6acSBarry Smith   PetscCheck(!vascii->fileunit, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot request file pointer for viewers that use Fortran files");
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 
3525d83a8b1SBarry Smith /*@
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 
3825d83a8b1SBarry Smith /*@
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 
4155d83a8b1SBarry Smith /*@
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 
4425d83a8b1SBarry Smith /*@
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
50957b1f488SBarry Smith     #define petscviewerasciisetfileunit_      PETSCVIEWERASCIISETFILEUNIT
51057b1f488SBarry Smith     #define petscviewerasciiworldsetfileunit_ PETSCVIEWERASCIIWORLDSETFILEUNIT
511e4096674SBarry Smith     #define petscfortranprinttounit_          PETSCFORTRANPRINTTOUNIT
512e4096674SBarry Smith   #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
513e4096674SBarry Smith     #define petscviewerasciiopenwithfileunit_ petscviewerasciiopenwithfileunit
514e4096674SBarry Smith     #define petscviewerasciisetfileunit_      petscviewerasciisetfileunit
51557b1f488SBarry Smith     #define petscviewerasciiworldsetfileunit_ petscviewerasciiworldsetfileunit
516e4096674SBarry Smith     #define petscfortranprinttounit_          petscfortranprinttounit
517e4096674SBarry Smith   #endif
518e4096674SBarry Smith 
519e4096674SBarry Smith   #if defined(__cplusplus)
520e4096674SBarry Smith extern "C" void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
521e4096674SBarry Smith   #else
522e4096674SBarry Smith extern void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
523e4096674SBarry Smith   #endif
524e4096674SBarry Smith 
525e4096674SBarry Smith   #define PETSCDEFAULTBUFFERSIZE 8 * 1024
526e4096674SBarry Smith 
52757b1f488SBarry Smith static PetscInt PETSC_VIEWER_ASCII_WORLD_fileunit = 0;
52857b1f488SBarry Smith 
52957b1f488SBarry Smith // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
53057b1f488SBarry Smith /*MC
53157b1f488SBarry Smith   PetscViewerASCIIWORLDSetFileUnit - sets `PETSC_VIEWER_STDOUT_WORLD` to write to a Fortran IO unit
53257b1f488SBarry Smith 
53357b1f488SBarry Smith   Synopsis:
53457b1f488SBarry Smith   #include <petscviewer.h>
53557b1f488SBarry Smith   void PetscViewerASCIIWORLDSetFileUnit(PetscInt unit, PetscErrorCode ierr)
53657b1f488SBarry Smith 
53757b1f488SBarry Smith   Input Parameter:
53857b1f488SBarry Smith . unit - the unit number
53957b1f488SBarry Smith 
54057b1f488SBarry Smith   Output Parameter:
54157b1f488SBarry Smith . ierr - the error code
54257b1f488SBarry Smith 
54357b1f488SBarry Smith   Level: intermediate
54457b1f488SBarry Smith 
54557b1f488SBarry Smith   Notes:
54657b1f488SBarry Smith   Must be called before `PetscInitialize()`
54757b1f488SBarry Smith 
5481d031f67SBarry Smith   This may not work currently with some viewers that (improperly) use the `fd` directly instead of `PetscViewerASCIIPrintf()`
54957b1f488SBarry Smith 
55057b1f488SBarry Smith   With this option, for example, `-log_options` results will be saved to the Fortran file
55157b1f488SBarry Smith 
5521d031f67SBarry Smith   Any process may call this but only the unit passed on the first process is used
55357b1f488SBarry Smith 
55457b1f488SBarry Smith   Fortran Note:
55557b1f488SBarry Smith   Only for Fortran
55657b1f488SBarry Smith 
55757b1f488SBarry Smith   Developer Note:
55857b1f488SBarry Smith   `PetscViewerASCIIWORLDSetFilename()` could be added in the future
55957b1f488SBarry Smith 
56057b1f488SBarry Smith .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIWORLDSetFileUnit()`
56157b1f488SBarry Smith M*/
56257b1f488SBarry Smith PETSC_EXTERN void petscviewerasciiworldsetfileunit_(PetscInt *unit, PetscErrorCode *ierr)
56357b1f488SBarry Smith {
56457b1f488SBarry Smith   PETSC_VIEWER_ASCII_WORLD_fileunit = *unit;
56557b1f488SBarry Smith }
56657b1f488SBarry Smith 
56757b1f488SBarry Smith   #include <petsc/private/fortranimpl.h>
56857b1f488SBarry Smith 
56910450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
570489d2c6aSPierre Jolivet /*MC
571baca6076SPierre Jolivet   PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` to write to a Fortran IO unit
572e4096674SBarry Smith 
57310450e9eSJacob Faibussowitsch   Synopsis:
57410450e9eSJacob Faibussowitsch   #include <petscviewer.h>
575e4096674SBarry Smith   void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr)
576e4096674SBarry Smith 
577e4096674SBarry Smith   Input Parameters:
578e4096674SBarry Smith + lab  - the viewer
579e4096674SBarry Smith - unit - the unit number
580e4096674SBarry Smith 
581e4096674SBarry Smith   Output Parameter:
582e4096674SBarry Smith . ierr - the error code
583e4096674SBarry Smith 
58410450e9eSJacob Faibussowitsch   Level: intermediate
58510450e9eSJacob Faibussowitsch 
586e4096674SBarry Smith   Note:
587e4096674SBarry Smith   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
588e4096674SBarry Smith 
589aec76313SJacob Faibussowitsch   Fortran Notes:
590e4096674SBarry Smith   Only for Fortran, use  `PetscViewerASCIISetFILE()` for C
591e4096674SBarry Smith 
59257b1f488SBarry Smith .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIWORLDSetFileUnit()`
593489d2c6aSPierre Jolivet M*/
594e4096674SBarry Smith PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, PetscInt *unit, PetscErrorCode *ierr)
595e4096674SBarry Smith {
59657b1f488SBarry Smith   PetscViewer_ASCII *vascii;
59757b1f488SBarry Smith   PetscViewer        v;
598e4096674SBarry Smith 
59957b1f488SBarry Smith   PetscPatchDefaultViewers_Fortran(lab, v);
60057b1f488SBarry Smith   vascii = (PetscViewer_ASCII *)v->data;
601e4096674SBarry Smith   if (vascii->mode == FILE_MODE_READ) {
602e4096674SBarry Smith     *ierr = PETSC_ERR_ARG_WRONGSTATE;
603e4096674SBarry Smith     return;
604e4096674SBarry Smith   }
605e4096674SBarry Smith   vascii->fileunit = *unit;
606e4096674SBarry Smith }
607e4096674SBarry Smith 
60810450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
609489d2c6aSPierre Jolivet /*MC
610baca6076SPierre Jolivet   PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit
611e4096674SBarry Smith 
61210450e9eSJacob Faibussowitsch   Synopsis:
61310450e9eSJacob Faibussowitsch   #include <petscviewer.h>
614e4096674SBarry Smith   void PetscViewerASCIIOpenWithFileUnit(MPI_Comm comm, PetscInt unit, PetscViewer viewer, PetscErrorCode ierr)
615e4096674SBarry Smith 
616e4096674SBarry Smith   Input Parameters:
617e4096674SBarry Smith + comm - the `MPI_Comm` to share the viewer
618e4096674SBarry Smith - unit - the unit number
619e4096674SBarry Smith 
620e4096674SBarry Smith   Output Parameters:
621e4096674SBarry Smith + lab  - the viewer
622e4096674SBarry Smith - ierr - the error code
623e4096674SBarry Smith 
62410450e9eSJacob Faibussowitsch   Level: intermediate
62510450e9eSJacob Faibussowitsch 
626e4096674SBarry Smith   Note:
627e4096674SBarry Smith   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
628e4096674SBarry Smith 
629aec76313SJacob Faibussowitsch   Fortran Notes:
630e4096674SBarry Smith   Only for Fortran, use  `PetscViewerASCIIOpenWithFILE()` for C
631e4096674SBarry Smith 
632e4096674SBarry Smith .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()`
633489d2c6aSPierre Jolivet M*/
634e4096674SBarry Smith PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Comm *comm, PetscInt *unit, PetscViewer *lab, PetscErrorCode *ierr)
635e4096674SBarry Smith {
636e4096674SBarry Smith   *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab);
637e4096674SBarry Smith   if (*ierr) return;
638e4096674SBarry Smith   *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII);
639e4096674SBarry Smith   if (*ierr) return;
640e4096674SBarry Smith   *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE);
641e4096674SBarry Smith   if (*ierr) return;
642e4096674SBarry Smith   petscviewerasciisetfileunit_(lab, unit, ierr);
643e4096674SBarry Smith }
644e4096674SBarry Smith 
645e4096674SBarry Smith static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
646e4096674SBarry Smith {
647e4096674SBarry Smith   PetscErrorCode ierr;
648e4096674SBarry Smith   char           str[PETSCDEFAULTBUFFERSIZE];
649e4096674SBarry Smith   size_t         len;
650e4096674SBarry Smith 
651e4096674SBarry Smith   PetscFunctionBegin;
652e4096674SBarry Smith   PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp));
653e4096674SBarry Smith   PetscCall(PetscStrlen(str, &len));
654e4096674SBarry Smith   petscfortranprinttounit_(&unit, str, &ierr, (int)len);
655e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
656e4096674SBarry Smith }
657e4096674SBarry Smith 
658e4096674SBarry Smith static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
659e4096674SBarry Smith {
660e4096674SBarry Smith   PetscErrorCode ierr;
661e4096674SBarry Smith   size_t         len;
662e4096674SBarry Smith 
663e4096674SBarry Smith   PetscFunctionBegin;
664e4096674SBarry Smith   PetscCall(PetscStrlen(str, &len));
665e4096674SBarry Smith   petscfortranprinttounit_(&unit, str, &ierr, (int)len);
666e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
667e4096674SBarry Smith }
668e4096674SBarry Smith 
669e4096674SBarry Smith #else
670e4096674SBarry Smith 
671e4096674SBarry Smith /* these will never be used; but are needed to link with */
672e4096674SBarry Smith static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
673e4096674SBarry Smith {
674e4096674SBarry Smith   PetscFunctionBegin;
675e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
676e4096674SBarry Smith }
677e4096674SBarry Smith 
678e4096674SBarry Smith static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
679e4096674SBarry Smith {
680e4096674SBarry Smith   PetscFunctionBegin;
681e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
682e4096674SBarry Smith }
683e4096674SBarry Smith #endif
684e4096674SBarry Smith 
68557b1f488SBarry Smith /*@
6861d031f67SBarry Smith   PetscViewerASCIIGetStdout - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processes
687*648c30bcSBarry Smith   in a communicator that prints to `stdout`. Error returning version of `PETSC_VIEWER_STDOUT_()`
68857b1f488SBarry Smith 
68957b1f488SBarry Smith   Collective
69057b1f488SBarry Smith 
69157b1f488SBarry Smith   Input Parameter:
69257b1f488SBarry Smith . comm - the MPI communicator to share the `PetscViewer`
69357b1f488SBarry Smith 
69457b1f488SBarry Smith   Output Parameter:
69557b1f488SBarry Smith . viewer - the viewer
69657b1f488SBarry Smith 
69757b1f488SBarry Smith   Level: beginner
69857b1f488SBarry Smith 
69957b1f488SBarry Smith   Note:
700*648c30bcSBarry Smith   Use `PetscViewerDestroy()` to destroy it
70157b1f488SBarry Smith 
70257b1f488SBarry Smith   Developer Note:
70357b1f488SBarry Smith   This should be used in all PETSc source code instead of `PETSC_VIEWER_STDOUT_()` since it allows error checking
70457b1f488SBarry Smith 
705*648c30bcSBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIGetStderr()`, `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
70657b1f488SBarry Smith           `PETSC_VIEWER_STDOUT_SELF`
70757b1f488SBarry Smith @*/
70857b1f488SBarry Smith PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm, PetscViewer *viewer)
70957b1f488SBarry Smith {
71057b1f488SBarry Smith   PetscBool flg;
71157b1f488SBarry Smith   MPI_Comm  ncomm;
71257b1f488SBarry Smith 
71357b1f488SBarry Smith   PetscFunctionBegin;
714377f809aSBarry Smith   PetscAssertPointer(viewer, 2);
71557b1f488SBarry Smith   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout));
71657b1f488SBarry Smith   PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
71757b1f488SBarry Smith   if (Petsc_Viewer_Stdout_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Stdout_keyval, NULL));
71857b1f488SBarry Smith   PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, (PetscMPIInt *)&flg));
71957b1f488SBarry Smith   if (!flg) { /* PetscViewer not yet created */
72057b1f488SBarry Smith #if defined(PETSC_USE_FORTRAN_BINDINGS)
72157b1f488SBarry Smith     PetscMPIInt size, gsize;
72257b1f488SBarry Smith 
72357b1f488SBarry Smith     PetscCallMPI(MPI_Comm_size(comm, &size));
72457b1f488SBarry Smith     PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &gsize));
72557b1f488SBarry Smith     if (size == gsize) { PetscCallMPI(MPI_Bcast(&PETSC_VIEWER_ASCII_WORLD_fileunit, 1, MPIU_INT, 0, comm)); }
72657b1f488SBarry Smith     if (PETSC_VIEWER_ASCII_WORLD_fileunit) {
72757b1f488SBarry Smith       PetscErrorCode ierr;
72857b1f488SBarry Smith 
72957b1f488SBarry Smith       petscviewerasciiopenwithfileunit_(&ncomm, &PETSC_VIEWER_ASCII_WORLD_fileunit, viewer, &ierr);
73057b1f488SBarry Smith     } else
73157b1f488SBarry Smith #endif
732*648c30bcSBarry Smith     {
733*648c30bcSBarry Smith       PetscCall(PetscViewerCreate(ncomm, viewer));
734*648c30bcSBarry Smith       PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
735*648c30bcSBarry Smith       PetscCall(PetscViewerFileSetName(*viewer, "stdout"));
736*648c30bcSBarry Smith     }
73757b1f488SBarry Smith     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
73857b1f488SBarry Smith     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer));
73957b1f488SBarry Smith   }
74057b1f488SBarry Smith   PetscCall(PetscCommDestroy(&ncomm));
74157b1f488SBarry Smith   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout));
74257b1f488SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
74357b1f488SBarry Smith }
74457b1f488SBarry Smith 
7455c6c1daeSBarry Smith /*@C
7465c6c1daeSBarry Smith   PetscViewerASCIIPrintf - Prints to a file, only from the first
7473f423023SBarry Smith   processor in the `PetscViewer` of type `PETSCVIEWERASCII`
7485c6c1daeSBarry Smith 
749c410d8ccSBarry Smith   Not Collective, but only the first MPI rank in the viewer has any effect
7505c6c1daeSBarry Smith 
7515c6c1daeSBarry Smith   Input Parameters:
752811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
7535c6c1daeSBarry Smith - format - the usual printf() format string
7545c6c1daeSBarry Smith 
7555c6c1daeSBarry Smith   Level: developer
7565c6c1daeSBarry Smith 
757aec76313SJacob Faibussowitsch   Fortran Notes:
758c410d8ccSBarry Smith   The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran.
7595c6c1daeSBarry Smith   That is, you can only pass a single character string from Fortran.
7605c6c1daeSBarry Smith 
761d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
762db781477SPatrick Sanan           `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
763db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
7645c6c1daeSBarry Smith @*/
765d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
766d71ae5a4SJacob Faibussowitsch {
7675c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
7685c6c1daeSBarry Smith   PetscMPIInt        rank;
769fe8fb074SBarry Smith   PetscInt           tab = 0, intab = ascii->tab;
7705c6c1daeSBarry Smith   FILE              *fd = ascii->fd;
7713f08860eSBarry Smith   PetscBool          iascii;
7725c6c1daeSBarry Smith 
7735c6c1daeSBarry Smith   PetscFunctionBegin;
7745c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
77528b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
7764f572ea9SToby Isaac   PetscAssertPointer(format, 2);
7779566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
77828b400f6SJacob Faibussowitsch   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
7799566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
7803ba16761SJacob Faibussowitsch   if (rank) PetscFunctionReturn(PETSC_SUCCESS);
7813f08860eSBarry Smith 
7823f08860eSBarry Smith   if (ascii->bviewer) { /* pass string up to parent viewer */
7833f08860eSBarry Smith     char   *string;
7843f08860eSBarry Smith     va_list Argp;
7853f08860eSBarry Smith     size_t  fullLength;
7863f08860eSBarry Smith 
7879566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
788fe8fb074SBarry Smith     for (; tab < ascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; }
7893f08860eSBarry Smith     va_start(Argp, format);
790fe8fb074SBarry Smith     PetscCall(PetscVSNPrintf(string + 2 * intab, QUEUESTRINGSIZE - 2 * intab, format, &fullLength, Argp));
7913f08860eSBarry Smith     va_end(Argp);
792fe8fb074SBarry Smith     PetscCall(PetscViewerASCIISynchronizedPrintf(ascii->bviewer, "%s", string));
7939566063dSJacob Faibussowitsch     PetscCall(PetscFree(string));
7943f08860eSBarry Smith   } else { /* write directly to file */
7955c6c1daeSBarry Smith     va_list Argp;
796fe8fb074SBarry Smith 
797dd2fa690SBarry Smith     tab = intab;
798e4096674SBarry Smith     while (tab--) {
799e4096674SBarry Smith       if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "  "));
800e4096674SBarry Smith       else PetscCall(PetscFPrintfFortran(ascii->fileunit, "   "));
801e4096674SBarry Smith     }
8025c6c1daeSBarry Smith 
8035c6c1daeSBarry Smith     va_start(Argp, format);
804e4096674SBarry Smith     if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
805e4096674SBarry Smith     else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
806eae3dc7dSJacob Faibussowitsch     va_end(Argp);
807c69effb2SJacob Faibussowitsch     PetscCall(PetscFFlush(fd));
8085c6c1daeSBarry Smith   }
8093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8105c6c1daeSBarry Smith }
8115c6c1daeSBarry Smith 
8125d83a8b1SBarry Smith /*@
813c410d8ccSBarry Smith   PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.
8145c6c1daeSBarry Smith 
815c3339decSBarry Smith   Collective
8165c6c1daeSBarry Smith 
8175c6c1daeSBarry Smith   Input Parameters:
8183f423023SBarry Smith + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
8195c6c1daeSBarry Smith - name   - the name of the file it should use
8205c6c1daeSBarry Smith 
8215c6c1daeSBarry Smith   Level: advanced
8225c6c1daeSBarry Smith 
823c410d8ccSBarry Smith   Note:
824c410d8ccSBarry Smith   This will have no effect on viewers that are not related to files
825c410d8ccSBarry Smith 
826d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
827db781477SPatrick Sanan           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
8285c6c1daeSBarry Smith @*/
829d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
830d71ae5a4SJacob Faibussowitsch {
831cc843e7aSLisandro Dalcin   char filename[PETSC_MAX_PATH_LEN];
8325c6c1daeSBarry Smith 
8335c6c1daeSBarry Smith   PetscFunctionBegin;
8345c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8354f572ea9SToby Isaac   PetscAssertPointer(name, 2);
8369566063dSJacob Faibussowitsch   PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
837cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
8383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8395c6c1daeSBarry Smith }
8405c6c1daeSBarry Smith 
8415c6c1daeSBarry Smith /*@C
842c410d8ccSBarry Smith   PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using
8435c6c1daeSBarry Smith 
8445c6c1daeSBarry Smith   Not Collective
8455c6c1daeSBarry Smith 
8465c6c1daeSBarry Smith   Input Parameter:
8473f423023SBarry Smith . viewer - the `PetscViewer`
8485c6c1daeSBarry Smith 
8495c6c1daeSBarry Smith   Output Parameter:
8505c6c1daeSBarry Smith . name - the name of the file it is using
8515c6c1daeSBarry Smith 
8525c6c1daeSBarry Smith   Level: advanced
8535c6c1daeSBarry Smith 
854c410d8ccSBarry Smith   Note:
855c410d8ccSBarry Smith   This will have no effect on viewers that are not related to files
856c410d8ccSBarry Smith 
857d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
8585c6c1daeSBarry Smith @*/
8595d83a8b1SBarry Smith PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char *name[])
860d71ae5a4SJacob Faibussowitsch {
8615c6c1daeSBarry Smith   PetscFunctionBegin;
8625c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8634f572ea9SToby Isaac   PetscAssertPointer(name, 2);
864cac4c232SBarry Smith   PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
8653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8665c6c1daeSBarry Smith }
8675c6c1daeSBarry Smith 
86834e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
869d71ae5a4SJacob Faibussowitsch {
8705c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
8715c6c1daeSBarry Smith 
8725c6c1daeSBarry Smith   PetscFunctionBegin;
8735c6c1daeSBarry Smith   *name = vascii->filename;
8743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8755c6c1daeSBarry Smith }
8765c6c1daeSBarry Smith 
877bf31d2d3SBarry Smith #include <errno.h>
87834e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
879d71ae5a4SJacob Faibussowitsch {
8805c6c1daeSBarry Smith   size_t             len;
881bbcf679cSJacob Faibussowitsch   char               fname[PETSC_MAX_PATH_LEN], *gz = NULL;
8825c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
8835c6c1daeSBarry Smith   PetscBool          isstderr, isstdout;
8845c6c1daeSBarry Smith   PetscMPIInt        rank;
8855c6c1daeSBarry Smith 
8865c6c1daeSBarry Smith   PetscFunctionBegin;
8879566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileClose_ASCII(viewer));
8883ba16761SJacob Faibussowitsch   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
8899566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &vascii->filename));
8905c6c1daeSBarry Smith 
8915c6c1daeSBarry Smith   /* Is this file to be compressed */
8925c6c1daeSBarry Smith   vascii->storecompressed = PETSC_FALSE;
893a297a907SKarl Rupp 
8949566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
8955c6c1daeSBarry Smith   if (gz) {
8969566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(gz, &len));
8975c6c1daeSBarry Smith     if (len == 3) {
89808401ef6SPierre 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");
8995c6c1daeSBarry Smith       *gz                     = 0;
9005c6c1daeSBarry Smith       vascii->storecompressed = PETSC_TRUE;
9015c6c1daeSBarry Smith     }
9025c6c1daeSBarry Smith   }
9039566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
904dd400576SPatrick Sanan   if (rank == 0) {
9059566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
9069566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
9075c6c1daeSBarry Smith     /* empty filename means stdout */
9085c6c1daeSBarry Smith     if (name[0] == 0) isstdout = PETSC_TRUE;
9095c6c1daeSBarry Smith     if (isstderr) vascii->fd = PETSC_STDERR;
9105c6c1daeSBarry Smith     else if (isstdout) vascii->fd = PETSC_STDOUT;
9115c6c1daeSBarry Smith     else {
9129566063dSJacob Faibussowitsch       PetscCall(PetscFixFilename(name, fname));
9135c6c1daeSBarry Smith       switch (vascii->mode) {
914d71ae5a4SJacob Faibussowitsch       case FILE_MODE_READ:
915d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "r");
916d71ae5a4SJacob Faibussowitsch         break;
917d71ae5a4SJacob Faibussowitsch       case FILE_MODE_WRITE:
918d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "w");
919d71ae5a4SJacob Faibussowitsch         break;
920d71ae5a4SJacob Faibussowitsch       case FILE_MODE_APPEND:
921d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "a");
922d71ae5a4SJacob Faibussowitsch         break;
9235c6c1daeSBarry Smith       case FILE_MODE_UPDATE:
9245c6c1daeSBarry Smith         vascii->fd = fopen(fname, "r+");
925a297a907SKarl Rupp         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
9265c6c1daeSBarry Smith         break;
9275c6c1daeSBarry Smith       case FILE_MODE_APPEND_UPDATE:
9285c6c1daeSBarry Smith         /* I really want a file which is opened at the end for updating,
9295c6c1daeSBarry Smith            not a+, which opens at the beginning, but makes writes at the end.
9305c6c1daeSBarry Smith         */
9315c6c1daeSBarry Smith         vascii->fd = fopen(fname, "r+");
932a297a907SKarl Rupp         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
9333ba16761SJacob Faibussowitsch         else {
9343ba16761SJacob Faibussowitsch           int ret = fseek(vascii->fd, 0, SEEK_END);
9353ba16761SJacob Faibussowitsch           PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
9363ba16761SJacob Faibussowitsch         }
9375c6c1daeSBarry Smith         break;
938d71ae5a4SJacob Faibussowitsch       default:
939d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
9405c6c1daeSBarry Smith       }
941bf31d2d3SBarry Smith       PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
9425c6c1daeSBarry Smith     }
9435c6c1daeSBarry Smith   }
9443ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
9453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9465c6c1daeSBarry Smith }
9475c6c1daeSBarry Smith 
94834e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
949d71ae5a4SJacob Faibussowitsch {
9505c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
9515c6c1daeSBarry Smith 
9525c6c1daeSBarry Smith   PetscFunctionBegin;
95328b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
954fe8fb074SBarry Smith   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
955e5afcf28SBarry Smith   /*
9569530cbd7SBarry Smith      The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
9579530cbd7SBarry 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
9589530cbd7SBarry Smith      (since the count never gets to zero) in some examples this displays information that otherwise would be lost
9599530cbd7SBarry Smith 
9609530cbd7SBarry Smith      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
9619530cbd7SBarry Smith      PCView_GASM().
962e5afcf28SBarry Smith   */
9639566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
964b4025f61SBarry Smith   PetscCall(PetscViewerFlush(viewer));
9659566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(subcomm, outviewer));
9669566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
9679566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
9685c6c1daeSBarry Smith   ovascii            = (PetscViewer_ASCII *)(*outviewer)->data;
9695c6c1daeSBarry Smith   ovascii->fd        = vascii->fd;
970ba5a0b41SBarry Smith   ovascii->closefile = PETSC_FALSE;
9715c6c1daeSBarry Smith 
9725c6c1daeSBarry Smith   vascii->sviewer                                      = *outviewer;
9735c6c1daeSBarry Smith   (*outviewer)->format                                 = viewer->format;
9745c6c1daeSBarry Smith   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
9753f08860eSBarry Smith   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
9763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9775c6c1daeSBarry Smith }
9785c6c1daeSBarry Smith 
97934e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
980d71ae5a4SJacob Faibussowitsch {
9815c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
9825c6c1daeSBarry Smith 
9835c6c1daeSBarry Smith   PetscFunctionBegin;
98428b400f6SJacob Faibussowitsch   PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
98508401ef6SPierre Jolivet   PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");
9865c6c1daeSBarry Smith 
9879566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
988e5afcf28SBarry Smith   ascii->sviewer             = NULL;
9895c6c1daeSBarry Smith   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
9909566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(outviewer));
991fe8fb074SBarry Smith   PetscCall(PetscViewerFlush(viewer));
9929566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
9933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9945c6c1daeSBarry Smith }
9955c6c1daeSBarry Smith 
99634e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
997d71ae5a4SJacob Faibussowitsch {
9982bf49c77SBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
9992bf49c77SBarry Smith 
10002bf49c77SBarry Smith   PetscFunctionBegin;
10011d031f67SBarry Smith   if (ascii->fileunit) PetscCall(PetscViewerASCIIPrintf(viewer, "Fortran FILE UNIT: %" PetscInt_FMT "\n", ascii->fileunit));
100257b1f488SBarry Smith   else if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
10033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10042bf49c77SBarry Smith }
10052bf49c77SBarry Smith 
10068556b5ebSBarry Smith /*MC
1007*648c30bcSBarry Smith    PETSCVIEWERASCII - A viewer that prints to `stdout`, `stderr`, or an ASCII file
10088556b5ebSBarry Smith 
1009811af0c4SBarry Smith   Level: beginner
1010811af0c4SBarry Smith 
1011d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1012db781477SPatrick Sanan           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
1013db781477SPatrick Sanan           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
10148556b5ebSBarry Smith M*/
1015d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
1016d71ae5a4SJacob Faibussowitsch {
10175c6c1daeSBarry Smith   PetscViewer_ASCII *vascii;
10185c6c1daeSBarry Smith 
10195c6c1daeSBarry Smith   PetscFunctionBegin;
10204dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&vascii));
10215c6c1daeSBarry Smith   viewer->data = (void *)vascii;
10225c6c1daeSBarry Smith 
10235c6c1daeSBarry Smith   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
10245c6c1daeSBarry Smith   viewer->ops->flush            = PetscViewerFlush_ASCII;
1025559f443fSBarry Smith   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
1026559f443fSBarry Smith   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
10272bf49c77SBarry Smith   viewer->ops->view             = PetscViewerView_ASCII;
10281d641e7bSMichael Lange   viewer->ops->read             = PetscViewerASCIIRead;
10295c6c1daeSBarry Smith 
10305c6c1daeSBarry Smith   /* defaults to stdout unless set with PetscViewerFileSetName() */
10315c6c1daeSBarry Smith   vascii->fd        = PETSC_STDOUT;
10325c6c1daeSBarry Smith   vascii->mode      = FILE_MODE_WRITE;
103302c9f0b5SLisandro Dalcin   vascii->bviewer   = NULL;
103402c9f0b5SLisandro Dalcin   vascii->subviewer = NULL;
103502c9f0b5SLisandro Dalcin   vascii->sviewer   = NULL;
10365c6c1daeSBarry Smith   vascii->tab       = 0;
10375c6c1daeSBarry Smith   vascii->tab_store = 0;
103802c9f0b5SLisandro Dalcin   vascii->filename  = NULL;
10395c6c1daeSBarry Smith   vascii->closefile = PETSC_TRUE;
10405c6c1daeSBarry Smith 
10419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
10429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
10439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
10449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
10453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10465c6c1daeSBarry Smith }
10475c6c1daeSBarry Smith 
10485c6c1daeSBarry Smith /*@C
1049c410d8ccSBarry Smith   PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
10505c6c1daeSBarry Smith   several processors.  Output of the first processor is followed by that of the
10515c6c1daeSBarry Smith   second, etc.
10525c6c1daeSBarry Smith 
1053c410d8ccSBarry Smith   Not Collective, must call collective `PetscViewerFlush()` to get the results flushed
10545c6c1daeSBarry Smith 
10555c6c1daeSBarry Smith   Input Parameters:
1056811af0c4SBarry Smith + viewer - the `PETSCVIEWERASCII` `PetscViewer`
10575c6c1daeSBarry Smith - format - the usual printf() format string
10585c6c1daeSBarry Smith 
10595c6c1daeSBarry Smith   Level: intermediate
10605c6c1daeSBarry Smith 
106195452b02SPatrick Sanan   Notes:
1062811af0c4SBarry Smith   You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
1063e6abc3ddSVáclav Hapla   Then you can do multiple independent calls to this routine.
1064811af0c4SBarry Smith 
1065811af0c4SBarry Smith   The actual synchronized print is then done using `PetscViewerFlush()`.
1066811af0c4SBarry Smith   `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
1067e6abc3ddSVáclav Hapla   to conclude the "synchronized session".
1068811af0c4SBarry Smith 
1069e6abc3ddSVáclav Hapla   So the typical calling sequence looks like
1070811af0c4SBarry Smith .vb
1071811af0c4SBarry Smith     PetscViewerASCIIPushSynchronized(viewer);
1072811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1073811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1074811af0c4SBarry Smith     ...
1075811af0c4SBarry Smith     PetscViewerFlush(viewer);
1076811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1077811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1078811af0c4SBarry Smith     ...
1079811af0c4SBarry Smith     PetscViewerFlush(viewer);
1080811af0c4SBarry Smith     PetscViewerASCIIPopSynchronized(viewer);
1081811af0c4SBarry Smith .ve
10825c6c1daeSBarry Smith 
1083aec76313SJacob Faibussowitsch   Fortran Notes:
10845c6c1daeSBarry Smith   Can only print a single character* string
10855c6c1daeSBarry Smith 
1086d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
1087db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
1088db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
10895c6c1daeSBarry Smith @*/
1090d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
1091d71ae5a4SJacob Faibussowitsch {
10925c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
10933f08860eSBarry Smith   PetscMPIInt        rank;
1094fe8fb074SBarry Smith   PetscInt           tab = 0;
10955c6c1daeSBarry Smith   MPI_Comm           comm;
1096fe8fb074SBarry Smith   PetscBool          iascii;
10975c6c1daeSBarry Smith 
10985c6c1daeSBarry Smith   PetscFunctionBegin;
10995c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
11004f572ea9SToby Isaac   PetscAssertPointer(format, 2);
11019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
110228b400f6SJacob Faibussowitsch   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
110328b400f6SJacob Faibussowitsch   PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");
11045c6c1daeSBarry Smith 
11059566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
11069566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11075c6c1daeSBarry Smith 
1108559f443fSBarry Smith   if (vascii->bviewer) {
1109fe8fb074SBarry Smith     char   *string;
11105c6c1daeSBarry Smith     va_list Argp;
1111fe8fb074SBarry Smith     size_t  fullLength;
11125c6c1daeSBarry Smith 
1113fe8fb074SBarry Smith     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
1114fe8fb074SBarry Smith     for (; tab < vascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; }
1115fe8fb074SBarry Smith     va_start(Argp, format);
1116fe8fb074SBarry Smith     PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp));
1117fe8fb074SBarry Smith     va_end(Argp);
1118fe8fb074SBarry Smith     PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string));
1119fe8fb074SBarry Smith     PetscCall(PetscFree(string));
1120fe8fb074SBarry Smith   } else if (rank == 0) { /* First processor prints immediately to fp */
1121fe8fb074SBarry Smith     va_list Argp;
1122fe8fb074SBarry Smith     FILE   *fp = vascii->fd;
1123fe8fb074SBarry Smith 
1124fe8fb074SBarry Smith     tab = vascii->tab;
112548a46eb9SPierre Jolivet     while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, "  "));
11265c6c1daeSBarry Smith 
11275c6c1daeSBarry Smith     va_start(Argp, format);
11289566063dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(fp, format, Argp));
1129eae3dc7dSJacob Faibussowitsch     va_end(Argp);
1130c69effb2SJacob Faibussowitsch     PetscCall(PetscFFlush(fp));
11315c6c1daeSBarry Smith     if (petsc_history) {
11325c6c1daeSBarry Smith       va_start(Argp, format);
11339566063dSJacob Faibussowitsch       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1134eae3dc7dSJacob Faibussowitsch       va_end(Argp);
1135c69effb2SJacob Faibussowitsch       PetscCall(PetscFFlush(petsc_history));
11365c6c1daeSBarry Smith     }
11375c6c1daeSBarry Smith     va_end(Argp);
1138559f443fSBarry Smith   } else { /* other processors add to queue */
11395c6c1daeSBarry Smith     char       *string;
11405c6c1daeSBarry Smith     va_list     Argp;
11415c6c1daeSBarry Smith     size_t      fullLength;
11425c6c1daeSBarry Smith     PrintfQueue next;
11435c6c1daeSBarry Smith 
11449566063dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
1145559f443fSBarry Smith     if (vascii->petsc_printfqueue) {
1146559f443fSBarry Smith       vascii->petsc_printfqueue->next = next;
1147559f443fSBarry Smith       vascii->petsc_printfqueue       = next;
1148a297a907SKarl Rupp     } else {
1149559f443fSBarry Smith       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1150a297a907SKarl Rupp     }
1151559f443fSBarry Smith     vascii->petsc_printfqueuelength++;
11525c6c1daeSBarry Smith     next->size = QUEUESTRINGSIZE;
11539566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(next->size, &next->string));
11545c6c1daeSBarry Smith     string = next->string;
1155f15bb73eSStefano Zampini 
1156f15bb73eSStefano Zampini     tab = vascii->tab;
11575c6c1daeSBarry Smith     tab *= 2;
1158ad540459SPierre Jolivet     while (tab--) *string++ = ' ';
11595c6c1daeSBarry Smith     va_start(Argp, format);
11609566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
11615c6c1daeSBarry Smith     va_end(Argp);
1162cb500232SBarry Smith     if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
11639566063dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
116414416c0eSBarry Smith       next->size = fullLength + 2 * vascii->tab;
11659566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(next->size, &next->string));
116614416c0eSBarry Smith       string = next->string;
116714416c0eSBarry Smith       tab    = 2 * vascii->tab;
1168ad540459SPierre Jolivet       while (tab--) *string++ = ' ';
116914416c0eSBarry Smith       va_start(Argp, format);
11709566063dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
117114416c0eSBarry Smith       va_end(Argp);
117214416c0eSBarry Smith     }
11735c6c1daeSBarry Smith   }
11743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11755c6c1daeSBarry Smith }
11765c6c1daeSBarry Smith 
11772655f987SMichael Lange /*@C
1178c410d8ccSBarry Smith   PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file
11792655f987SMichael Lange 
1180c410d8ccSBarry Smith   Only MPI rank 0 in the `PetscViewer` may call this
11812655f987SMichael Lange 
11822655f987SMichael Lange   Input Parameters:
11833f423023SBarry Smith + viewer - the `PETSCVIEWERASCII` viewer
1184c410d8ccSBarry Smith . data   - location to write the data, treated as an array of type indicated by `datatype`
1185060da220SMatthew G. Knepley . num    - number of items of data to read
1186aec76313SJacob Faibussowitsch - dtype  - type of data to read
11872655f987SMichael Lange 
118820f4b53cSBarry Smith   Output Parameter:
11893f423023SBarry Smith . count - number of items of data actually read, or `NULL`
1190f8e4bde8SMatthew G. Knepley 
11912655f987SMichael Lange   Level: beginner
11922655f987SMichael Lange 
1193d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1194db781477SPatrick Sanan           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1195db781477SPatrick Sanan           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
11962655f987SMichael Lange @*/
1197d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1198d71ae5a4SJacob Faibussowitsch {
11992655f987SMichael Lange   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
12002655f987SMichael Lange   FILE              *fd     = vascii->fd;
12012655f987SMichael Lange   PetscInt           i;
12023b7fe8c3SMatthew G. Knepley   int                ret = 0;
1203f8859db6SBarry Smith   PetscMPIInt        rank;
12042655f987SMichael Lange 
12052655f987SMichael Lange   PetscFunctionBegin;
12062655f987SMichael Lange   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
12079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1208c5853193SPierre Jolivet   PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1209060da220SMatthew G. Knepley   for (i = 0; i < num; i++) {
1210f8e4bde8SMatthew G. Knepley     if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1211f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1212a05e1a72SSatish Balay     else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1213f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
12149e3e4c22SLisandro Dalcin     else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1215972064b6SLisandro Dalcin     else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1216f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1217f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1218a6e181c6SToby Isaac #if defined(PETSC_USE_REAL___FLOAT128)
1219fba955ccSBarry Smith     else if (dtype == PETSC___FLOAT128) {
1220fba955ccSBarry Smith       double tmp;
1221fba955ccSBarry Smith       ret                     = fscanf(fd, "%lg", &tmp);
1222a6e181c6SToby Isaac       ((__float128 *)data)[i] = tmp;
1223a6e181c6SToby Isaac     }
1224fba955ccSBarry Smith #endif
12259371c9d4SSatish Balay     else
12269371c9d4SSatish Balay       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
122728b400f6SJacob Faibussowitsch     PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1228f7d195e4SLawrence Mitchell     if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
12292655f987SMichael Lange   }
1230060da220SMatthew G. Knepley   if (count) *count = i;
123108401ef6SPierre Jolivet   else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
12323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12332655f987SMichael Lange }
1234