xref: /petsc/src/sys/classes/viewer/impls/ascii/filev.c (revision b8b5be36363868cf48bd7e7da4f4146957780db1)
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;
41*b8b5be36SMartin Diehl   PetscMPIInt        iflg;
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 */
49c8025a54SPierre Jolivet   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, NULL));
505c6c1daeSBarry Smith 
51*b8b5be36SMartin Diehl   PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, &iflg));
52*b8b5be36SMartin Diehl   if (iflg) {
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;
74*b8b5be36SMartin Diehl     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, &iflg));
75*b8b5be36SMartin Diehl     if (iflg && 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;
79*b8b5be36SMartin Diehl     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, &iflg));
80*b8b5be36SMartin Diehl     if (iflg && 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 
985c6c1daeSBarry Smith /*@C
99811af0c4SBarry Smith   PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`.
1005c6c1daeSBarry Smith 
10135cb6cd3SPierre Jolivet   Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer; No Fortran Support
1025c6c1daeSBarry Smith 
103f8859db6SBarry Smith   Input Parameter:
1043f423023SBarry Smith . viewer - `PetscViewer` context, obtained from `PetscViewerASCIIOpen()`
105f8859db6SBarry Smith 
106f8859db6SBarry Smith   Output Parameter:
107f8859db6SBarry Smith . fd - file pointer
108f8859db6SBarry Smith 
1095c6c1daeSBarry Smith   Level: intermediate
1105c6c1daeSBarry Smith 
111811af0c4SBarry Smith   Note:
112c410d8ccSBarry Smith   For the standard `PETSCVIEWERASCII` the value is valid only on MPI rank 0 of the viewer
113811af0c4SBarry Smith 
1143f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`,
1153f423023SBarry Smith           `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
1165c6c1daeSBarry Smith @*/
117d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
118d71ae5a4SJacob Faibussowitsch {
1195c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1205c6c1daeSBarry Smith 
1215c6c1daeSBarry Smith   PetscFunctionBegin;
122c621c6acSBarry Smith   PetscCheck(!vascii->fileunit, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot request file pointer for viewers that use Fortran files");
1235c6c1daeSBarry Smith   *fd = vascii->fd;
1243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1255c6c1daeSBarry Smith }
1265c6c1daeSBarry Smith 
12734e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
128d71ae5a4SJacob Faibussowitsch {
1295c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1305c6c1daeSBarry Smith 
1315c6c1daeSBarry Smith   PetscFunctionBegin;
1325c6c1daeSBarry Smith   *mode = vascii->mode;
1333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1345c6c1daeSBarry Smith }
1355c6c1daeSBarry Smith 
13634e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
137d71ae5a4SJacob Faibussowitsch {
1385c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1395c6c1daeSBarry Smith 
1405c6c1daeSBarry Smith   PetscFunctionBegin;
1415c6c1daeSBarry Smith   vascii->mode = mode;
1423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1435c6c1daeSBarry Smith }
1445c6c1daeSBarry Smith 
1455c6c1daeSBarry Smith /*
1465c6c1daeSBarry Smith    If petsc_history is on, then all Petsc*Printf() results are saved
1475c6c1daeSBarry Smith    if the appropriate (usually .petschistory) file.
1485c6c1daeSBarry Smith */
14995c0884eSLisandro Dalcin PETSC_INTERN FILE *petsc_history;
1505c6c1daeSBarry Smith 
1515c6c1daeSBarry Smith /*@
1523f423023SBarry Smith   PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times before printing
1535c6c1daeSBarry Smith 
154cf53795eSBarry Smith   Not Collective, but only first processor in set has any effect; No Fortran Support
1555c6c1daeSBarry Smith 
1565c6c1daeSBarry Smith   Input Parameters:
157811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
1585c6c1daeSBarry Smith - tabs   - number of tabs
1595c6c1daeSBarry Smith 
1605c6c1daeSBarry Smith   Level: developer
1615c6c1daeSBarry Smith 
1623f423023SBarry Smith   Note:
1633f423023SBarry Smith   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
1643f423023SBarry Smith 
1653f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
1663f423023SBarry Smith           `PetscViewerASCIIGetTab()`,
167db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
1683f423023SBarry Smith           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
1693f423023SBarry Smith           `PetscViewerASCIIPushTab()`
1705c6c1daeSBarry Smith @*/
171d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
172d71ae5a4SJacob Faibussowitsch {
1735c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
1749f196a02SMartin Diehl   PetscBool          isascii;
1755c6c1daeSBarry Smith 
1765c6c1daeSBarry Smith   PetscFunctionBegin;
1775c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1789f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1799f196a02SMartin Diehl   if (isascii) ascii->tab = tabs;
1803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1815c6c1daeSBarry Smith }
1825c6c1daeSBarry Smith 
1835c6c1daeSBarry Smith /*@
184811af0c4SBarry Smith   PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.
1855c6c1daeSBarry Smith 
186cf53795eSBarry Smith   Not Collective, meaningful on first processor only; No Fortran Support
1875c6c1daeSBarry Smith 
18820f4b53cSBarry Smith   Input Parameter:
189811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
190a2b725a8SWilliam Gropp 
19120f4b53cSBarry Smith   Output Parameter:
1925c6c1daeSBarry Smith . tabs - number of tabs
1935c6c1daeSBarry Smith 
1945c6c1daeSBarry Smith   Level: developer
1955c6c1daeSBarry Smith 
1963f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
1973f423023SBarry Smith           `PetscViewerASCIISetTab()`,
198db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
199db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
2005c6c1daeSBarry Smith @*/
201d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
202d71ae5a4SJacob Faibussowitsch {
2035c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
2049f196a02SMartin Diehl   PetscBool          isascii;
2055c6c1daeSBarry Smith 
2065c6c1daeSBarry Smith   PetscFunctionBegin;
2075c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2089f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2099f196a02SMartin Diehl   if (isascii && tabs) *tabs = ascii->tab;
2103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2115c6c1daeSBarry Smith }
2125c6c1daeSBarry Smith 
2135c6c1daeSBarry Smith /*@
2143f423023SBarry Smith   PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing
2155c6c1daeSBarry Smith 
216cf53795eSBarry Smith   Not Collective, but only first processor in set has any effect; No Fortran Support
2175c6c1daeSBarry Smith 
2185c6c1daeSBarry Smith   Input Parameters:
219811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
2205c6c1daeSBarry Smith - tabs   - number of tabs
2215c6c1daeSBarry Smith 
2225c6c1daeSBarry Smith   Level: developer
2235c6c1daeSBarry Smith 
2243f423023SBarry Smith   Note:
2253f423023SBarry Smith   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
2263f423023SBarry Smith 
2273f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
228db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
229db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
2305c6c1daeSBarry Smith @*/
231d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
232d71ae5a4SJacob Faibussowitsch {
2335c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
2349f196a02SMartin Diehl   PetscBool          isascii;
2355c6c1daeSBarry Smith 
2365c6c1daeSBarry Smith   PetscFunctionBegin;
2375c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2389f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2399f196a02SMartin Diehl   if (isascii) ascii->tab += tabs;
2403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2415c6c1daeSBarry Smith }
2425c6c1daeSBarry Smith 
2435c6c1daeSBarry Smith /*@
2443f423023SBarry Smith   PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing
2455c6c1daeSBarry Smith 
246cf53795eSBarry Smith   Not Collective, but only first processor in set has any effect; No Fortran Support
2475c6c1daeSBarry Smith 
2485c6c1daeSBarry Smith   Input Parameters:
249811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
2505c6c1daeSBarry Smith - tabs   - number of tabs
2515c6c1daeSBarry Smith 
2525c6c1daeSBarry Smith   Level: developer
2535c6c1daeSBarry Smith 
2543f423023SBarry Smith   Note:
2553f423023SBarry Smith   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
2563f423023SBarry Smith 
2573f423023SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
258db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
2593f423023SBarry Smith           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
2603f423023SBarry Smith           `PetscViewerASCIIPushTab()`
2615c6c1daeSBarry Smith @*/
262d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
263d71ae5a4SJacob Faibussowitsch {
2645c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
2659f196a02SMartin Diehl   PetscBool          isascii;
2665c6c1daeSBarry Smith 
2675c6c1daeSBarry Smith   PetscFunctionBegin;
2685c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
2699f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2709f196a02SMartin Diehl   if (isascii) ascii->tab -= tabs;
2713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2725c6c1daeSBarry Smith }
2735c6c1daeSBarry Smith 
2745d83a8b1SBarry Smith /*@
275811af0c4SBarry Smith   PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer
2765c6c1daeSBarry Smith 
277c3339decSBarry Smith   Collective
2785c6c1daeSBarry Smith 
27920f4b53cSBarry Smith   Input Parameter:
280811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
2815c6c1daeSBarry Smith 
2825c6c1daeSBarry Smith   Level: intermediate
2835c6c1daeSBarry Smith 
284811af0c4SBarry Smith   Note:
285811af0c4SBarry Smith   See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
2865c6c1daeSBarry Smith 
287d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
288db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
289db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
2905c6c1daeSBarry Smith @*/
291d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
292d71ae5a4SJacob Faibussowitsch {
2935c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
2949f196a02SMartin Diehl   PetscBool          isascii;
2955c6c1daeSBarry Smith 
2965c6c1daeSBarry Smith   PetscFunctionBegin;
2975c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
29828b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
2999f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
3009f196a02SMartin Diehl   if (isascii) ascii->allowsynchronized++;
3013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3021575c14dSBarry Smith }
3031575c14dSBarry Smith 
3045d83a8b1SBarry Smith /*@
305811af0c4SBarry Smith   PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer
3061575c14dSBarry Smith 
307c3339decSBarry Smith   Collective
3081575c14dSBarry Smith 
30920f4b53cSBarry Smith   Input Parameter:
310811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
3111575c14dSBarry Smith 
3121575c14dSBarry Smith   Level: intermediate
3131575c14dSBarry Smith 
314811af0c4SBarry Smith   Note:
315811af0c4SBarry Smith   See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
3161575c14dSBarry Smith 
317d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
318db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
319db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
3201575c14dSBarry Smith @*/
321d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
322d71ae5a4SJacob Faibussowitsch {
3231575c14dSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3249f196a02SMartin Diehl   PetscBool          isascii;
3251575c14dSBarry Smith 
3261575c14dSBarry Smith   PetscFunctionBegin;
3271575c14dSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
32828b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
3299f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
3309f196a02SMartin Diehl   if (isascii) {
3311575c14dSBarry Smith     ascii->allowsynchronized--;
33208401ef6SPierre Jolivet     PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()");
3331575c14dSBarry Smith   }
3343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3355c6c1daeSBarry Smith }
3365c6c1daeSBarry Smith 
3375d83a8b1SBarry Smith /*@
338811af0c4SBarry Smith   PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
3395c6c1daeSBarry Smith   lines are tabbed.
3405c6c1daeSBarry Smith 
341c410d8ccSBarry Smith   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
3425c6c1daeSBarry Smith 
34320f4b53cSBarry Smith   Input Parameter:
344811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
3455c6c1daeSBarry Smith 
3465c6c1daeSBarry Smith   Level: developer
3475c6c1daeSBarry Smith 
348d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
349db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
350db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
3515c6c1daeSBarry Smith @*/
352d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
353d71ae5a4SJacob Faibussowitsch {
3545c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3559f196a02SMartin Diehl   PetscBool          isascii;
3565c6c1daeSBarry Smith 
3575c6c1daeSBarry Smith   PetscFunctionBegin;
3585c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
3599f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
3609f196a02SMartin Diehl   if (isascii) ascii->tab++;
3613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3625c6c1daeSBarry Smith }
3635c6c1daeSBarry Smith 
3645d83a8b1SBarry Smith /*@
3653f423023SBarry Smith   PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by
3663f423023SBarry Smith   `PetscViewerASCIIPushTab()`
3675c6c1daeSBarry Smith 
368c410d8ccSBarry Smith   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
3695c6c1daeSBarry Smith 
37020f4b53cSBarry Smith   Input Parameter:
371811af0c4SBarry Smith . viewer - obtained with `PetscViewerASCIIOpen()`
3725c6c1daeSBarry Smith 
3735c6c1daeSBarry Smith   Level: developer
3745c6c1daeSBarry Smith 
375d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
376db781477SPatrick Sanan           `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
377db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
3785c6c1daeSBarry Smith @*/
379d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
380d71ae5a4SJacob Faibussowitsch {
3815c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
3829f196a02SMartin Diehl   PetscBool          isascii;
3835c6c1daeSBarry Smith 
3845c6c1daeSBarry Smith   PetscFunctionBegin;
3855c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
3869f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
3879f196a02SMartin Diehl   if (isascii) {
38808401ef6SPierre Jolivet     PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed");
3895c6c1daeSBarry Smith     ascii->tab--;
3905c6c1daeSBarry Smith   }
3913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3925c6c1daeSBarry Smith }
3935c6c1daeSBarry Smith 
3945c6c1daeSBarry Smith /*@
395c410d8ccSBarry Smith   PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer`
3965c6c1daeSBarry Smith 
397c410d8ccSBarry Smith   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
3985c6c1daeSBarry Smith 
3995c6c1daeSBarry Smith   Input Parameters:
400811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
401811af0c4SBarry Smith - flg    - `PETSC_TRUE` or `PETSC_FALSE`
4025c6c1daeSBarry Smith 
4035c6c1daeSBarry Smith   Level: developer
4045c6c1daeSBarry Smith 
405d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
406db781477SPatrick Sanan           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
407db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
4085c6c1daeSBarry Smith @*/
409d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
410d71ae5a4SJacob Faibussowitsch {
4115c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
4129f196a02SMartin Diehl   PetscBool          isascii;
4135c6c1daeSBarry Smith 
4145c6c1daeSBarry Smith   PetscFunctionBegin;
4155c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
4169f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
4179f196a02SMartin Diehl   if (isascii) {
418a297a907SKarl Rupp     if (flg) ascii->tab = ascii->tab_store;
419a297a907SKarl Rupp     else {
4205c6c1daeSBarry Smith       ascii->tab_store = ascii->tab;
4215c6c1daeSBarry Smith       ascii->tab       = 0;
4225c6c1daeSBarry Smith     }
4235c6c1daeSBarry Smith   }
4243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4255c6c1daeSBarry Smith }
4265c6c1daeSBarry Smith 
427e4096674SBarry Smith #if defined(PETSC_USE_FORTRAN_BINDINGS)
428e4096674SBarry Smith 
429e4096674SBarry Smith   #if defined(PETSC_HAVE_FORTRAN_CAPS)
430e4096674SBarry Smith     #define petscviewerasciiopenwithfileunit_  PETSCVIEWERASCIIOPENWITHFILEUNIT
43157b1f488SBarry Smith     #define petscviewerasciisetfileunit_       PETSCVIEWERASCIISETFILEUNIT
4329f0612e4SBarry Smith     #define petscviewerasciistdoutsetfileunit_ PETSCVIEWERASCIISTDOUTSETFILEUNIT
4339f0612e4SBarry Smith     #define petscfortranprinttofileunit_       PETSCFORTRANPRINTTOFILEUNIT
434e4096674SBarry Smith   #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
435e4096674SBarry Smith     #define petscviewerasciiopenwithfileunit_  petscviewerasciiopenwithfileunit
436e4096674SBarry Smith     #define petscviewerasciisetfileunit_       petscviewerasciisetfileunit
4379f0612e4SBarry Smith     #define petscviewerasciistdoutsetfileunit_ petscviewerasciistdoutsetfileunit
4389f0612e4SBarry Smith     #define petscfortranprinttofileunit_       petscfortranprinttofileunit
439e4096674SBarry Smith   #endif
440e4096674SBarry Smith 
441e4096674SBarry Smith   #if defined(__cplusplus)
4429f0612e4SBarry Smith extern "C" void petscfortranprinttofileunit_(int *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
443e4096674SBarry Smith   #else
4449f0612e4SBarry Smith extern void petscfortranprinttofileunit_(int *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
445e4096674SBarry Smith   #endif
446e4096674SBarry Smith 
447e4096674SBarry Smith   #define PETSCDEFAULTBUFFERSIZE 8 * 1024
448e4096674SBarry Smith 
4499f0612e4SBarry Smith static int PETSC_VIEWER_ASCII_STDOUT_fileunit = 0;
45057b1f488SBarry Smith 
45157b1f488SBarry Smith // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
45257b1f488SBarry Smith /*MC
4539f0612e4SBarry Smith   PetscViewerASCIIStdoutSetFileUnit - sets `PETSC_VIEWER_STDOUT_()` to write to a Fortran IO unit
45457b1f488SBarry Smith 
45557b1f488SBarry Smith   Synopsis:
45657b1f488SBarry Smith   #include <petscviewer.h>
4579f0612e4SBarry Smith   void PetscViewerASCIIStdoutSetFileUnit(PetscInt unit, PetscErrorCode ierr)
45857b1f488SBarry Smith 
45957b1f488SBarry Smith   Input Parameter:
46057b1f488SBarry Smith . unit - the unit number
46157b1f488SBarry Smith 
46257b1f488SBarry Smith   Output Parameter:
46357b1f488SBarry Smith . ierr - the error code
46457b1f488SBarry Smith 
46557b1f488SBarry Smith   Level: intermediate
46657b1f488SBarry Smith 
46757b1f488SBarry Smith   Notes:
4689f0612e4SBarry Smith   Can be called before `PetscInitialize()`
4699f0612e4SBarry Smith 
4709f0612e4SBarry Smith   Immediately changes the output for all `PETSC_VIEWER_STDOUT_()` viewers
47157b1f488SBarry Smith 
4721d031f67SBarry Smith   This may not work currently with some viewers that (improperly) use the `fd` directly instead of `PetscViewerASCIIPrintf()`
47357b1f488SBarry Smith 
47457b1f488SBarry Smith   With this option, for example, `-log_options` results will be saved to the Fortran file
47557b1f488SBarry Smith 
4761d031f67SBarry Smith   Any process may call this but only the unit passed on the first process is used
47757b1f488SBarry Smith 
47857b1f488SBarry Smith   Fortran Note:
47957b1f488SBarry Smith   Only for Fortran
48057b1f488SBarry Smith 
48157b1f488SBarry Smith   Developer Note:
4829f0612e4SBarry Smith   `PetscViewerASCIIWORLDSetFilename()` and `PetscViewerASCIIWORLDSetFILE()` could be added
48357b1f488SBarry Smith 
4849f0612e4SBarry Smith .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIStdoutSetFileUnit()`,
4859f0612e4SBarry Smith           `PETSC_VIEWER_STDOUT_()`, `PetscViewerASCIIGetStdout()`
48657b1f488SBarry Smith M*/
4879f0612e4SBarry Smith PETSC_EXTERN void petscviewerasciistdoutsetfileunit_(int *unit, PetscErrorCode *ierr)
48857b1f488SBarry Smith {
4899f0612e4SBarry Smith   #if defined(PETSC_USE_FORTRAN_BINDINGS)
4909f0612e4SBarry Smith   PETSC_VIEWER_ASCII_STDOUT_fileunit = *unit;
4919f0612e4SBarry Smith   #endif
49257b1f488SBarry Smith }
49357b1f488SBarry Smith 
4946dd63270SBarry Smith   #include <petsc/private/ftnimpl.h>
49557b1f488SBarry Smith 
49610450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
497489d2c6aSPierre Jolivet /*MC
4989f0612e4SBarry Smith   PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` `PetscViewer` to write to a Fortran IO unit
499e4096674SBarry Smith 
50010450e9eSJacob Faibussowitsch   Synopsis:
50110450e9eSJacob Faibussowitsch   #include <petscviewer.h>
502e4096674SBarry Smith   void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr)
503e4096674SBarry Smith 
504e4096674SBarry Smith   Input Parameters:
505e4096674SBarry Smith + lab  - the viewer
506e4096674SBarry Smith - unit - the unit number
507e4096674SBarry Smith 
508e4096674SBarry Smith   Output Parameter:
509e4096674SBarry Smith . ierr - the error code
510e4096674SBarry Smith 
51110450e9eSJacob Faibussowitsch   Level: intermediate
51210450e9eSJacob Faibussowitsch 
513e4096674SBarry Smith   Note:
514e4096674SBarry Smith   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
515e4096674SBarry Smith 
516aec76313SJacob Faibussowitsch   Fortran Notes:
517e4096674SBarry Smith   Only for Fortran, use  `PetscViewerASCIISetFILE()` for C
518e4096674SBarry Smith 
5199f0612e4SBarry Smith .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIStdoutSetFileUnit()`
520489d2c6aSPierre Jolivet M*/
5219f0612e4SBarry Smith PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, int *unit, PetscErrorCode *ierr)
522e4096674SBarry Smith {
52357b1f488SBarry Smith   PetscViewer_ASCII *vascii;
52457b1f488SBarry Smith   PetscViewer        v;
525e4096674SBarry Smith 
52657b1f488SBarry Smith   PetscPatchDefaultViewers_Fortran(lab, v);
52757b1f488SBarry Smith   vascii = (PetscViewer_ASCII *)v->data;
528e4096674SBarry Smith   if (vascii->mode == FILE_MODE_READ) {
529e4096674SBarry Smith     *ierr = PETSC_ERR_ARG_WRONGSTATE;
530e4096674SBarry Smith     return;
531e4096674SBarry Smith   }
532e4096674SBarry Smith   vascii->fileunit = *unit;
533e4096674SBarry Smith }
534e4096674SBarry Smith 
53510450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
536489d2c6aSPierre Jolivet /*MC
537baca6076SPierre Jolivet   PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit
538e4096674SBarry Smith 
53910450e9eSJacob Faibussowitsch   Synopsis:
54010450e9eSJacob Faibussowitsch   #include <petscviewer.h>
5419f0612e4SBarry Smith   void PetscViewerASCIIOpenWithFileUnit((MPI_Fint comm, integer unit, PetscViewer viewer, PetscErrorCode ierr)
542e4096674SBarry Smith 
543e4096674SBarry Smith   Input Parameters:
544e4096674SBarry Smith + comm - the `MPI_Comm` to share the viewer
545e4096674SBarry Smith - unit - the unit number
546e4096674SBarry Smith 
547e4096674SBarry Smith   Output Parameters:
548e4096674SBarry Smith + lab  - the viewer
549e4096674SBarry Smith - ierr - the error code
550e4096674SBarry Smith 
55110450e9eSJacob Faibussowitsch   Level: intermediate
55210450e9eSJacob Faibussowitsch 
553e4096674SBarry Smith   Note:
554e4096674SBarry Smith   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
555e4096674SBarry Smith 
556aec76313SJacob Faibussowitsch   Fortran Notes:
557e4096674SBarry Smith   Only for Fortran, use  `PetscViewerASCIIOpenWithFILE()` for C
558e4096674SBarry Smith 
559e4096674SBarry Smith .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()`
560489d2c6aSPierre Jolivet M*/
5619f0612e4SBarry Smith PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Fint *comm, int *unit, PetscViewer *lab, PetscErrorCode *ierr)
562e4096674SBarry Smith {
563e4096674SBarry Smith   *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab);
564e4096674SBarry Smith   if (*ierr) return;
565e4096674SBarry Smith   *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII);
566e4096674SBarry Smith   if (*ierr) return;
567e4096674SBarry Smith   *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE);
568e4096674SBarry Smith   if (*ierr) return;
569e4096674SBarry Smith   petscviewerasciisetfileunit_(lab, unit, ierr);
570e4096674SBarry Smith }
571e4096674SBarry Smith 
5729f0612e4SBarry Smith static PetscErrorCode PetscVFPrintfFortran(int unit, const char format[], va_list Argp)
573e4096674SBarry Smith {
574e4096674SBarry Smith   PetscErrorCode ierr;
575e4096674SBarry Smith   char           str[PETSCDEFAULTBUFFERSIZE];
576e4096674SBarry Smith   size_t         len;
577e4096674SBarry Smith 
578e4096674SBarry Smith   PetscFunctionBegin;
579e4096674SBarry Smith   PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp));
580e4096674SBarry Smith   PetscCall(PetscStrlen(str, &len));
5819f0612e4SBarry Smith   petscfortranprinttofileunit_(&unit, str, &ierr, (int)len);
582e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
583e4096674SBarry Smith }
584e4096674SBarry Smith 
5859f0612e4SBarry Smith static PetscErrorCode PetscFPrintfFortran(int unit, const char str[])
586e4096674SBarry Smith {
587e4096674SBarry Smith   PetscErrorCode ierr;
588e4096674SBarry Smith   size_t         len;
589e4096674SBarry Smith 
590e4096674SBarry Smith   PetscFunctionBegin;
591e4096674SBarry Smith   PetscCall(PetscStrlen(str, &len));
5929f0612e4SBarry Smith   petscfortranprinttofileunit_(&unit, str, &ierr, (int)len);
593e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
594e4096674SBarry Smith }
595e4096674SBarry Smith 
596e4096674SBarry Smith #else
597e4096674SBarry Smith 
598e4096674SBarry Smith /* these will never be used; but are needed to link with */
5999f0612e4SBarry Smith static PetscErrorCode PetscVFPrintfFortran(int unit, const char format[], va_list Argp)
600e4096674SBarry Smith {
601e4096674SBarry Smith   PetscFunctionBegin;
602e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
603e4096674SBarry Smith }
604e4096674SBarry Smith 
6059f0612e4SBarry Smith static PetscErrorCode PetscFPrintfFortran(int unit, const char str[])
606e4096674SBarry Smith {
607e4096674SBarry Smith   PetscFunctionBegin;
608e4096674SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
609e4096674SBarry Smith }
610e4096674SBarry Smith #endif
611e4096674SBarry Smith 
61257b1f488SBarry Smith /*@
6131d031f67SBarry Smith   PetscViewerASCIIGetStdout - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processes
614648c30bcSBarry Smith   in a communicator that prints to `stdout`. Error returning version of `PETSC_VIEWER_STDOUT_()`
61557b1f488SBarry Smith 
61657b1f488SBarry Smith   Collective
61757b1f488SBarry Smith 
61857b1f488SBarry Smith   Input Parameter:
61957b1f488SBarry Smith . comm - the MPI communicator to share the `PetscViewer`
62057b1f488SBarry Smith 
62157b1f488SBarry Smith   Output Parameter:
62257b1f488SBarry Smith . viewer - the viewer
62357b1f488SBarry Smith 
62457b1f488SBarry Smith   Level: beginner
62557b1f488SBarry Smith 
62657b1f488SBarry Smith   Note:
627648c30bcSBarry Smith   Use `PetscViewerDestroy()` to destroy it
62857b1f488SBarry Smith 
62957b1f488SBarry Smith   Developer Note:
63057b1f488SBarry Smith   This should be used in all PETSc source code instead of `PETSC_VIEWER_STDOUT_()` since it allows error checking
63157b1f488SBarry Smith 
632648c30bcSBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIGetStderr()`, `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
63357b1f488SBarry Smith           `PETSC_VIEWER_STDOUT_SELF`
63457b1f488SBarry Smith @*/
63557b1f488SBarry Smith PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm, PetscViewer *viewer)
63657b1f488SBarry Smith {
637*b8b5be36SMartin Diehl   PetscMPIInt iflg;
63857b1f488SBarry Smith   MPI_Comm    ncomm;
63957b1f488SBarry Smith 
64057b1f488SBarry Smith   PetscFunctionBegin;
641377f809aSBarry Smith   PetscAssertPointer(viewer, 2);
64257b1f488SBarry Smith   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout));
64357b1f488SBarry Smith   PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
64457b1f488SBarry 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));
645*b8b5be36SMartin Diehl   PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, &iflg));
646*b8b5be36SMartin Diehl   if (!iflg) { /* PetscViewer not yet created */
64757b1f488SBarry Smith #if defined(PETSC_USE_FORTRAN_BINDINGS)
6489f0612e4SBarry Smith     PetscCallMPI(MPI_Bcast(&PETSC_VIEWER_ASCII_STDOUT_fileunit, 1, MPI_INT, 0, comm));
6499f0612e4SBarry Smith     if (PETSC_VIEWER_ASCII_STDOUT_fileunit) {
65057b1f488SBarry Smith       PetscErrorCode ierr;
6519f0612e4SBarry Smith       MPI_Fint       fcomm = MPI_Comm_c2f(ncomm);
65257b1f488SBarry Smith 
6539f0612e4SBarry Smith       petscviewerasciiopenwithfileunit_(&fcomm, &PETSC_VIEWER_ASCII_STDOUT_fileunit, viewer, &ierr);
65457b1f488SBarry Smith     } else
65557b1f488SBarry Smith #endif
656648c30bcSBarry Smith     {
657648c30bcSBarry Smith       PetscCall(PetscViewerCreate(ncomm, viewer));
658648c30bcSBarry Smith       PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
659648c30bcSBarry Smith       PetscCall(PetscViewerFileSetName(*viewer, "stdout"));
660648c30bcSBarry Smith     }
66157b1f488SBarry Smith     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
66257b1f488SBarry Smith     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer));
66357b1f488SBarry Smith   }
66457b1f488SBarry Smith   PetscCall(PetscCommDestroy(&ncomm));
66557b1f488SBarry Smith   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout));
6669f0612e4SBarry Smith #if defined(PETSC_USE_FORTRAN_BINDINGS)
6679f0612e4SBarry Smith   ((PetscViewer_ASCII *)(*viewer)->data)->fileunit = PETSC_VIEWER_ASCII_STDOUT_fileunit;
6689f0612e4SBarry Smith #endif
66957b1f488SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
67057b1f488SBarry Smith }
67157b1f488SBarry Smith 
6725c6c1daeSBarry Smith /*@C
6735c6c1daeSBarry Smith   PetscViewerASCIIPrintf - Prints to a file, only from the first
6743f423023SBarry Smith   processor in the `PetscViewer` of type `PETSCVIEWERASCII`
6755c6c1daeSBarry Smith 
676c410d8ccSBarry Smith   Not Collective, but only the first MPI rank in the viewer has any effect
6775c6c1daeSBarry Smith 
6785c6c1daeSBarry Smith   Input Parameters:
679811af0c4SBarry Smith + viewer - obtained with `PetscViewerASCIIOpen()`
6805c6c1daeSBarry Smith - format - the usual printf() format string
6815c6c1daeSBarry Smith 
6825c6c1daeSBarry Smith   Level: developer
6835c6c1daeSBarry Smith 
684aec76313SJacob Faibussowitsch   Fortran Notes:
685c410d8ccSBarry Smith   The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran.
6865c6c1daeSBarry Smith   That is, you can only pass a single character string from Fortran.
6875c6c1daeSBarry Smith 
688d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
689db781477SPatrick Sanan           `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
690db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
6915c6c1daeSBarry Smith @*/
692d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
693d71ae5a4SJacob Faibussowitsch {
6945c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
6955c6c1daeSBarry Smith   PetscMPIInt        rank;
696fe8fb074SBarry Smith   PetscInt           tab = 0, intab = ascii->tab;
6975c6c1daeSBarry Smith   FILE              *fd = ascii->fd;
6989f196a02SMartin Diehl   PetscBool          isascii;
6995c6c1daeSBarry Smith 
7005c6c1daeSBarry Smith   PetscFunctionBegin;
7015c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
70228b400f6SJacob Faibussowitsch   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
7034f572ea9SToby Isaac   PetscAssertPointer(format, 2);
7049f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
7059f196a02SMartin Diehl   PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
7069566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
7073ba16761SJacob Faibussowitsch   if (rank) PetscFunctionReturn(PETSC_SUCCESS);
7083f08860eSBarry Smith 
7093f08860eSBarry Smith   if (ascii->bviewer) { /* pass string up to parent viewer */
7103f08860eSBarry Smith     char   *string;
7113f08860eSBarry Smith     va_list Argp;
7123f08860eSBarry Smith     size_t  fullLength;
7133f08860eSBarry Smith 
7149566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
715ac530a7eSPierre Jolivet     for (; tab < ascii->tab; tab++) string[2 * tab] = string[2 * tab + 1] = ' ';
7163f08860eSBarry Smith     va_start(Argp, format);
717fe8fb074SBarry Smith     PetscCall(PetscVSNPrintf(string + 2 * intab, QUEUESTRINGSIZE - 2 * intab, format, &fullLength, Argp));
7183f08860eSBarry Smith     va_end(Argp);
719fe8fb074SBarry Smith     PetscCall(PetscViewerASCIISynchronizedPrintf(ascii->bviewer, "%s", string));
7209566063dSJacob Faibussowitsch     PetscCall(PetscFree(string));
7213f08860eSBarry Smith   } else { /* write directly to file */
7225c6c1daeSBarry Smith     va_list Argp;
723fe8fb074SBarry Smith 
724dd2fa690SBarry Smith     tab = intab;
725e4096674SBarry Smith     while (tab--) {
726e4096674SBarry Smith       if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "  "));
727e4096674SBarry Smith       else PetscCall(PetscFPrintfFortran(ascii->fileunit, "   "));
728e4096674SBarry Smith     }
7295c6c1daeSBarry Smith 
7305c6c1daeSBarry Smith     va_start(Argp, format);
731e4096674SBarry Smith     if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
732e4096674SBarry Smith     else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
733eae3dc7dSJacob Faibussowitsch     va_end(Argp);
734c69effb2SJacob Faibussowitsch     PetscCall(PetscFFlush(fd));
7355c6c1daeSBarry Smith   }
7363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7375c6c1daeSBarry Smith }
7385c6c1daeSBarry Smith 
7395d83a8b1SBarry Smith /*@
740c410d8ccSBarry Smith   PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.
7415c6c1daeSBarry Smith 
742c3339decSBarry Smith   Collective
7435c6c1daeSBarry Smith 
7445c6c1daeSBarry Smith   Input Parameters:
7453f423023SBarry Smith + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
7465c6c1daeSBarry Smith - name   - the name of the file it should use
7475c6c1daeSBarry Smith 
7485c6c1daeSBarry Smith   Level: advanced
7495c6c1daeSBarry Smith 
750c410d8ccSBarry Smith   Note:
751c410d8ccSBarry Smith   This will have no effect on viewers that are not related to files
752c410d8ccSBarry Smith 
753d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
754db781477SPatrick Sanan           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
7555c6c1daeSBarry Smith @*/
756d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
757d71ae5a4SJacob Faibussowitsch {
758cc843e7aSLisandro Dalcin   char filename[PETSC_MAX_PATH_LEN];
7595c6c1daeSBarry Smith 
7605c6c1daeSBarry Smith   PetscFunctionBegin;
7615c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
7624f572ea9SToby Isaac   PetscAssertPointer(name, 2);
7639566063dSJacob Faibussowitsch   PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
764cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
7653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7665c6c1daeSBarry Smith }
7675c6c1daeSBarry Smith 
7685c6c1daeSBarry Smith /*@C
769c410d8ccSBarry Smith   PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using
7705c6c1daeSBarry Smith 
7715c6c1daeSBarry Smith   Not Collective
7725c6c1daeSBarry Smith 
7735c6c1daeSBarry Smith   Input Parameter:
7743f423023SBarry Smith . viewer - the `PetscViewer`
7755c6c1daeSBarry Smith 
7765c6c1daeSBarry Smith   Output Parameter:
7775c6c1daeSBarry Smith . name - the name of the file it is using
7785c6c1daeSBarry Smith 
7795c6c1daeSBarry Smith   Level: advanced
7805c6c1daeSBarry Smith 
781c410d8ccSBarry Smith   Note:
782c410d8ccSBarry Smith   This will have no effect on viewers that are not related to files
783c410d8ccSBarry Smith 
784d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
7855c6c1daeSBarry Smith @*/
7865d83a8b1SBarry Smith PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char *name[])
787d71ae5a4SJacob Faibussowitsch {
7885c6c1daeSBarry Smith   PetscFunctionBegin;
7895c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
7904f572ea9SToby Isaac   PetscAssertPointer(name, 2);
791cac4c232SBarry Smith   PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
7923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7935c6c1daeSBarry Smith }
7945c6c1daeSBarry Smith 
79534e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
796d71ae5a4SJacob Faibussowitsch {
7975c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
7985c6c1daeSBarry Smith 
7995c6c1daeSBarry Smith   PetscFunctionBegin;
8005c6c1daeSBarry Smith   *name = vascii->filename;
8013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8025c6c1daeSBarry Smith }
8035c6c1daeSBarry Smith 
804bf31d2d3SBarry Smith #include <errno.h>
80534e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
806d71ae5a4SJacob Faibussowitsch {
8075c6c1daeSBarry Smith   size_t             len;
808bbcf679cSJacob Faibussowitsch   char               fname[PETSC_MAX_PATH_LEN], *gz = NULL;
8095c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
8105c6c1daeSBarry Smith   PetscBool          isstderr, isstdout;
8115c6c1daeSBarry Smith   PetscMPIInt        rank;
8125c6c1daeSBarry Smith 
8135c6c1daeSBarry Smith   PetscFunctionBegin;
8149566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileClose_ASCII(viewer));
8153ba16761SJacob Faibussowitsch   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
8169566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &vascii->filename));
8175c6c1daeSBarry Smith 
8185c6c1daeSBarry Smith   /* Is this file to be compressed */
8195c6c1daeSBarry Smith   vascii->storecompressed = PETSC_FALSE;
820a297a907SKarl Rupp 
8219566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
8225c6c1daeSBarry Smith   if (gz) {
8239566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(gz, &len));
8245c6c1daeSBarry Smith     if (len == 3) {
82508401ef6SPierre 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");
8265c6c1daeSBarry Smith       *gz                     = 0;
8275c6c1daeSBarry Smith       vascii->storecompressed = PETSC_TRUE;
8285c6c1daeSBarry Smith     }
8295c6c1daeSBarry Smith   }
8309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
831dd400576SPatrick Sanan   if (rank == 0) {
8329566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
8339566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
8345c6c1daeSBarry Smith     /* empty filename means stdout */
8355c6c1daeSBarry Smith     if (name[0] == 0) isstdout = PETSC_TRUE;
8365c6c1daeSBarry Smith     if (isstderr) vascii->fd = PETSC_STDERR;
8375c6c1daeSBarry Smith     else if (isstdout) vascii->fd = PETSC_STDOUT;
8385c6c1daeSBarry Smith     else {
8399566063dSJacob Faibussowitsch       PetscCall(PetscFixFilename(name, fname));
8405c6c1daeSBarry Smith       switch (vascii->mode) {
841d71ae5a4SJacob Faibussowitsch       case FILE_MODE_READ:
842d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "r");
843d71ae5a4SJacob Faibussowitsch         break;
844d71ae5a4SJacob Faibussowitsch       case FILE_MODE_WRITE:
845d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "w");
846d71ae5a4SJacob Faibussowitsch         break;
847d71ae5a4SJacob Faibussowitsch       case FILE_MODE_APPEND:
848d71ae5a4SJacob Faibussowitsch         vascii->fd = fopen(fname, "a");
849d71ae5a4SJacob Faibussowitsch         break;
8505c6c1daeSBarry Smith       case FILE_MODE_UPDATE:
8515c6c1daeSBarry Smith         vascii->fd = fopen(fname, "r+");
852a297a907SKarl Rupp         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
8535c6c1daeSBarry Smith         break;
8545c6c1daeSBarry Smith       case FILE_MODE_APPEND_UPDATE:
8555c6c1daeSBarry Smith         /* I really want a file which is opened at the end for updating,
8565c6c1daeSBarry Smith            not a+, which opens at the beginning, but makes writes at the end.
8575c6c1daeSBarry Smith         */
8585c6c1daeSBarry Smith         vascii->fd = fopen(fname, "r+");
859a297a907SKarl Rupp         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
8603ba16761SJacob Faibussowitsch         else {
8613ba16761SJacob Faibussowitsch           int ret = fseek(vascii->fd, 0, SEEK_END);
8623ba16761SJacob Faibussowitsch           PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
8633ba16761SJacob Faibussowitsch         }
8645c6c1daeSBarry Smith         break;
865d71ae5a4SJacob Faibussowitsch       default:
866d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
8675c6c1daeSBarry Smith       }
868bf31d2d3SBarry Smith       PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
8695c6c1daeSBarry Smith     }
8705c6c1daeSBarry Smith   }
8713ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
8723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8735c6c1daeSBarry Smith }
8745c6c1daeSBarry Smith 
87534e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
876d71ae5a4SJacob Faibussowitsch {
8775c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
8785c6c1daeSBarry Smith 
8795c6c1daeSBarry Smith   PetscFunctionBegin;
88028b400f6SJacob Faibussowitsch   PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
881fe8fb074SBarry Smith   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
882e5afcf28SBarry Smith   /*
8839530cbd7SBarry Smith      The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
8849530cbd7SBarry 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
8859530cbd7SBarry Smith      (since the count never gets to zero) in some examples this displays information that otherwise would be lost
8869530cbd7SBarry Smith 
8879530cbd7SBarry Smith      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
8889530cbd7SBarry Smith      PCView_GASM().
889e5afcf28SBarry Smith   */
8909566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
891b4025f61SBarry Smith   PetscCall(PetscViewerFlush(viewer));
8929566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(subcomm, outviewer));
8939566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
8949566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
8955c6c1daeSBarry Smith   ovascii            = (PetscViewer_ASCII *)(*outviewer)->data;
8965c6c1daeSBarry Smith   ovascii->fd        = vascii->fd;
8979f0612e4SBarry Smith   ovascii->fileunit  = vascii->fileunit;
898ba5a0b41SBarry Smith   ovascii->closefile = PETSC_FALSE;
8995c6c1daeSBarry Smith 
9005c6c1daeSBarry Smith   vascii->sviewer                                      = *outviewer;
9015c6c1daeSBarry Smith   (*outviewer)->format                                 = viewer->format;
9025c6c1daeSBarry Smith   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
9033f08860eSBarry Smith   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
9043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9055c6c1daeSBarry Smith }
9065c6c1daeSBarry Smith 
90734e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
908d71ae5a4SJacob Faibussowitsch {
9095c6c1daeSBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
9105c6c1daeSBarry Smith 
9115c6c1daeSBarry Smith   PetscFunctionBegin;
91228b400f6SJacob Faibussowitsch   PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
91308401ef6SPierre Jolivet   PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");
9145c6c1daeSBarry Smith 
9159566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
916e5afcf28SBarry Smith   ascii->sviewer             = NULL;
9175c6c1daeSBarry Smith   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
9189566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(outviewer));
919fe8fb074SBarry Smith   PetscCall(PetscViewerFlush(viewer));
9209566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
9213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9225c6c1daeSBarry Smith }
9235c6c1daeSBarry Smith 
92434e79e72SJacob Faibussowitsch static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
925d71ae5a4SJacob Faibussowitsch {
9262bf49c77SBarry Smith   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
9272bf49c77SBarry Smith 
9282bf49c77SBarry Smith   PetscFunctionBegin;
9299f0612e4SBarry Smith   if (ascii->fileunit) PetscCall(PetscViewerASCIIPrintf(viewer, "Fortran FILE UNIT: %d\n", ascii->fileunit));
93057b1f488SBarry Smith   else if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
9313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9322bf49c77SBarry Smith }
9332bf49c77SBarry Smith 
9349f0612e4SBarry Smith static PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
9359f0612e4SBarry Smith {
9369f0612e4SBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
9379f0612e4SBarry Smith   MPI_Comm           comm;
9389f0612e4SBarry Smith   PetscMPIInt        rank, size;
9399f0612e4SBarry Smith   FILE              *fd = vascii->fd;
9409f0612e4SBarry Smith 
9419f0612e4SBarry Smith   PetscFunctionBegin;
9429f0612e4SBarry Smith   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
9439f0612e4SBarry Smith   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
9449f0612e4SBarry Smith   PetscCallMPI(MPI_Comm_rank(comm, &rank));
9459f0612e4SBarry Smith   PetscCallMPI(MPI_Comm_size(comm, &size));
9469f0612e4SBarry Smith 
9479f0612e4SBarry Smith   if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd));
9489f0612e4SBarry Smith 
9499f0612e4SBarry Smith   if (vascii->allowsynchronized) {
9509f0612e4SBarry Smith     PetscMPIInt tag, i, j, n = 0, dummy = 0;
9519f0612e4SBarry Smith     char       *message;
9529f0612e4SBarry Smith     MPI_Status  status;
9539f0612e4SBarry Smith 
9549f0612e4SBarry Smith     PetscCall(PetscCommDuplicate(comm, &comm, &tag));
9559f0612e4SBarry Smith 
9569f0612e4SBarry Smith     /* First processor waits for messages from all other processors */
9579f0612e4SBarry Smith     if (rank == 0) {
9589f0612e4SBarry Smith       /* flush my own messages that I may have queued up */
9599f0612e4SBarry Smith       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
9609f0612e4SBarry Smith       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
9619f0612e4SBarry Smith         if (!vascii->bviewer) {
9629f0612e4SBarry Smith           if (!vascii->fileunit) PetscCall(PetscFPrintf(comm, fd, "%s", next->string));
9639f0612e4SBarry Smith           else PetscCall(PetscFPrintfFortran(vascii->fileunit, next->string));
9649f0612e4SBarry Smith         } else {
9659f0612e4SBarry Smith           PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string));
9669f0612e4SBarry Smith         }
9679f0612e4SBarry Smith         previous = next;
9689f0612e4SBarry Smith         next     = next->next;
9699f0612e4SBarry Smith         PetscCall(PetscFree(previous->string));
9709f0612e4SBarry Smith         PetscCall(PetscFree(previous));
9719f0612e4SBarry Smith       }
9729f0612e4SBarry Smith       vascii->petsc_printfqueue       = NULL;
9739f0612e4SBarry Smith       vascii->petsc_printfqueuelength = 0;
9749f0612e4SBarry Smith       for (i = 1; i < size; i++) {
9759f0612e4SBarry Smith         /* to prevent a flood of messages to process zero, request each message separately */
9769f0612e4SBarry Smith         PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
9779f0612e4SBarry Smith         PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
9789f0612e4SBarry Smith         for (j = 0; j < n; j++) {
9796497c311SBarry Smith           size_t size;
9809f0612e4SBarry Smith 
9816497c311SBarry Smith           PetscCallMPI(MPI_Recv(&size, 1, MPIU_SIZE_T, i, tag, comm, &status));
9829f0612e4SBarry Smith           PetscCall(PetscMalloc1(size, &message));
9836497c311SBarry Smith           PetscCallMPI(MPI_Recv(message, (PetscMPIInt)size, MPI_CHAR, i, tag, comm, &status));
9849f0612e4SBarry Smith           if (!vascii->bviewer) {
9859f0612e4SBarry Smith             if (!vascii->fileunit) PetscCall(PetscFPrintf(comm, fd, "%s", message));
9869f0612e4SBarry Smith             else PetscCall(PetscFPrintfFortran(vascii->fileunit, message));
9879f0612e4SBarry Smith           } else {
9889f0612e4SBarry Smith             PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message));
9899f0612e4SBarry Smith           }
9909f0612e4SBarry Smith           PetscCall(PetscFree(message));
9919f0612e4SBarry Smith         }
9929f0612e4SBarry Smith       }
9939f0612e4SBarry Smith     } else { /* other processors send queue to processor 0 */
9949f0612e4SBarry Smith       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
9959f0612e4SBarry Smith 
9969f0612e4SBarry Smith       PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
9979f0612e4SBarry Smith       PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
9989f0612e4SBarry Smith       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
9996497c311SBarry Smith         PetscCallMPI(MPI_Send(&next->size, 1, MPIU_SIZE_T, 0, tag, comm));
10006497c311SBarry Smith         PetscCallMPI(MPI_Send(next->string, (PetscMPIInt)next->size, MPI_CHAR, 0, tag, comm));
10019f0612e4SBarry Smith         previous = next;
10029f0612e4SBarry Smith         next     = next->next;
10039f0612e4SBarry Smith         PetscCall(PetscFree(previous->string));
10049f0612e4SBarry Smith         PetscCall(PetscFree(previous));
10059f0612e4SBarry Smith       }
10069f0612e4SBarry Smith       vascii->petsc_printfqueue       = NULL;
10079f0612e4SBarry Smith       vascii->petsc_printfqueuelength = 0;
10089f0612e4SBarry Smith     }
10099f0612e4SBarry Smith     PetscCall(PetscCommDestroy(&comm));
10109f0612e4SBarry Smith   }
10119f0612e4SBarry Smith   PetscFunctionReturn(PETSC_SUCCESS);
10129f0612e4SBarry Smith }
10139f0612e4SBarry Smith 
10148556b5ebSBarry Smith /*MC
1015648c30bcSBarry Smith    PETSCVIEWERASCII - A viewer that prints to `stdout`, `stderr`, or an ASCII file
10168556b5ebSBarry Smith 
1017811af0c4SBarry Smith   Level: beginner
1018811af0c4SBarry Smith 
1019d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1020db781477SPatrick Sanan           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
1021db781477SPatrick Sanan           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
10228556b5ebSBarry Smith M*/
1023d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
1024d71ae5a4SJacob Faibussowitsch {
10255c6c1daeSBarry Smith   PetscViewer_ASCII *vascii;
10265c6c1daeSBarry Smith 
10275c6c1daeSBarry Smith   PetscFunctionBegin;
10284dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&vascii));
10295c6c1daeSBarry Smith   viewer->data = (void *)vascii;
10305c6c1daeSBarry Smith 
10315c6c1daeSBarry Smith   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
10325c6c1daeSBarry Smith   viewer->ops->flush            = PetscViewerFlush_ASCII;
1033559f443fSBarry Smith   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
1034559f443fSBarry Smith   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
10352bf49c77SBarry Smith   viewer->ops->view             = PetscViewerView_ASCII;
10361d641e7bSMichael Lange   viewer->ops->read             = PetscViewerASCIIRead;
10375c6c1daeSBarry Smith 
10385c6c1daeSBarry Smith   /* defaults to stdout unless set with PetscViewerFileSetName() */
10395c6c1daeSBarry Smith   vascii->fd        = PETSC_STDOUT;
10405c6c1daeSBarry Smith   vascii->mode      = FILE_MODE_WRITE;
104102c9f0b5SLisandro Dalcin   vascii->bviewer   = NULL;
104202c9f0b5SLisandro Dalcin   vascii->subviewer = NULL;
104302c9f0b5SLisandro Dalcin   vascii->sviewer   = NULL;
10445c6c1daeSBarry Smith   vascii->tab       = 0;
10455c6c1daeSBarry Smith   vascii->tab_store = 0;
104602c9f0b5SLisandro Dalcin   vascii->filename  = NULL;
10475c6c1daeSBarry Smith   vascii->closefile = PETSC_TRUE;
10485c6c1daeSBarry Smith 
10499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
10509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
10519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
10529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
10533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10545c6c1daeSBarry Smith }
10555c6c1daeSBarry Smith 
10565c6c1daeSBarry Smith /*@C
1057c410d8ccSBarry Smith   PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
10585c6c1daeSBarry Smith   several processors.  Output of the first processor is followed by that of the
10595c6c1daeSBarry Smith   second, etc.
10605c6c1daeSBarry Smith 
1061c410d8ccSBarry Smith   Not Collective, must call collective `PetscViewerFlush()` to get the results flushed
10625c6c1daeSBarry Smith 
10635c6c1daeSBarry Smith   Input Parameters:
1064811af0c4SBarry Smith + viewer - the `PETSCVIEWERASCII` `PetscViewer`
10655c6c1daeSBarry Smith - format - the usual printf() format string
10665c6c1daeSBarry Smith 
10675c6c1daeSBarry Smith   Level: intermediate
10685c6c1daeSBarry Smith 
106995452b02SPatrick Sanan   Notes:
1070811af0c4SBarry Smith   You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
1071e6abc3ddSVáclav Hapla   Then you can do multiple independent calls to this routine.
1072811af0c4SBarry Smith 
1073811af0c4SBarry Smith   The actual synchronized print is then done using `PetscViewerFlush()`.
1074811af0c4SBarry Smith   `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
1075e6abc3ddSVáclav Hapla   to conclude the "synchronized session".
1076811af0c4SBarry Smith 
1077e6abc3ddSVáclav Hapla   So the typical calling sequence looks like
1078811af0c4SBarry Smith .vb
1079811af0c4SBarry Smith     PetscViewerASCIIPushSynchronized(viewer);
1080811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1081811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1082811af0c4SBarry Smith     ...
1083811af0c4SBarry Smith     PetscViewerFlush(viewer);
1084811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1085811af0c4SBarry Smith     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1086811af0c4SBarry Smith     ...
1087811af0c4SBarry Smith     PetscViewerFlush(viewer);
1088811af0c4SBarry Smith     PetscViewerASCIIPopSynchronized(viewer);
1089811af0c4SBarry Smith .ve
10905c6c1daeSBarry Smith 
1091aec76313SJacob Faibussowitsch   Fortran Notes:
10925c6c1daeSBarry Smith   Can only print a single character* string
10935c6c1daeSBarry Smith 
1094d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
1095db781477SPatrick Sanan           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
1096db781477SPatrick Sanan           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
10975c6c1daeSBarry Smith @*/
1098d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
1099d71ae5a4SJacob Faibussowitsch {
11005c6c1daeSBarry Smith   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
11013f08860eSBarry Smith   PetscMPIInt        rank;
1102fe8fb074SBarry Smith   PetscInt           tab = 0;
11035c6c1daeSBarry Smith   MPI_Comm           comm;
11049f196a02SMartin Diehl   PetscBool          isascii;
11055c6c1daeSBarry Smith 
11065c6c1daeSBarry Smith   PetscFunctionBegin;
11075c6c1daeSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
11084f572ea9SToby Isaac   PetscAssertPointer(format, 2);
11099f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
11109f196a02SMartin Diehl   PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
111128b400f6SJacob Faibussowitsch   PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");
11125c6c1daeSBarry Smith 
11139566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
11149566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11155c6c1daeSBarry Smith 
1116559f443fSBarry Smith   if (vascii->bviewer) {
1117fe8fb074SBarry Smith     char   *string;
11185c6c1daeSBarry Smith     va_list Argp;
1119fe8fb074SBarry Smith     size_t  fullLength;
11205c6c1daeSBarry Smith 
1121fe8fb074SBarry Smith     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
1122ac530a7eSPierre Jolivet     for (; tab < vascii->tab; tab++) string[2 * tab] = string[2 * tab + 1] = ' ';
1123fe8fb074SBarry Smith     va_start(Argp, format);
1124fe8fb074SBarry Smith     PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp));
1125fe8fb074SBarry Smith     va_end(Argp);
1126fe8fb074SBarry Smith     PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string));
1127fe8fb074SBarry Smith     PetscCall(PetscFree(string));
1128fe8fb074SBarry Smith   } else if (rank == 0) { /* First processor prints immediately to fp */
1129fe8fb074SBarry Smith     va_list Argp;
1130fe8fb074SBarry Smith     FILE   *fp = vascii->fd;
1131fe8fb074SBarry Smith 
1132fe8fb074SBarry Smith     tab = vascii->tab;
11339f0612e4SBarry Smith     while (tab--) {
11349f0612e4SBarry Smith       if (!vascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, "  "));
11359f0612e4SBarry Smith       else PetscCall(PetscFPrintfFortran(vascii->fileunit, "   "));
11369f0612e4SBarry Smith     }
11375c6c1daeSBarry Smith 
11385c6c1daeSBarry Smith     va_start(Argp, format);
11399f0612e4SBarry Smith     if (!vascii->fileunit) PetscCall((*PetscVFPrintf)(fp, format, Argp));
11409f0612e4SBarry Smith     else PetscCall(PetscVFPrintfFortran(vascii->fileunit, format, Argp));
1141eae3dc7dSJacob Faibussowitsch     va_end(Argp);
1142c69effb2SJacob Faibussowitsch     PetscCall(PetscFFlush(fp));
11435c6c1daeSBarry Smith     if (petsc_history) {
11445c6c1daeSBarry Smith       va_start(Argp, format);
11459566063dSJacob Faibussowitsch       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1146eae3dc7dSJacob Faibussowitsch       va_end(Argp);
1147c69effb2SJacob Faibussowitsch       PetscCall(PetscFFlush(petsc_history));
11485c6c1daeSBarry Smith     }
1149559f443fSBarry Smith   } else { /* other processors add to queue */
11505c6c1daeSBarry Smith     char       *string;
11515c6c1daeSBarry Smith     va_list     Argp;
11525c6c1daeSBarry Smith     size_t      fullLength;
11535c6c1daeSBarry Smith     PrintfQueue next;
11545c6c1daeSBarry Smith 
11559566063dSJacob Faibussowitsch     PetscCall(PetscNew(&next));
1156559f443fSBarry Smith     if (vascii->petsc_printfqueue) {
1157559f443fSBarry Smith       vascii->petsc_printfqueue->next = next;
1158559f443fSBarry Smith       vascii->petsc_printfqueue       = next;
1159a297a907SKarl Rupp     } else {
1160559f443fSBarry Smith       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1161a297a907SKarl Rupp     }
1162559f443fSBarry Smith     vascii->petsc_printfqueuelength++;
11635c6c1daeSBarry Smith     next->size = QUEUESTRINGSIZE;
11649566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(next->size, &next->string));
11655c6c1daeSBarry Smith     string = next->string;
1166f15bb73eSStefano Zampini 
1167f15bb73eSStefano Zampini     tab = vascii->tab;
11685c6c1daeSBarry Smith     tab *= 2;
1169ad540459SPierre Jolivet     while (tab--) *string++ = ' ';
11705c6c1daeSBarry Smith     va_start(Argp, format);
11719566063dSJacob Faibussowitsch     PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
11725c6c1daeSBarry Smith     va_end(Argp);
1173835f2295SStefano Zampini     if (fullLength > next->size - 2 * vascii->tab) {
11749566063dSJacob Faibussowitsch       PetscCall(PetscFree(next->string));
117514416c0eSBarry Smith       next->size = fullLength + 2 * vascii->tab;
11769566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(next->size, &next->string));
117714416c0eSBarry Smith       string = next->string;
117814416c0eSBarry Smith       tab    = 2 * vascii->tab;
1179ad540459SPierre Jolivet       while (tab--) *string++ = ' ';
118014416c0eSBarry Smith       va_start(Argp, format);
11819566063dSJacob Faibussowitsch       PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
118214416c0eSBarry Smith       va_end(Argp);
118314416c0eSBarry Smith     }
11845c6c1daeSBarry Smith   }
11853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11865c6c1daeSBarry Smith }
11875c6c1daeSBarry Smith 
11882655f987SMichael Lange /*@C
1189c410d8ccSBarry Smith   PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file
11902655f987SMichael Lange 
1191c410d8ccSBarry Smith   Only MPI rank 0 in the `PetscViewer` may call this
11922655f987SMichael Lange 
11932655f987SMichael Lange   Input Parameters:
11943f423023SBarry Smith + viewer - the `PETSCVIEWERASCII` viewer
1195c410d8ccSBarry Smith . data   - location to write the data, treated as an array of type indicated by `datatype`
1196060da220SMatthew G. Knepley . num    - number of items of data to read
1197aec76313SJacob Faibussowitsch - dtype  - type of data to read
11982655f987SMichael Lange 
119920f4b53cSBarry Smith   Output Parameter:
12003f423023SBarry Smith . count - number of items of data actually read, or `NULL`
1201f8e4bde8SMatthew G. Knepley 
12022655f987SMichael Lange   Level: beginner
12032655f987SMichael Lange 
1204d1f92df0SBarry Smith .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1205db781477SPatrick Sanan           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1206db781477SPatrick Sanan           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
12072655f987SMichael Lange @*/
1208d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1209d71ae5a4SJacob Faibussowitsch {
12102655f987SMichael Lange   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
12112655f987SMichael Lange   FILE              *fd     = vascii->fd;
12122655f987SMichael Lange   PetscInt           i;
12133b7fe8c3SMatthew G. Knepley   int                ret = 0;
1214f8859db6SBarry Smith   PetscMPIInt        rank;
12152655f987SMichael Lange 
12162655f987SMichael Lange   PetscFunctionBegin;
12172655f987SMichael Lange   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
12189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1219c5853193SPierre Jolivet   PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1220060da220SMatthew G. Knepley   for (i = 0; i < num; i++) {
1221f8e4bde8SMatthew G. Knepley     if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1222f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1223a05e1a72SSatish Balay     else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1224f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
12259e3e4c22SLisandro Dalcin     else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1226972064b6SLisandro Dalcin     else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
12276497c311SBarry Smith     else if (dtype == PETSC_COUNT) ret = fscanf(fd, "%" PetscCount_FMT, &(((PetscCount *)data)[i]));
1228f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1229f8e4bde8SMatthew G. Knepley     else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1230a6e181c6SToby Isaac #if defined(PETSC_USE_REAL___FLOAT128)
1231fba955ccSBarry Smith     else if (dtype == PETSC___FLOAT128) {
1232fba955ccSBarry Smith       double tmp;
1233fba955ccSBarry Smith       ret                     = fscanf(fd, "%lg", &tmp);
1234a6e181c6SToby Isaac       ((__float128 *)data)[i] = tmp;
1235a6e181c6SToby Isaac     }
1236fba955ccSBarry Smith #endif
12379371c9d4SSatish Balay     else
12389371c9d4SSatish Balay       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
123928b400f6SJacob Faibussowitsch     PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1240f7d195e4SLawrence Mitchell     if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
12412655f987SMichael Lange   }
1242060da220SMatthew G. Knepley   if (count) *count = i;
124308401ef6SPierre Jolivet   else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
12443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12452655f987SMichael Lange }
1246