xref: /petsc/src/sys/classes/viewer/impls/ascii/filev.c (revision 10450e9e44b354a0a3da7bbd573407bdf051df10)
15c6c1daeSBarry Smith 
2665c2dedSJed Brown #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h> /*I "petscviewer.h" I*/
35c6c1daeSBarry Smith 
45c6c1daeSBarry Smith #define QUEUESTRINGSIZE 8192
55c6c1daeSBarry Smith 
6d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer)
7d71ae5a4SJacob Faibussowitsch {
85c6c1daeSBarry Smith   PetscMPIInt        rank;
95c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
105c6c1daeSBarry Smith   int                err;
115c6c1daeSBarry Smith 
125c6c1daeSBarry Smith   PetscFunctionBegin;
1328b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
149566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
15dd400576SPatrick Sanan   if (rank == 0 && vascii->fd != stderr && vascii->fd != PETSC_STDOUT) {
165c6c1daeSBarry Smith     if (vascii->fd && vascii->closefile) {
175c6c1daeSBarry Smith       err = fclose(vascii->fd);
1828b400f6SJacob Faibussowitsch       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
195c6c1daeSBarry Smith     }
205c6c1daeSBarry Smith     if (vascii->storecompressed) {
215c6c1daeSBarry Smith       char  par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN];
225c6c1daeSBarry Smith       FILE *fp;
239566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(par, "gzip ", sizeof(par)));
249566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(par, vascii->filename, sizeof(par)));
255c6c1daeSBarry Smith #if defined(PETSC_HAVE_POPEN)
269566063dSJacob Faibussowitsch       PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp));
27cc73adaaSBarry Smith       PetscCheck(!fgets(buf, 1024, fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from compression command %s\n%s", par, buf);
289566063dSJacob Faibussowitsch       PetscCall(PetscPClose(PETSC_COMM_SELF, fp));
295c6c1daeSBarry Smith #else
305c6c1daeSBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
315c6c1daeSBarry Smith #endif
325c6c1daeSBarry Smith     }
335c6c1daeSBarry Smith   }
349566063dSJacob Faibussowitsch   PetscCall(PetscFree(vascii->filename));
353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
365c6c1daeSBarry Smith }
375c6c1daeSBarry Smith 
385c6c1daeSBarry Smith /* ----------------------------------------------------------------------*/
39d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
40d71ae5a4SJacob Faibussowitsch {
415c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
425c6c1daeSBarry Smith   PetscViewerLink   *vlink;
435c6c1daeSBarry Smith   PetscBool          flg;
445c6c1daeSBarry Smith 
455c6c1daeSBarry Smith   PetscFunctionBegin;
4628b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
479566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileClose_ASCII(viewer));
489566063dSJacob Faibussowitsch   PetscCall(PetscFree(vascii));
495c6c1daeSBarry Smith 
505c6c1daeSBarry Smith   /* remove the viewer from the list in the MPI Communicator */
5148a46eb9SPierre Jolivet   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0));
525c6c1daeSBarry Smith 
539566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
545c6c1daeSBarry Smith   if (flg) {
555c6c1daeSBarry Smith     if (vlink && vlink->viewer == viewer) {
56e5840a18SBarry Smith       if (vlink->next) {
579566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next));
58e5840a18SBarry Smith       } else {
599566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval));
60e5840a18SBarry Smith       }
619566063dSJacob Faibussowitsch       PetscCall(PetscFree(vlink));
625c6c1daeSBarry Smith     } else {
635c6c1daeSBarry Smith       while (vlink && vlink->next) {
645c6c1daeSBarry Smith         if (vlink->next->viewer == viewer) {
655c6c1daeSBarry Smith           PetscViewerLink *nv = vlink->next;
665c6c1daeSBarry Smith           vlink->next         = vlink->next->next;
679566063dSJacob Faibussowitsch           PetscCall(PetscFree(nv));
685c6c1daeSBarry Smith         }
695c6c1daeSBarry Smith         vlink = vlink->next;
705c6c1daeSBarry Smith       }
715c6c1daeSBarry Smith     }
725c6c1daeSBarry Smith   }
73aa139df6SJed Brown 
74aa139df6SJed Brown   if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
75aa139df6SJed Brown     PetscViewer aviewer;
769566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
7748a46eb9SPierre Jolivet     if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval));
78aa139df6SJed Brown   }
79aa139df6SJed Brown   if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
80aa139df6SJed Brown     PetscViewer aviewer;
819566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
8248a46eb9SPierre Jolivet     if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval));
83aa139df6SJed Brown   }
842e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
852e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
862e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
872e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
895c6c1daeSBarry Smith }
905c6c1daeSBarry Smith 
91d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
92d71ae5a4SJacob Faibussowitsch {
935c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
945fd66863SKarl Rupp 
955c6c1daeSBarry Smith   PetscFunctionBegin;
969566063dSJacob Faibussowitsch   PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer));
973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
985c6c1daeSBarry Smith }
995c6c1daeSBarry Smith 
100d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
101d71ae5a4SJacob Faibussowitsch {
1025c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
103559f443fSBarry Smith   MPI_Comm           comm;
104559f443fSBarry Smith   PetscMPIInt        rank, size;
105559f443fSBarry Smith   FILE              *fd = vascii->fd;
1065c6c1daeSBarry Smith 
1075c6c1daeSBarry Smith   PetscFunctionBegin;
10828b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
1099566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
112559f443fSBarry Smith 
113c69effb2SJacob Faibussowitsch   if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd));
1145c6c1daeSBarry Smith 
1155c6c1daeSBarry Smith   if (vascii->allowsynchronized) {
116559f443fSBarry Smith     PetscMPIInt tag, i, j, n = 0, dummy = 0;
117559f443fSBarry Smith     char       *message;
118559f443fSBarry Smith     MPI_Status  status;
119559f443fSBarry Smith 
1209566063dSJacob Faibussowitsch     PetscCall(PetscCommDuplicate(comm, &comm, &tag));
121559f443fSBarry Smith 
122559f443fSBarry Smith     /* First processor waits for messages from all other processors */
123dd400576SPatrick Sanan     if (rank == 0) {
124559f443fSBarry Smith       /* flush my own messages that I may have queued up */
125559f443fSBarry Smith       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
126559f443fSBarry Smith       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
127559f443fSBarry Smith         if (!vascii->bviewer) {
1289566063dSJacob Faibussowitsch           PetscCall(PetscFPrintf(comm, fd, "%s", next->string));
129559f443fSBarry Smith         } else {
1309566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string));
131559f443fSBarry Smith         }
132559f443fSBarry Smith         previous = next;
133559f443fSBarry Smith         next     = next->next;
1349566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous->string));
1359566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous));
136559f443fSBarry Smith       }
13702c9f0b5SLisandro Dalcin       vascii->petsc_printfqueue       = NULL;
138559f443fSBarry Smith       vascii->petsc_printfqueuelength = 0;
139559f443fSBarry Smith       for (i = 1; i < size; i++) {
140559f443fSBarry Smith         /* to prevent a flood of messages to process zero, request each message separately */
1419566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
1429566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
143559f443fSBarry Smith         for (j = 0; j < n; j++) {
144559f443fSBarry Smith           PetscMPIInt size = 0;
145559f443fSBarry Smith 
1469566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
1479566063dSJacob Faibussowitsch           PetscCall(PetscMalloc1(size, &message));
1489566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
149559f443fSBarry Smith           if (!vascii->bviewer) {
1509566063dSJacob Faibussowitsch             PetscCall(PetscFPrintf(comm, fd, "%s", message));
151559f443fSBarry Smith           } else {
1529566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message));
153559f443fSBarry Smith           }
1549566063dSJacob Faibussowitsch           PetscCall(PetscFree(message));
155559f443fSBarry Smith         }
156559f443fSBarry Smith       }
157559f443fSBarry Smith     } else { /* other processors send queue to processor 0 */
158559f443fSBarry Smith       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
159559f443fSBarry Smith 
1609566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
1619566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
162559f443fSBarry Smith       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
1639566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
1649566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
165559f443fSBarry Smith         previous = next;
166559f443fSBarry Smith         next     = next->next;
1679566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous->string));
1689566063dSJacob Faibussowitsch         PetscCall(PetscFree(previous));
169559f443fSBarry Smith       }
17002c9f0b5SLisandro Dalcin       vascii->petsc_printfqueue       = NULL;
171559f443fSBarry Smith       vascii->petsc_printfqueuelength = 0;
172559f443fSBarry Smith     }
1739566063dSJacob Faibussowitsch     PetscCall(PetscCommDestroy(&comm));
1745c6c1daeSBarry Smith   }
1753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1765c6c1daeSBarry Smith }
1775c6c1daeSBarry Smith 
1785c6c1daeSBarry Smith /*@C
179811af0c4SBarry Smith   PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`.
1805c6c1daeSBarry Smith 
18135cb6cd3SPierre Jolivet   Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer; No Fortran Support
1825c6c1daeSBarry Smith 
183f8859db6SBarry Smith   Input Parameter:
1843f423023SBarry Smith . viewer - `PetscViewer` context, obtained from `PetscViewerASCIIOpen()`
185f8859db6SBarry Smith 
186f8859db6SBarry Smith   Output Parameter:
187f8859db6SBarry Smith . fd - file pointer
188f8859db6SBarry Smith 
1895c6c1daeSBarry Smith   Level: intermediate
1905c6c1daeSBarry Smith 
191811af0c4SBarry Smith   Note:
192c410d8ccSBarry Smith   For the standard `PETSCVIEWERASCII` the value is valid only on MPI rank 0 of the viewer
193811af0c4SBarry Smith 
1943f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`,
1953f423023SBarry Smith           `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
1965c6c1daeSBarry Smith @*/
197d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
198d71ae5a4SJacob Faibussowitsch {
1995c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
2005c6c1daeSBarry Smith 
2015c6c1daeSBarry Smith   PetscFunctionBegin;
2025c6c1daeSBarry Smith   *fd = vascii->fd;
2033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2045c6c1daeSBarry Smith }
2055c6c1daeSBarry Smith 
206d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
207d71ae5a4SJacob Faibussowitsch {
2085c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
2095c6c1daeSBarry Smith 
2105c6c1daeSBarry Smith   PetscFunctionBegin;
2115c6c1daeSBarry Smith   *mode = vascii->mode;
2123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2135c6c1daeSBarry Smith }
2145c6c1daeSBarry Smith 
215d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
216d71ae5a4SJacob Faibussowitsch {
2175c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
2185c6c1daeSBarry Smith 
2195c6c1daeSBarry Smith   PetscFunctionBegin;
2205c6c1daeSBarry Smith   vascii->mode = mode;
2213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2225c6c1daeSBarry Smith }
2235c6c1daeSBarry Smith 
2245c6c1daeSBarry Smith /*
2255c6c1daeSBarry Smith    If petsc_history is on, then all Petsc*Printf() results are saved
2265c6c1daeSBarry Smith    if the appropriate (usually .petschistory) file.
2275c6c1daeSBarry Smith */
22895c0884eSLisandro Dalcin PETSC_INTERN FILE *petsc_history;
2295c6c1daeSBarry Smith 
2305c6c1daeSBarry Smith /*@
2313f423023SBarry Smith   PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times before printing
2325c6c1daeSBarry Smith 
233cf53795eSBarry Smith   Not Collective, but only first processor in set has any effect; No Fortran Support
2345c6c1daeSBarry Smith 
2355c6c1daeSBarry Smith   Input Parameters:
236811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
2375c6c1daeSBarry Smith - tabs   - number of tabs
2385c6c1daeSBarry Smith 
2395c6c1daeSBarry Smith   Level: developer
2405c6c1daeSBarry Smith 
2413f423023SBarry Smith   Note:
2423f423023SBarry Smith   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
2433f423023SBarry Smith 
2443f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
2453f423023SBarry Smith           `PetscViewerASCIIGetTab()`,
246db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
2473f423023SBarry Smith           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
2483f423023SBarry Smith           `PetscViewerASCIIPushTab()`
2495c6c1daeSBarry Smith @*/
250d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
251d71ae5a4SJacob Faibussowitsch {
2525c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
2535c6c1daeSBarry Smith   PetscBool          iascii;
2545c6c1daeSBarry Smith 
2555c6c1daeSBarry Smith   PetscFunctionBegin;
2565c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
258a297a907SKarl Rupp   if (iascii) ascii->tab = tabs;
2593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2605c6c1daeSBarry Smith }
2615c6c1daeSBarry Smith 
2625c6c1daeSBarry Smith /*@
263811af0c4SBarry Smith   PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.
2645c6c1daeSBarry Smith 
265cf53795eSBarry Smith   Not Collective, meaningful on first processor only; No Fortran Support
2665c6c1daeSBarry Smith 
26720f4b53cSBarry Smith   Input Parameter:
268811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
269a2b725a8SWilliam Gropp 
27020f4b53cSBarry Smith   Output Parameter:
2715c6c1daeSBarry Smith . tabs - number of tabs
2725c6c1daeSBarry Smith 
2735c6c1daeSBarry Smith   Level: developer
2745c6c1daeSBarry Smith 
2753f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
2763f423023SBarry Smith           `PetscViewerASCIISetTab()`,
277db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
278db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
2795c6c1daeSBarry Smith @*/
280d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
281d71ae5a4SJacob Faibussowitsch {
2825c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
2835c6c1daeSBarry Smith   PetscBool          iascii;
2845c6c1daeSBarry Smith 
2855c6c1daeSBarry Smith   PetscFunctionBegin;
2865c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2879566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
288a297a907SKarl Rupp   if (iascii && tabs) *tabs = ascii->tab;
2893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2905c6c1daeSBarry Smith }
2915c6c1daeSBarry Smith 
2925c6c1daeSBarry Smith /*@
2933f423023SBarry Smith   PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing
2945c6c1daeSBarry Smith 
295cf53795eSBarry Smith   Not Collective, but only first processor in set has any effect; No Fortran Support
2965c6c1daeSBarry Smith 
2975c6c1daeSBarry Smith   Input Parameters:
298811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
2995c6c1daeSBarry Smith - tabs   - number of tabs
3005c6c1daeSBarry Smith 
3015c6c1daeSBarry Smith   Level: developer
3025c6c1daeSBarry Smith 
3033f423023SBarry Smith   Note:
3043f423023SBarry Smith   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
3053f423023SBarry Smith 
3063f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
307db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
308db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
3095c6c1daeSBarry Smith @*/
310d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
311d71ae5a4SJacob Faibussowitsch {
3125c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3135c6c1daeSBarry Smith   PetscBool          iascii;
3145c6c1daeSBarry Smith 
3155c6c1daeSBarry Smith   PetscFunctionBegin;
3165c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
3179566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
318a297a907SKarl Rupp   if (iascii) ascii->tab += tabs;
3193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3205c6c1daeSBarry Smith }
3215c6c1daeSBarry Smith 
3225c6c1daeSBarry Smith /*@
3233f423023SBarry Smith   PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing
3245c6c1daeSBarry Smith 
325cf53795eSBarry Smith   Not Collective, but only first processor in set has any effect; No Fortran Support
3265c6c1daeSBarry Smith 
3275c6c1daeSBarry Smith   Input Parameters:
328811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
3295c6c1daeSBarry Smith - tabs   - number of tabs
3305c6c1daeSBarry Smith 
3315c6c1daeSBarry Smith   Level: developer
3325c6c1daeSBarry Smith 
3333f423023SBarry Smith   Note:
3343f423023SBarry Smith   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
3353f423023SBarry Smith 
3363f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
337db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
3383f423023SBarry Smith           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
3393f423023SBarry Smith           `PetscViewerASCIIPushTab()`
3405c6c1daeSBarry Smith @*/
341d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
342d71ae5a4SJacob Faibussowitsch {
3435c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3445c6c1daeSBarry Smith   PetscBool          iascii;
3455c6c1daeSBarry Smith 
3465c6c1daeSBarry Smith   PetscFunctionBegin;
3475c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
3489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
349a297a907SKarl Rupp   if (iascii) ascii->tab -= tabs;
3503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3515c6c1daeSBarry Smith }
3525c6c1daeSBarry Smith 
3535c6c1daeSBarry Smith /*@C
354811af0c4SBarry Smith   PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer
3555c6c1daeSBarry Smith 
356c3339decSBarry Smith   Collective
3575c6c1daeSBarry Smith 
35820f4b53cSBarry Smith   Input Parameter:
359811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
3605c6c1daeSBarry Smith 
3615c6c1daeSBarry Smith   Level: intermediate
3625c6c1daeSBarry Smith 
363811af0c4SBarry Smith   Note:
364811af0c4SBarry Smith   See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
3655c6c1daeSBarry Smith 
366d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
367db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
368db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
3695c6c1daeSBarry Smith @*/
370d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
371d71ae5a4SJacob Faibussowitsch {
3725c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3735c6c1daeSBarry Smith   PetscBool          iascii;
3745c6c1daeSBarry Smith 
3755c6c1daeSBarry Smith   PetscFunctionBegin;
3765c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
37728b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
3789566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
3791575c14dSBarry Smith   if (iascii) ascii->allowsynchronized++;
3803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3811575c14dSBarry Smith }
3821575c14dSBarry Smith 
3831575c14dSBarry Smith /*@C
384811af0c4SBarry Smith   PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer
3851575c14dSBarry Smith 
386c3339decSBarry Smith   Collective
3871575c14dSBarry Smith 
38820f4b53cSBarry Smith   Input Parameter:
389811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
3901575c14dSBarry Smith 
3911575c14dSBarry Smith   Level: intermediate
3921575c14dSBarry Smith 
393811af0c4SBarry Smith   Note:
394811af0c4SBarry Smith   See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
3951575c14dSBarry Smith 
396d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
397db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
398db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
3991575c14dSBarry Smith @*/
400d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
401d71ae5a4SJacob Faibussowitsch {
4021575c14dSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4031575c14dSBarry Smith   PetscBool          iascii;
4041575c14dSBarry Smith 
4051575c14dSBarry Smith   PetscFunctionBegin;
4061575c14dSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
40728b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
4089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4091575c14dSBarry Smith   if (iascii) {
4101575c14dSBarry Smith     ascii->allowsynchronized--;
41108401ef6SPierre Jolivet     PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()");
4121575c14dSBarry Smith   }
4133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4145c6c1daeSBarry Smith }
4155c6c1daeSBarry Smith 
4161c297824SMatthew G. Knepley /*@C
417811af0c4SBarry Smith   PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
4185c6c1daeSBarry Smith   lines are tabbed.
4195c6c1daeSBarry Smith 
420c410d8ccSBarry Smith   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
4215c6c1daeSBarry Smith 
42220f4b53cSBarry Smith   Input Parameter:
423811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
4245c6c1daeSBarry Smith 
4255c6c1daeSBarry Smith   Level: developer
4265c6c1daeSBarry Smith 
427d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
428db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
429db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
4305c6c1daeSBarry Smith @*/
431d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
432d71ae5a4SJacob Faibussowitsch {
4335c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4345c6c1daeSBarry Smith   PetscBool          iascii;
4355c6c1daeSBarry Smith 
4365c6c1daeSBarry Smith   PetscFunctionBegin;
4375c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
4389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
439a297a907SKarl Rupp   if (iascii) ascii->tab++;
4403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4415c6c1daeSBarry Smith }
4425c6c1daeSBarry Smith 
4431c297824SMatthew G. Knepley /*@C
4443f423023SBarry Smith   PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by
4453f423023SBarry Smith   `PetscViewerASCIIPushTab()`
4465c6c1daeSBarry Smith 
447c410d8ccSBarry Smith   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
4485c6c1daeSBarry Smith 
44920f4b53cSBarry Smith   Input Parameter:
450811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
4515c6c1daeSBarry Smith 
4525c6c1daeSBarry Smith   Level: developer
4535c6c1daeSBarry Smith 
454d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
455db781477SPatrick Sanan           `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
456db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
4575c6c1daeSBarry Smith @*/
458d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
459d71ae5a4SJacob Faibussowitsch {
4605c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4615c6c1daeSBarry Smith   PetscBool          iascii;
4625c6c1daeSBarry Smith 
4635c6c1daeSBarry Smith   PetscFunctionBegin;
4645c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
4659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4665c6c1daeSBarry Smith   if (iascii) {
46708401ef6SPierre Jolivet     PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed");
4685c6c1daeSBarry Smith     ascii->tab--;
4695c6c1daeSBarry Smith   }
4703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4715c6c1daeSBarry Smith }
4725c6c1daeSBarry Smith 
4735c6c1daeSBarry Smith /*@
474c410d8ccSBarry Smith   PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer`
4755c6c1daeSBarry Smith 
476c410d8ccSBarry Smith   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
4775c6c1daeSBarry Smith 
4785c6c1daeSBarry Smith   Input Parameters:
479811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
480811af0c4SBarry Smith - flg    - `PETSC_TRUE` or `PETSC_FALSE`
4815c6c1daeSBarry Smith 
4825c6c1daeSBarry Smith   Level: developer
4835c6c1daeSBarry Smith 
484d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
485db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
486db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
4875c6c1daeSBarry Smith @*/
488d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
489d71ae5a4SJacob Faibussowitsch {
4905c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4915c6c1daeSBarry Smith   PetscBool          iascii;
4925c6c1daeSBarry Smith 
4935c6c1daeSBarry Smith   PetscFunctionBegin;
4945c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
4959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
4965c6c1daeSBarry Smith   if (iascii) {
497a297a907SKarl Rupp     if (flg) ascii->tab = ascii->tab_store;
498a297a907SKarl Rupp     else {
4995c6c1daeSBarry Smith       ascii->tab_store = ascii->tab;
5005c6c1daeSBarry Smith       ascii->tab       = 0;
5015c6c1daeSBarry Smith     }
5025c6c1daeSBarry Smith   }
5033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5045c6c1daeSBarry Smith }
5055c6c1daeSBarry Smith 
506e4096674SBarry Smith #if defined(PETSC_USE_FORTRAN_BINDINGS)
507e4096674SBarry Smith 
508e4096674SBarry Smith   #if defined(PETSC_HAVE_FORTRAN_CAPS)
509e4096674SBarry Smith     #define petscviewerasciiopenwithfileunit_ PETSCVIEWERASCIIOPENWITHFILEUNIT
510e4096674SBarry Smith     #define petscviewerasciisetfilefileunit_  PETSCVIEWERASCIISETFILEUNIT
511e4096674SBarry Smith     #define petscfortranprinttounit_          PETSCFORTRANPRINTTOUNIT
512e4096674SBarry Smith   #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
513e4096674SBarry Smith     #define petscviewerasciiopenwithfileunit_ petscviewerasciiopenwithfileunit
514e4096674SBarry Smith     #define petscviewerasciisetfileunit_      petscviewerasciisetfileunit
515e4096674SBarry Smith     #define petscfortranprinttounit_          petscfortranprinttounit
516e4096674SBarry Smith   #endif
517e4096674SBarry Smith 
518e4096674SBarry Smith   #if defined(__cplusplus)
519e4096674SBarry Smith extern "C" void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
520e4096674SBarry Smith   #else
521e4096674SBarry Smith extern void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
522e4096674SBarry Smith   #endif
523e4096674SBarry Smith 
524e4096674SBarry Smith   #define PETSCDEFAULTBUFFERSIZE 8 * 1024
525e4096674SBarry Smith 
526*10450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
527e4096674SBarry Smith /*@M
528e4096674SBarry Smith   PetscViewerASCIISetFileUnit - sets the `PETSCASCIIVIEWER` to write to a Fortan IO unit
529e4096674SBarry Smith 
530*10450e9eSJacob Faibussowitsch   Synopsis:
531*10450e9eSJacob Faibussowitsch   #include <petscviewer.h>
532e4096674SBarry Smith   void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr)
533e4096674SBarry Smith 
534e4096674SBarry Smith   Input Parameters:
535e4096674SBarry Smith + lab  - the viewer
536e4096674SBarry Smith - unit - the unit number
537e4096674SBarry Smith 
538e4096674SBarry Smith   Output Parameter:
539e4096674SBarry Smith . ierr - the error code
540e4096674SBarry Smith 
541*10450e9eSJacob Faibussowitsch   Level: intermediate
542*10450e9eSJacob Faibussowitsch 
543e4096674SBarry Smith   Note:
544e4096674SBarry Smith   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
545e4096674SBarry Smith 
546aec76313SJacob Faibussowitsch   Fortran Notes:
547e4096674SBarry Smith   Only for Fortran, use  `PetscViewerASCIISetFILE()` for C
548e4096674SBarry Smith 
549e4096674SBarry Smith .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`
550e4096674SBarry Smith @*/
551e4096674SBarry Smith PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, PetscInt *unit, PetscErrorCode *ierr)
552e4096674SBarry Smith {
553e4096674SBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)(*lab)->data;
554e4096674SBarry Smith 
555e4096674SBarry Smith   if (vascii->mode == FILE_MODE_READ) {
556e4096674SBarry Smith     *ierr = PETSC_ERR_ARG_WRONGSTATE;
557e4096674SBarry Smith     return;
558e4096674SBarry Smith   }
559e4096674SBarry Smith   vascii->fileunit = *unit;
560e4096674SBarry Smith }
561e4096674SBarry Smith 
562*10450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
563e4096674SBarry Smith /*@M
564e4096674SBarry Smith   PetscViewerASCIIOpenWithFileUnit - opens a `PETSCASCIIVIEWER` to write to a Fortan IO unit
565e4096674SBarry Smith 
566*10450e9eSJacob Faibussowitsch   Synopsis:
567*10450e9eSJacob Faibussowitsch   #include <petscviewer.h>
568e4096674SBarry Smith   void PetscViewerASCIIOpenWithFileUnit(MPI_Comm comm, PetscInt unit, PetscViewer viewer, PetscErrorCode ierr)
569e4096674SBarry Smith 
570e4096674SBarry Smith   Input Parameters:
571e4096674SBarry Smith + comm - the `MPI_Comm` to share the viewer
572e4096674SBarry Smith - unit - the unit number
573e4096674SBarry Smith 
574e4096674SBarry Smith   Output Parameters:
575e4096674SBarry Smith + lab  - the viewer
576e4096674SBarry Smith - ierr - the error code
577e4096674SBarry Smith 
578*10450e9eSJacob Faibussowitsch   Level: intermediate
579*10450e9eSJacob Faibussowitsch 
580e4096674SBarry Smith   Note:
581e4096674SBarry Smith   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
582e4096674SBarry Smith 
583aec76313SJacob Faibussowitsch   Fortran Notes:
584e4096674SBarry Smith   Only for Fortran, use  `PetscViewerASCIIOpenWithFILE()` for C
585e4096674SBarry Smith 
586e4096674SBarry Smith .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()`
587e4096674SBarry Smith @*/
588e4096674SBarry Smith PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Comm *comm, PetscInt *unit, PetscViewer *lab, PetscErrorCode *ierr)
589e4096674SBarry Smith {
590e4096674SBarry Smith   *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab);
591e4096674SBarry Smith   if (*ierr) return;
592e4096674SBarry Smith   *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII);
593e4096674SBarry Smith   if (*ierr) return;
594e4096674SBarry Smith   *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE);
595e4096674SBarry Smith   if (*ierr) return;
596e4096674SBarry Smith   petscviewerasciisetfileunit_(lab, unit, ierr);
597e4096674SBarry Smith }
598e4096674SBarry Smith 
599e4096674SBarry Smith static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
600e4096674SBarry Smith {
601e4096674SBarry Smith   PetscErrorCode ierr;
602e4096674SBarry Smith   char           str[PETSCDEFAULTBUFFERSIZE];
603e4096674SBarry Smith   size_t         len;
604e4096674SBarry Smith 
605e4096674SBarry Smith   PetscFunctionBegin;
606e4096674SBarry Smith   PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp));
607e4096674SBarry Smith   PetscCall(PetscStrlen(str, &len));
608e4096674SBarry Smith   petscfortranprinttounit_(&unit, str, &ierr, (int)len);
609e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
610e4096674SBarry Smith }
611e4096674SBarry Smith 
612e4096674SBarry Smith static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
613e4096674SBarry Smith {
614e4096674SBarry Smith   PetscErrorCode ierr;
615e4096674SBarry Smith   size_t         len;
616e4096674SBarry Smith 
617e4096674SBarry Smith   PetscFunctionBegin;
618e4096674SBarry Smith   PetscCall(PetscStrlen(str, &len));
619e4096674SBarry Smith   petscfortranprinttounit_(&unit, str, &ierr, (int)len);
620e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
621e4096674SBarry Smith }
622e4096674SBarry Smith 
623e4096674SBarry Smith #else
624e4096674SBarry Smith 
625e4096674SBarry Smith /* these will never be used; but are needed to link with */
626e4096674SBarry Smith static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
627e4096674SBarry Smith {
628e4096674SBarry Smith   PetscFunctionBegin;
629e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
630e4096674SBarry Smith }
631e4096674SBarry Smith 
632e4096674SBarry Smith static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
633e4096674SBarry Smith {
634e4096674SBarry Smith   PetscFunctionBegin;
635e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
636e4096674SBarry Smith }
637e4096674SBarry Smith #endif
638e4096674SBarry Smith 
6395c6c1daeSBarry Smith /*@C
6405c6c1daeSBarry Smith   PetscViewerASCIIPrintf - Prints to a file, only from the first
6413f423023SBarry Smith   processor in the `PetscViewer` of type `PETSCVIEWERASCII`
6425c6c1daeSBarry Smith 
643c410d8ccSBarry Smith   Not Collective, but only the first MPI rank in the viewer has any effect
6445c6c1daeSBarry Smith 
6455c6c1daeSBarry Smith   Input Parameters:
646811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
6475c6c1daeSBarry Smith - format - the usual printf() format string
6485c6c1daeSBarry Smith 
6495c6c1daeSBarry Smith   Level: developer
6505c6c1daeSBarry Smith 
651aec76313SJacob Faibussowitsch   Fortran Notes:
652c410d8ccSBarry Smith   The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran.
6535c6c1daeSBarry Smith   That is, you can only pass a single character string from Fortran.
6545c6c1daeSBarry Smith 
655d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
656db781477SPatrick Sanan           `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
657db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
6585c6c1daeSBarry Smith @*/
659d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
660d71ae5a4SJacob Faibussowitsch {
6615c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
6625c6c1daeSBarry Smith   PetscMPIInt        rank;
663dd2fa690SBarry Smith   PetscInt           tab, intab = ascii->tab;
6645c6c1daeSBarry Smith   FILE              *fd = ascii->fd;
6653f08860eSBarry Smith   PetscBool          iascii;
6665c6c1daeSBarry Smith 
6675c6c1daeSBarry Smith   PetscFunctionBegin;
6685c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
66928b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
6705c6c1daeSBarry Smith   PetscValidCharPointer(format, 2);
6719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
67228b400f6SJacob Faibussowitsch   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
6739566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
6743ba16761SJacob Faibussowitsch   if (rank) PetscFunctionReturn(PETSC_SUCCESS);
6753f08860eSBarry Smith 
6763f08860eSBarry Smith   if (ascii->bviewer) { /* pass string up to parent viewer */
6773f08860eSBarry Smith     char   *string;
6783f08860eSBarry Smith     va_list Argp;
6793f08860eSBarry Smith     size_t  fullLength;
6803f08860eSBarry Smith 
6819566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
6823f08860eSBarry Smith     va_start(Argp, format);
6839566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(string, QUEUESTRINGSIZE, format, &fullLength, Argp));
6843f08860eSBarry Smith     va_end(Argp);
6859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%s", string));
6869566063dSJacob Faibussowitsch     PetscCall(PetscFree(string));
6873f08860eSBarry Smith   } else { /* write directly to file */
6885c6c1daeSBarry Smith     va_list Argp;
689559f443fSBarry Smith     /* flush my own messages that I may have queued up */
690559f443fSBarry Smith     PrintfQueue next = ascii->petsc_printfqueuebase, previous;
691559f443fSBarry Smith     PetscInt    i;
692559f443fSBarry Smith     for (i = 0; i < ascii->petsc_printfqueuelength; i++) {
693e4096674SBarry Smith       if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "%s", next->string));
694e4096674SBarry Smith       else PetscCall(PetscFPrintfFortran(ascii->fileunit, next->string));
695559f443fSBarry Smith       previous = next;
696559f443fSBarry Smith       next     = next->next;
6979566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
6989566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
699559f443fSBarry Smith     }
70002c9f0b5SLisandro Dalcin     ascii->petsc_printfqueue       = NULL;
701559f443fSBarry Smith     ascii->petsc_printfqueuelength = 0;
702dd2fa690SBarry Smith     tab                            = intab;
703e4096674SBarry Smith     while (tab--) {
704e4096674SBarry Smith       if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "  "));
705e4096674SBarry Smith       else PetscCall(PetscFPrintfFortran(ascii->fileunit, "   "));
706e4096674SBarry Smith     }
7075c6c1daeSBarry Smith 
7085c6c1daeSBarry Smith     va_start(Argp, format);
709e4096674SBarry Smith     if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
710e4096674SBarry Smith     else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
711eae3dc7dSJacob Faibussowitsch     va_end(Argp);
712c69effb2SJacob Faibussowitsch     PetscCall(PetscFFlush(fd));
7135c6c1daeSBarry Smith   }
7143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7155c6c1daeSBarry Smith }
7165c6c1daeSBarry Smith 
7175c6c1daeSBarry Smith /*@C
718c410d8ccSBarry Smith   PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.
7195c6c1daeSBarry Smith 
720c3339decSBarry Smith   Collective
7215c6c1daeSBarry Smith 
7225c6c1daeSBarry Smith   Input Parameters:
7233f423023SBarry Smith + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
7245c6c1daeSBarry Smith - name   - the name of the file it should use
7255c6c1daeSBarry Smith 
7265c6c1daeSBarry Smith   Level: advanced
7275c6c1daeSBarry Smith 
728c410d8ccSBarry Smith   Note:
729c410d8ccSBarry Smith   This will have no effect on viewers that are not related to files
730c410d8ccSBarry Smith 
731d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
732db781477SPatrick Sanan           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
7335c6c1daeSBarry Smith @*/
734d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
735d71ae5a4SJacob Faibussowitsch {
736cc843e7aSLisandro Dalcin   char filename[PETSC_MAX_PATH_LEN];
7375c6c1daeSBarry Smith 
7385c6c1daeSBarry Smith   PetscFunctionBegin;
7395c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
7405c6c1daeSBarry Smith   PetscValidCharPointer(name, 2);
7419566063dSJacob Faibussowitsch   PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
742cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
7433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7445c6c1daeSBarry Smith }
7455c6c1daeSBarry Smith 
7465c6c1daeSBarry Smith /*@C
747c410d8ccSBarry Smith   PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using
7485c6c1daeSBarry Smith 
7495c6c1daeSBarry Smith   Not Collective
7505c6c1daeSBarry Smith 
7515c6c1daeSBarry Smith   Input Parameter:
7523f423023SBarry Smith . viewer - the `PetscViewer`
7535c6c1daeSBarry Smith 
7545c6c1daeSBarry Smith   Output Parameter:
7555c6c1daeSBarry Smith . name - the name of the file it is using
7565c6c1daeSBarry Smith 
7575c6c1daeSBarry Smith   Level: advanced
7585c6c1daeSBarry Smith 
759c410d8ccSBarry Smith   Note:
760c410d8ccSBarry Smith   This will have no effect on viewers that are not related to files
761c410d8ccSBarry Smith 
762d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
7635c6c1daeSBarry Smith @*/
764d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
765d71ae5a4SJacob Faibussowitsch {
7665c6c1daeSBarry Smith   PetscFunctionBegin;
7675c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
7686e05b1faSLisandro Dalcin   PetscValidPointer(name, 2);
769cac4c232SBarry Smith   PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
7703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7715c6c1daeSBarry Smith }
7725c6c1daeSBarry Smith 
773d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
774d71ae5a4SJacob Faibussowitsch {
7755c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
7765c6c1daeSBarry Smith 
7775c6c1daeSBarry Smith   PetscFunctionBegin;
7785c6c1daeSBarry Smith   *name = vascii->filename;
7793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7805c6c1daeSBarry Smith }
7815c6c1daeSBarry Smith 
782bf31d2d3SBarry Smith #include <errno.h>
783d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
784d71ae5a4SJacob Faibussowitsch {
7855c6c1daeSBarry Smith   size_t             len;
786bbcf679cSJacob Faibussowitsch   char               fname[PETSC_MAX_PATH_LEN], *gz = NULL;
7875c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
7885c6c1daeSBarry Smith   PetscBool          isstderr, isstdout;
7895c6c1daeSBarry Smith   PetscMPIInt        rank;
7905c6c1daeSBarry Smith 
7915c6c1daeSBarry Smith   PetscFunctionBegin;
7929566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileClose_ASCII(viewer));
7933ba16761SJacob Faibussowitsch   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
7949566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &vascii->filename));
7955c6c1daeSBarry Smith 
7965c6c1daeSBarry Smith   /* Is this file to be compressed */
7975c6c1daeSBarry Smith   vascii->storecompressed = PETSC_FALSE;
798a297a907SKarl Rupp 
7999566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
8005c6c1daeSBarry Smith   if (gz) {
8019566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(gz, &len));
8025c6c1daeSBarry Smith     if (len == 3) {
80308401ef6SPierre 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");
8045c6c1daeSBarry Smith       *gz                     = 0;
8055c6c1daeSBarry Smith       vascii->storecompressed = PETSC_TRUE;
8065c6c1daeSBarry Smith     }
8075c6c1daeSBarry Smith   }
8089566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
809dd400576SPatrick Sanan   if (rank == 0) {
8109566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
8119566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
8125c6c1daeSBarry Smith     /* empty filename means stdout */
8135c6c1daeSBarry Smith     if (name[0] == 0) isstdout = PETSC_TRUE;
8145c6c1daeSBarry Smith     if (isstderr) vascii->fd = PETSC_STDERR;
8155c6c1daeSBarry Smith     else if (isstdout) vascii->fd = PETSC_STDOUT;
8165c6c1daeSBarry Smith     else {
8179566063dSJacob Faibussowitsch       PetscCall(PetscFixFilename(name, fname));
8185c6c1daeSBarry Smith       switch (vascii->mode) {
819d71ae5a4SJacob Faibussowitsch       case FILE_MODE_READ:
820d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "r");
821d71ae5a4SJacob Faibussowitsch         break;
822d71ae5a4SJacob Faibussowitsch       case FILE_MODE_WRITE:
823d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "w");
824d71ae5a4SJacob Faibussowitsch         break;
825d71ae5a4SJacob Faibussowitsch       case FILE_MODE_APPEND:
826d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "a");
827d71ae5a4SJacob Faibussowitsch         break;
8285c6c1daeSBarry Smith       case FILE_MODE_UPDATE:
8295c6c1daeSBarry Smith         vascii->fd = fopen(fname, "r+");
830a297a907SKarl Rupp         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
8315c6c1daeSBarry Smith         break;
8325c6c1daeSBarry Smith       case FILE_MODE_APPEND_UPDATE:
8335c6c1daeSBarry Smith         /* I really want a file which is opened at the end for updating,
8345c6c1daeSBarry Smith            not a+, which opens at the beginning, but makes writes at the end.
8355c6c1daeSBarry Smith         */
8365c6c1daeSBarry Smith         vascii->fd = fopen(fname, "r+");
837a297a907SKarl Rupp         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
8383ba16761SJacob Faibussowitsch         else {
8393ba16761SJacob Faibussowitsch           int ret = fseek(vascii->fd, 0, SEEK_END);
8403ba16761SJacob Faibussowitsch           PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
8413ba16761SJacob Faibussowitsch         }
8425c6c1daeSBarry Smith         break;
843d71ae5a4SJacob Faibussowitsch       default:
844d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
8455c6c1daeSBarry Smith       }
846bf31d2d3SBarry Smith       PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
8475c6c1daeSBarry Smith     }
8485c6c1daeSBarry Smith   }
8495c6c1daeSBarry Smith #if defined(PETSC_USE_LOG)
8503ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
8515c6c1daeSBarry Smith #endif
8523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8535c6c1daeSBarry Smith }
8545c6c1daeSBarry Smith 
855d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
856d71ae5a4SJacob Faibussowitsch {
8575c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
8585c6c1daeSBarry Smith 
8595c6c1daeSBarry Smith   PetscFunctionBegin;
8609566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
86128b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
862e5afcf28SBarry Smith   /*
8639530cbd7SBarry Smith      The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
8649530cbd7SBarry 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
8659530cbd7SBarry Smith      (since the count never gets to zero) in some examples this displays information that otherwise would be lost
8669530cbd7SBarry Smith 
8679530cbd7SBarry Smith      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
8689530cbd7SBarry Smith      PCView_GASM().
869e5afcf28SBarry Smith   */
8709566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
8719566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(subcomm, outviewer));
8729566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
8739566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
8745c6c1daeSBarry Smith   ovascii            = (PetscViewer_ASCII *)(*outviewer)->data;
8755c6c1daeSBarry Smith   ovascii->fd        = vascii->fd;
8765c6c1daeSBarry Smith   ovascii->tab       = vascii->tab;
877ba5a0b41SBarry Smith   ovascii->closefile = PETSC_FALSE;
8785c6c1daeSBarry Smith 
8795c6c1daeSBarry Smith   vascii->sviewer                                      = *outviewer;
8805c6c1daeSBarry Smith   (*outviewer)->format                                 = viewer->format;
8815c6c1daeSBarry Smith   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
8823f08860eSBarry Smith   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
8833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8845c6c1daeSBarry Smith }
8855c6c1daeSBarry Smith 
886d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
887d71ae5a4SJacob Faibussowitsch {
8885c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
8895c6c1daeSBarry Smith 
8905c6c1daeSBarry Smith   PetscFunctionBegin;
89128b400f6SJacob Faibussowitsch   PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
89208401ef6SPierre Jolivet   PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");
8935c6c1daeSBarry Smith 
8949566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
895e5afcf28SBarry Smith   ascii->sviewer             = NULL;
8965c6c1daeSBarry Smith   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
8979566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(outviewer));
8989566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9005c6c1daeSBarry Smith }
9015c6c1daeSBarry Smith 
902d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
903d71ae5a4SJacob Faibussowitsch {
9042bf49c77SBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
9052bf49c77SBarry Smith 
9062bf49c77SBarry Smith   PetscFunctionBegin;
90748a46eb9SPierre Jolivet   if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
9083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9092bf49c77SBarry Smith }
9102bf49c77SBarry Smith 
9118556b5ebSBarry Smith /*MC
9128556b5ebSBarry Smith    PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file
9138556b5ebSBarry Smith 
914811af0c4SBarry Smith   Level: beginner
915811af0c4SBarry Smith 
916d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
917db781477SPatrick Sanan           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
918db781477SPatrick Sanan           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
9198556b5ebSBarry Smith M*/
920d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
921d71ae5a4SJacob Faibussowitsch {
9225c6c1daeSBarry Smith   PetscViewer_ASCII *vascii;
9235c6c1daeSBarry Smith 
9245c6c1daeSBarry Smith   PetscFunctionBegin;
9254dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&vascii));
9265c6c1daeSBarry Smith   viewer->data = (void *)vascii;
9275c6c1daeSBarry Smith 
9285c6c1daeSBarry Smith   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
9295c6c1daeSBarry Smith   viewer->ops->flush            = PetscViewerFlush_ASCII;
930559f443fSBarry Smith   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
931559f443fSBarry Smith   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
9322bf49c77SBarry Smith   viewer->ops->view             = PetscViewerView_ASCII;
9331d641e7bSMichael Lange   viewer->ops->read             = PetscViewerASCIIRead;
9345c6c1daeSBarry Smith 
9355c6c1daeSBarry Smith   /* defaults to stdout unless set with PetscViewerFileSetName() */
9365c6c1daeSBarry Smith   vascii->fd        = PETSC_STDOUT;
9375c6c1daeSBarry Smith   vascii->mode      = FILE_MODE_WRITE;
93802c9f0b5SLisandro Dalcin   vascii->bviewer   = NULL;
93902c9f0b5SLisandro Dalcin   vascii->subviewer = NULL;
94002c9f0b5SLisandro Dalcin   vascii->sviewer   = NULL;
9415c6c1daeSBarry Smith   vascii->tab       = 0;
9425c6c1daeSBarry Smith   vascii->tab_store = 0;
94302c9f0b5SLisandro Dalcin   vascii->filename  = NULL;
9445c6c1daeSBarry Smith   vascii->closefile = PETSC_TRUE;
9455c6c1daeSBarry Smith 
9469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
9479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
9489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
9499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
9503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9515c6c1daeSBarry Smith }
9525c6c1daeSBarry Smith 
9535c6c1daeSBarry Smith /*@C
954c410d8ccSBarry Smith   PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
9555c6c1daeSBarry Smith   several processors.  Output of the first processor is followed by that of the
9565c6c1daeSBarry Smith   second, etc.
9575c6c1daeSBarry Smith 
958c410d8ccSBarry Smith   Not Collective, must call collective `PetscViewerFlush()` to get the results flushed
9595c6c1daeSBarry Smith 
9605c6c1daeSBarry Smith   Input Parameters:
961811af0c4SBarry Smith + viewer - the `PETSCVIEWERASCII` `PetscViewer`
9625c6c1daeSBarry Smith - format - the usual printf() format string
9635c6c1daeSBarry Smith 
9645c6c1daeSBarry Smith   Level: intermediate
9655c6c1daeSBarry Smith 
96695452b02SPatrick Sanan   Notes:
967811af0c4SBarry Smith   You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
968e6abc3ddSVáclav Hapla   Then you can do multiple independent calls to this routine.
969811af0c4SBarry Smith 
970811af0c4SBarry Smith   The actual synchronized print is then done using `PetscViewerFlush()`.
971811af0c4SBarry Smith   `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
972e6abc3ddSVáclav Hapla   to conclude the "synchronized session".
973811af0c4SBarry Smith 
974e6abc3ddSVáclav Hapla   So the typical calling sequence looks like
975811af0c4SBarry Smith .vb
976811af0c4SBarry Smith     PetscViewerASCIIPushSynchronized(viewer);
977811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
978811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
979811af0c4SBarry Smith     ...
980811af0c4SBarry Smith     PetscViewerFlush(viewer);
981811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
982811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
983811af0c4SBarry Smith     ...
984811af0c4SBarry Smith     PetscViewerFlush(viewer);
985811af0c4SBarry Smith    PetscViewerASCIIPopSynchronized(viewer);
986811af0c4SBarry Smith .ve
9875c6c1daeSBarry Smith 
988aec76313SJacob Faibussowitsch   Fortran Notes:
9895c6c1daeSBarry Smith   Can only print a single character* string
9905c6c1daeSBarry Smith 
991d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
992db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
993db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
9945c6c1daeSBarry Smith @*/
995d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
996d71ae5a4SJacob Faibussowitsch {
9975c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
9983f08860eSBarry Smith   PetscMPIInt        rank;
9995c6c1daeSBarry Smith   PetscInt           tab = vascii->tab;
10005c6c1daeSBarry Smith   MPI_Comm           comm;
10015c6c1daeSBarry Smith   FILE              *fp;
1002559f443fSBarry Smith   PetscBool          iascii, hasbviewer = PETSC_FALSE;
10035c6c1daeSBarry Smith 
10045c6c1daeSBarry Smith   PetscFunctionBegin;
10055c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
10065c6c1daeSBarry Smith   PetscValidCharPointer(format, 2);
10079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
100828b400f6SJacob Faibussowitsch   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
100928b400f6SJacob Faibussowitsch   PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");
10105c6c1daeSBarry Smith 
10119566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
10129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10135c6c1daeSBarry Smith 
1014559f443fSBarry Smith   if (vascii->bviewer) {
1015559f443fSBarry Smith     hasbviewer = PETSC_TRUE;
1016dd400576SPatrick Sanan     if (rank == 0) {
1017559f443fSBarry Smith       vascii = (PetscViewer_ASCII *)vascii->bviewer->data;
10189566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
10199566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
1020559f443fSBarry Smith     }
1021559f443fSBarry Smith   }
10223f08860eSBarry Smith 
1023559f443fSBarry Smith   fp = vascii->fd;
1024559f443fSBarry Smith 
1025dd400576SPatrick Sanan   if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */
10265c6c1daeSBarry Smith     va_list Argp;
1027559f443fSBarry Smith     /* flush my own messages that I may have queued up */
1028559f443fSBarry Smith     PrintfQueue next = vascii->petsc_printfqueuebase, previous;
1029559f443fSBarry Smith     PetscInt    i;
1030559f443fSBarry Smith     for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
10319566063dSJacob Faibussowitsch       PetscCall(PetscFPrintf(comm, fp, "%s", next->string));
1032559f443fSBarry Smith       previous = next;
1033559f443fSBarry Smith       next     = next->next;
10349566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous->string));
10359566063dSJacob Faibussowitsch       PetscCall(PetscFree(previous));
1036559f443fSBarry Smith     }
103702c9f0b5SLisandro Dalcin     vascii->petsc_printfqueue       = NULL;
1038559f443fSBarry Smith     vascii->petsc_printfqueuelength = 0;
10395c6c1daeSBarry Smith 
104048a46eb9SPierre Jolivet     while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, "  "));
10415c6c1daeSBarry Smith 
10425c6c1daeSBarry Smith     va_start(Argp, format);
10439566063dSJacob Faibussowitsch     PetscCall((*PetscVFPrintf)(fp, format, Argp));
1044eae3dc7dSJacob Faibussowitsch     va_end(Argp);
1045c69effb2SJacob Faibussowitsch     PetscCall(PetscFFlush(fp));
10465c6c1daeSBarry Smith     if (petsc_history) {
10475c6c1daeSBarry Smith       va_start(Argp, format);
10489566063dSJacob Faibussowitsch       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1049eae3dc7dSJacob Faibussowitsch       va_end(Argp);
1050c69effb2SJacob Faibussowitsch       PetscCall(PetscFFlush(petsc_history));
10515c6c1daeSBarry Smith     }
10525c6c1daeSBarry Smith     va_end(Argp);
1053559f443fSBarry Smith   } else { /* other processors add to queue */
10545c6c1daeSBarry Smith     char       *string;
10555c6c1daeSBarry Smith     va_list     Argp;
10565c6c1daeSBarry Smith     size_t      fullLength;
10575c6c1daeSBarry Smith     PrintfQueue next;
10585c6c1daeSBarry Smith 
10599566063dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
1060559f443fSBarry Smith     if (vascii->petsc_printfqueue) {
1061559f443fSBarry Smith       vascii->petsc_printfqueue->next = next;
1062559f443fSBarry Smith       vascii->petsc_printfqueue       = next;
1063a297a907SKarl Rupp     } else {
1064559f443fSBarry Smith       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1065a297a907SKarl Rupp     }
1066559f443fSBarry Smith     vascii->petsc_printfqueuelength++;
10675c6c1daeSBarry Smith     next->size = QUEUESTRINGSIZE;
10689566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(next->size, &next->string));
10695c6c1daeSBarry Smith     string = next->string;
10705c6c1daeSBarry Smith     tab *= 2;
1071ad540459SPierre Jolivet     while (tab--) *string++ = ' ';
10725c6c1daeSBarry Smith     va_start(Argp, format);
10739566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
10745c6c1daeSBarry Smith     va_end(Argp);
1075cb500232SBarry Smith     if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
10769566063dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
107714416c0eSBarry Smith       next->size = fullLength + 2 * vascii->tab;
10789566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(next->size, &next->string));
107914416c0eSBarry Smith       string = next->string;
108014416c0eSBarry Smith       tab    = 2 * vascii->tab;
1081ad540459SPierre Jolivet       while (tab--) *string++ = ' ';
108214416c0eSBarry Smith       va_start(Argp, format);
10839566063dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
108414416c0eSBarry Smith       va_end(Argp);
108514416c0eSBarry Smith     }
10865c6c1daeSBarry Smith   }
10873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10885c6c1daeSBarry Smith }
10895c6c1daeSBarry Smith 
10902655f987SMichael Lange /*@C
1091c410d8ccSBarry Smith   PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file
10922655f987SMichael Lange 
1093c410d8ccSBarry Smith   Only MPI rank 0 in the `PetscViewer` may call this
10942655f987SMichael Lange 
10952655f987SMichael Lange   Input Parameters:
10963f423023SBarry Smith + viewer - the `PETSCVIEWERASCII` viewer
1097c410d8ccSBarry Smith . data   - location to write the data, treated as an array of type indicated by `datatype`
1098060da220SMatthew G. Knepley . num    - number of items of data to read
1099aec76313SJacob Faibussowitsch - dtype  - type of data to read
11002655f987SMichael Lange 
110120f4b53cSBarry Smith   Output Parameter:
11023f423023SBarry Smith . count - number of items of data actually read, or `NULL`
1103f8e4bde8SMatthew G. Knepley 
11042655f987SMichael Lange   Level: beginner
11052655f987SMichael Lange 
1106d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1107db781477SPatrick Sanan           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1108db781477SPatrick Sanan           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
11092655f987SMichael Lange @*/
1110d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1111d71ae5a4SJacob Faibussowitsch {
11122655f987SMichael Lange   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
11132655f987SMichael Lange   FILE              *fd     = vascii->fd;
11142655f987SMichael Lange   PetscInt           i;
11153b7fe8c3SMatthew G. Knepley   int                ret = 0;
1116f8859db6SBarry Smith   PetscMPIInt        rank;
11172655f987SMichael Lange 
11182655f987SMichael Lange   PetscFunctionBegin;
11192655f987SMichael Lange   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
11209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1121c5853193SPierre Jolivet   PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1122060da220SMatthew G. Knepley   for (i = 0; i < num; i++) {
1123f8e4bde8SMatthew G. Knepley     if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1124f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1125a05e1a72SSatish Balay     else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1126f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
11279e3e4c22SLisandro Dalcin     else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1128972064b6SLisandro Dalcin     else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1129f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1130f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1131a6e181c6SToby Isaac #if defined(PETSC_USE_REAL___FLOAT128)
1132fba955ccSBarry Smith     else if (dtype == PETSC___FLOAT128) {
1133fba955ccSBarry Smith       double tmp;
1134fba955ccSBarry Smith       ret                     = fscanf(fd, "%lg", &tmp);
1135a6e181c6SToby Isaac       ((__float128 *)data)[i] = tmp;
1136a6e181c6SToby Isaac     }
1137fba955ccSBarry Smith #endif
11389371c9d4SSatish Balay     else
11399371c9d4SSatish Balay       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
114028b400f6SJacob Faibussowitsch     PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1141f7d195e4SLawrence Mitchell     if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
11422655f987SMichael Lange   }
1143060da220SMatthew G. Knepley   if (count) *count = i;
114408401ef6SPierre Jolivet   else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
11453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11462655f987SMichael Lange }
1147