xref: /petsc/src/sys/classes/viewer/impls/ascii/filev.c (revision ebead697dbf761eb322f829370bbe90b3bd93fa3)
1 
2 #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h>  /*I "petscviewer.h" I*/
3 
4 #define QUEUESTRINGSIZE 8192
5 
6 static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer)
7 {
8   PetscMPIInt       rank;
9   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
10   int               err;
11 
12   PetscFunctionBegin;
13   PetscCheck(!vascii->sviewer,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_WRONGSTATE,"Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
14   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank));
15   if (rank == 0 && vascii->fd != stderr && vascii->fd != PETSC_STDOUT) {
16     if (vascii->fd && vascii->closefile) {
17       err = fclose(vascii->fd);
18       PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
19     }
20     if (vascii->storecompressed) {
21       char par[PETSC_MAX_PATH_LEN],buf[PETSC_MAX_PATH_LEN];
22       FILE *fp;
23       PetscCall(PetscStrncpy(par,"gzip ",sizeof(par)));
24       PetscCall(PetscStrlcat(par,vascii->filename,sizeof(par)));
25 #if defined(PETSC_HAVE_POPEN)
26       PetscCall(PetscPOpen(PETSC_COMM_SELF,NULL,par,"r",&fp));
27       PetscCheck(!fgets(buf,1024,fp),PETSC_COMM_SELF,PETSC_ERR_LIB,"Error from compression command %s\n%s",par,buf);
28       PetscCall(PetscPClose(PETSC_COMM_SELF,fp));
29 #else
30       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
31 #endif
32     }
33   }
34   PetscCall(PetscFree(vascii->filename));
35   PetscFunctionReturn(0);
36 }
37 
38 /* ----------------------------------------------------------------------*/
39 PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
40 {
41   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
42   PetscViewerLink   *vlink;
43   PetscBool         flg;
44 
45   PetscFunctionBegin;
46   PetscCheck(!vascii->sviewer,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_WRONGSTATE,"Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
47   PetscCall(PetscViewerFileClose_ASCII(viewer));
48   PetscCall(PetscFree(vascii));
49 
50   /* remove the viewer from the list in the MPI Communicator */
51   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) {
52     PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,Petsc_DelViewer,&Petsc_Viewer_keyval,(void*)0));
53   }
54 
55   PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_keyval,(void**)&vlink,(PetscMPIInt*)&flg));
56   if (flg) {
57     if (vlink && vlink->viewer == viewer) {
58       if (vlink->next) {
59         PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_keyval,vlink->next));
60       } else {
61         PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_keyval));
62       }
63       PetscCall(PetscFree(vlink));
64     } else {
65       while (vlink && vlink->next) {
66         if (vlink->next->viewer == viewer) {
67           PetscViewerLink *nv = vlink->next;
68           vlink->next = vlink->next->next;
69           PetscCall(PetscFree(nv));
70         }
71         vlink = vlink->next;
72       }
73     }
74   }
75 
76   if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
77     PetscViewer aviewer;
78     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stdout_keyval,(void**)&aviewer,(PetscMPIInt*)&flg));
79     if (flg && aviewer == viewer) {
80       PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stdout_keyval));
81     }
82   }
83   if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
84     PetscViewer aviewer;
85     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stderr_keyval,(void**)&aviewer,(PetscMPIInt*)&flg));
86     if (flg && aviewer == viewer) {
87       PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stderr_keyval));
88     }
89   }
90   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL));
91   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL));
92   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetMode_C",NULL));
93   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL));
94   PetscFunctionReturn(0);
95 }
96 
97 PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
98 {
99   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
100 
101   PetscFunctionBegin;
102   PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer,0,&viewer));
103   PetscFunctionReturn(0);
104 }
105 
106 PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
107 {
108   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
109   int               err;
110   MPI_Comm          comm;
111   PetscMPIInt       rank,size;
112   FILE              *fd = vascii->fd;
113 
114   PetscFunctionBegin;
115   PetscCheck(!vascii->sviewer,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_WRONGSTATE,"Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
116   PetscCall(PetscObjectGetComm((PetscObject)viewer,&comm));
117   PetscCallMPI(MPI_Comm_rank(comm,&rank));
118   PetscCallMPI(MPI_Comm_size(comm,&size));
119 
120   if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) {
121     err = fflush(vascii->fd);
122     PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() call failed");
123   }
124 
125   if (vascii->allowsynchronized) {
126     PetscMPIInt   tag,i,j,n = 0,dummy = 0;
127     char          *message;
128     MPI_Status    status;
129 
130     PetscCall(PetscCommDuplicate(comm,&comm,&tag));
131 
132     /* First processor waits for messages from all other processors */
133     if (rank == 0) {
134       /* flush my own messages that I may have queued up */
135       PrintfQueue next = vascii->petsc_printfqueuebase,previous;
136       for (i=0; i<vascii->petsc_printfqueuelength; i++) {
137         if (!vascii->bviewer) {
138           PetscCall(PetscFPrintf(comm,fd,"%s",next->string));
139         } else {
140           PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer,"%s",next->string));
141         }
142         previous = next;
143         next     = next->next;
144         PetscCall(PetscFree(previous->string));
145         PetscCall(PetscFree(previous));
146       }
147       vascii->petsc_printfqueue       = NULL;
148       vascii->petsc_printfqueuelength = 0;
149       for (i=1; i<size; i++) {
150         /* to prevent a flood of messages to process zero, request each message separately */
151         PetscCallMPI(MPI_Send(&dummy,1,MPI_INT,i,tag,comm));
152         PetscCallMPI(MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status));
153         for (j=0; j<n; j++) {
154           PetscMPIInt size = 0;
155 
156           PetscCallMPI(MPI_Recv(&size,1,MPI_INT,i,tag,comm,&status));
157           PetscCall(PetscMalloc1(size, &message));
158           PetscCallMPI(MPI_Recv(message,size,MPI_CHAR,i,tag,comm,&status));
159           if (!vascii->bviewer) {
160             PetscCall(PetscFPrintf(comm,fd,"%s",message));
161           } else {
162             PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer,"%s",message));
163           }
164           PetscCall(PetscFree(message));
165         }
166       }
167     } else { /* other processors send queue to processor 0 */
168       PrintfQueue next = vascii->petsc_printfqueuebase,previous;
169 
170       PetscCallMPI(MPI_Recv(&dummy,1,MPI_INT,0,tag,comm,&status));
171       PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength,1,MPI_INT,0,tag,comm));
172       for (i=0; i<vascii->petsc_printfqueuelength; i++) {
173         PetscCallMPI(MPI_Send(&next->size,1,MPI_INT,0,tag,comm));
174         PetscCallMPI(MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm));
175         previous = next;
176         next     = next->next;
177         PetscCall(PetscFree(previous->string));
178         PetscCall(PetscFree(previous));
179       }
180       vascii->petsc_printfqueue       = NULL;
181       vascii->petsc_printfqueuelength = 0;
182     }
183     PetscCall(PetscCommDestroy(&comm));
184   }
185   PetscFunctionReturn(0);
186 }
187 
188 /*@C
189     PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII PetscViewer.
190 
191     Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer
192 
193     Input Parameter:
194 .    viewer - PetscViewer context, obtained from PetscViewerASCIIOpen()
195 
196     Output Parameter:
197 .    fd - file pointer
198 
199     Notes: for the standard PETSCVIEWERASCII the value is valid only on process 0 of the viewer
200 
201     Level: intermediate
202 
203     Fortran Note:
204     This routine is not supported in Fortran.
205 
206 .seealso: `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`,
207           `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
208 @*/
209 PetscErrorCode  PetscViewerASCIIGetPointer(PetscViewer viewer,FILE **fd)
210 {
211   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
212 
213   PetscFunctionBegin;
214   *fd = vascii->fd;
215   PetscFunctionReturn(0);
216 }
217 
218 PetscErrorCode  PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
219 {
220   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
221 
222   PetscFunctionBegin;
223   *mode = vascii->mode;
224   PetscFunctionReturn(0);
225 }
226 
227 PetscErrorCode  PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
228 {
229   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
230 
231   PetscFunctionBegin;
232   vascii->mode = mode;
233   PetscFunctionReturn(0);
234 }
235 
236 /*
237    If petsc_history is on, then all Petsc*Printf() results are saved
238    if the appropriate (usually .petschistory) file.
239 */
240 PETSC_INTERN FILE *petsc_history;
241 
242 /*@
243     PetscViewerASCIISetTab - Causes PetscViewer to tab in a number of times
244 
245     Not Collective, but only first processor in set has any effect
246 
247     Input Parameters:
248 +    viewer - obtained with PetscViewerASCIIOpen()
249 -    tabs - number of tabs
250 
251     Level: developer
252 
253     Fortran Note:
254     This routine is not supported in Fortran.
255 
256 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIGetTab()`,
257           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
258           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
259 @*/
260 PetscErrorCode  PetscViewerASCIISetTab(PetscViewer viewer,PetscInt tabs)
261 {
262   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
263   PetscBool         iascii;
264 
265   PetscFunctionBegin;
266   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
267   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
268   if (iascii) ascii->tab = tabs;
269   PetscFunctionReturn(0);
270 }
271 
272 /*@
273     PetscViewerASCIIGetTab - Return the number of tabs used by PetscViewer.
274 
275     Not Collective, meaningful on first processor only.
276 
277     Input Parameters:
278 .    viewer - obtained with PetscViewerASCIIOpen()
279 
280     Output Parameters:
281 .    tabs - number of tabs
282 
283     Level: developer
284 
285     Fortran Note:
286     This routine is not supported in Fortran.
287 
288 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISetTab()`,
289           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
290           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
291 @*/
292 PetscErrorCode  PetscViewerASCIIGetTab(PetscViewer viewer,PetscInt *tabs)
293 {
294   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
295   PetscBool         iascii;
296 
297   PetscFunctionBegin;
298   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
299   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
300   if (iascii && tabs) *tabs = ascii->tab;
301   PetscFunctionReturn(0);
302 }
303 
304 /*@
305     PetscViewerASCIIAddTab - Add to the number of times an ASCII viewer tabs before printing
306 
307     Not Collective, but only first processor in set has any effect
308 
309     Input Parameters:
310 +    viewer - obtained with PetscViewerASCIIOpen()
311 -    tabs - number of tabs
312 
313     Level: developer
314 
315     Fortran Note:
316     This routine is not supported in Fortran.
317 
318 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
319           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
320           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
321 @*/
322 PetscErrorCode  PetscViewerASCIIAddTab(PetscViewer viewer,PetscInt tabs)
323 {
324   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
325   PetscBool         iascii;
326 
327   PetscFunctionBegin;
328   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
329   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
330   if (iascii) ascii->tab += tabs;
331   PetscFunctionReturn(0);
332 }
333 
334 /*@
335     PetscViewerASCIISubtractTab - Subtracts from the number of times an ASCII viewer tabs before printing
336 
337     Not Collective, but only first processor in set has any effect
338 
339     Input Parameters:
340 +    viewer - obtained with PetscViewerASCIIOpen()
341 -    tabs - number of tabs
342 
343     Level: developer
344 
345     Fortran Note:
346     This routine is not supported in Fortran.
347 
348 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
349           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
350           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
351 @*/
352 PetscErrorCode  PetscViewerASCIISubtractTab(PetscViewer viewer,PetscInt tabs)
353 {
354   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
355   PetscBool         iascii;
356 
357   PetscFunctionBegin;
358   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
359   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
360   if (iascii) ascii->tab -= tabs;
361   PetscFunctionReturn(0);
362 }
363 
364 /*@C
365     PetscViewerASCIIPushSynchronized - Allows calls to PetscViewerASCIISynchronizedPrintf() for this viewer
366 
367     Collective on PetscViewer
368 
369     Input Parameters:
370 .    viewer - obtained with PetscViewerASCIIOpen()
371 
372     Level: intermediate
373 
374     Notes:
375     See documentation of PetscViewerASCIISynchronizedPrintf() for more details how the synchronized output should be done properly.
376 
377 .seealso: `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
378           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
379           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
380 @*/
381 PetscErrorCode  PetscViewerASCIIPushSynchronized(PetscViewer viewer)
382 {
383   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
384   PetscBool         iascii;
385 
386   PetscFunctionBegin;
387   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
388   PetscCheck(!ascii->sviewer,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_WRONGSTATE,"Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
389   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
390   if (iascii) ascii->allowsynchronized++;
391   PetscFunctionReturn(0);
392 }
393 
394 /*@C
395     PetscViewerASCIIPopSynchronized - Undoes most recent PetscViewerASCIIPushSynchronized() for this viewer
396 
397     Collective on PetscViewer
398 
399     Input Parameters:
400 .    viewer - obtained with PetscViewerASCIIOpen()
401 
402     Level: intermediate
403 
404     Notes:
405     See documentation of PetscViewerASCIISynchronizedPrintf() for more details how the synchronized output should be done properly.
406 
407 .seealso: `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
408           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
409           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
410 @*/
411 PetscErrorCode  PetscViewerASCIIPopSynchronized(PetscViewer viewer)
412 {
413   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
414   PetscBool         iascii;
415 
416   PetscFunctionBegin;
417   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
418   PetscCheck(!ascii->sviewer,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_WRONGSTATE,"Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
419   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
420   if (iascii) {
421     ascii->allowsynchronized--;
422     PetscCheck(ascii->allowsynchronized >= 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called more times than PetscViewerASCIIPushSynchronized()");
423   }
424   PetscFunctionReturn(0);
425 }
426 
427 /*@C
428     PetscViewerASCIIPushTab - Adds one more tab to the amount that PetscViewerASCIIPrintf()
429      lines are tabbed.
430 
431     Not Collective, but only first processor in set has any effect
432 
433     Input Parameters:
434 .    viewer - obtained with PetscViewerASCIIOpen()
435 
436     Level: developer
437 
438     Fortran Note:
439     This routine is not supported in Fortran.
440 
441 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
442           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
443           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
444 @*/
445 PetscErrorCode  PetscViewerASCIIPushTab(PetscViewer viewer)
446 {
447   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
448   PetscBool         iascii;
449 
450   PetscFunctionBegin;
451   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
452   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
453   if (iascii) ascii->tab++;
454   PetscFunctionReturn(0);
455 }
456 
457 /*@C
458     PetscViewerASCIIPopTab - Removes one tab from the amount that PetscViewerASCIIPrintf()
459      lines are tabbed.
460 
461     Not Collective, but only first processor in set has any effect
462 
463     Input Parameters:
464 .    viewer - obtained with PetscViewerASCIIOpen()
465 
466     Level: developer
467 
468     Fortran Note:
469     This routine is not supported in Fortran.
470 
471 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
472           `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
473           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
474 @*/
475 PetscErrorCode  PetscViewerASCIIPopTab(PetscViewer viewer)
476 {
477   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
478   PetscBool         iascii;
479 
480   PetscFunctionBegin;
481   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
482   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
483   if (iascii) {
484     PetscCheck(ascii->tab > 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"More tabs popped than pushed");
485     ascii->tab--;
486   }
487   PetscFunctionReturn(0);
488 }
489 
490 /*@
491     PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the ASCII PetscViewer
492 
493     Not Collective, but only first processor in set has any effect
494 
495     Input Parameters:
496 +    viewer - obtained with PetscViewerASCIIOpen()
497 -    flg - PETSC_TRUE or PETSC_FALSE
498 
499     Level: developer
500 
501     Fortran Note:
502     This routine is not supported in Fortran.
503 
504 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
505           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
506           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
507 @*/
508 PetscErrorCode  PetscViewerASCIIUseTabs(PetscViewer viewer,PetscBool flg)
509 {
510   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
511   PetscBool         iascii;
512 
513   PetscFunctionBegin;
514   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
515   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
516   if (iascii) {
517     if (flg) ascii->tab = ascii->tab_store;
518     else {
519       ascii->tab_store = ascii->tab;
520       ascii->tab       = 0;
521     }
522   }
523   PetscFunctionReturn(0);
524 }
525 
526 /* ----------------------------------------------------------------------- */
527 
528 /*@C
529     PetscViewerASCIIPrintf - Prints to a file, only from the first
530     processor in the PetscViewer
531 
532     Not Collective, but only first processor in set has any effect
533 
534     Input Parameters:
535 +    viewer - obtained with PetscViewerASCIIOpen()
536 -    format - the usual printf() format string
537 
538     Level: developer
539 
540     Fortran Note:
541     The call sequence is PetscViewerASCIIPrintf(PetscViewer, character(*), int ierr) from Fortran.
542     That is, you can only pass a single character string from Fortran.
543 
544 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
545           `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
546           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
547 @*/
548 PetscErrorCode  PetscViewerASCIIPrintf(PetscViewer viewer,const char format[],...)
549 {
550   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
551   PetscMPIInt       rank;
552   PetscInt          tab,intab = ascii->tab;
553   FILE              *fd = ascii->fd;
554   PetscBool         iascii;
555   int               err;
556 
557   PetscFunctionBegin;
558   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
559   PetscCheck(!ascii->sviewer,PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_WRONGSTATE,"Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
560   PetscValidCharPointer(format,2);
561   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
562   PetscCheck(iascii,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Not ASCII PetscViewer");
563   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank));
564   if (rank) PetscFunctionReturn(0);
565 
566   if (ascii->bviewer) { /* pass string up to parent viewer */
567     char        *string;
568     va_list     Argp;
569     size_t      fullLength;
570 
571     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
572     va_start(Argp,format);
573     PetscCall(PetscVSNPrintf(string,QUEUESTRINGSIZE,format,&fullLength,Argp));
574     va_end(Argp);
575     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer,"%s",string));
576     PetscCall(PetscFree(string));
577   } else { /* write directly to file */
578     va_list Argp;
579     /* flush my own messages that I may have queued up */
580     PrintfQueue next = ascii->petsc_printfqueuebase,previous;
581     PetscInt    i;
582     for (i=0; i<ascii->petsc_printfqueuelength; i++) {
583       PetscCall(PetscFPrintf(PETSC_COMM_SELF,fd,"%s",next->string));
584       previous = next;
585       next     = next->next;
586       PetscCall(PetscFree(previous->string));
587       PetscCall(PetscFree(previous));
588     }
589     ascii->petsc_printfqueue       = NULL;
590     ascii->petsc_printfqueuelength = 0;
591     tab = intab;
592     while (tab--) {
593       PetscCall(PetscFPrintf(PETSC_COMM_SELF,fd,"  "));
594     }
595 
596     va_start(Argp,format);
597     PetscCall((*PetscVFPrintf)(fd,format,Argp));
598     err  = fflush(fd);
599     PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
600     if (petsc_history) {
601       va_start(Argp,format);
602       tab = intab;
603       while (tab--) {
604         PetscCall(PetscFPrintf(PETSC_COMM_SELF,petsc_history,"  "));
605       }
606       PetscCall((*PetscVFPrintf)(petsc_history,format,Argp));
607       err  = fflush(petsc_history);
608       PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
609     }
610     va_end(Argp);
611   }
612   PetscFunctionReturn(0);
613 }
614 
615 /*@C
616      PetscViewerFileSetName - Sets the name of the file the PetscViewer uses.
617 
618     Collective on PetscViewer
619 
620   Input Parameters:
621 +  viewer - the PetscViewer; either ASCII or binary
622 -  name - the name of the file it should use
623 
624     Level: advanced
625 
626 .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
627           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
628 
629 @*/
630 PetscErrorCode  PetscViewerFileSetName(PetscViewer viewer,const char name[])
631 {
632   char           filename[PETSC_MAX_PATH_LEN];
633 
634   PetscFunctionBegin;
635   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
636   PetscValidCharPointer(name,2);
637   PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer),name,filename,sizeof(filename)));
638   PetscTryMethod(viewer,"PetscViewerFileSetName_C",(PetscViewer,const char[]),(viewer,filename));
639   PetscFunctionReturn(0);
640 }
641 
642 /*@C
643      PetscViewerFileGetName - Gets the name of the file the PetscViewer uses.
644 
645     Not Collective
646 
647   Input Parameter:
648 .  viewer - the PetscViewer; either ASCII or binary
649 
650   Output Parameter:
651 .  name - the name of the file it is using
652 
653     Level: advanced
654 
655 .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
656 
657 @*/
658 PetscErrorCode  PetscViewerFileGetName(PetscViewer viewer,const char **name)
659 {
660   PetscFunctionBegin;
661   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
662   PetscValidPointer(name,2);
663   PetscUseMethod(viewer,"PetscViewerFileGetName_C",(PetscViewer,const char**),(viewer,name));
664   PetscFunctionReturn(0);
665 }
666 
667 PetscErrorCode  PetscViewerFileGetName_ASCII(PetscViewer viewer,const char **name)
668 {
669   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
670 
671   PetscFunctionBegin;
672   *name = vascii->filename;
673   PetscFunctionReturn(0);
674 }
675 
676 PetscErrorCode  PetscViewerFileSetName_ASCII(PetscViewer viewer,const char name[])
677 {
678   size_t            len;
679   char              fname[PETSC_MAX_PATH_LEN],*gz;
680   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
681   PetscBool         isstderr,isstdout;
682   PetscMPIInt       rank;
683 
684   PetscFunctionBegin;
685   PetscCall(PetscViewerFileClose_ASCII(viewer));
686   if (!name) PetscFunctionReturn(0);
687   PetscCall(PetscStrallocpy(name,&vascii->filename));
688 
689   /* Is this file to be compressed */
690   vascii->storecompressed = PETSC_FALSE;
691 
692   PetscCall(PetscStrstr(vascii->filename,".gz",&gz));
693   if (gz) {
694     PetscCall(PetscStrlen(gz,&len));
695     if (len == 3) {
696       PetscCheck(vascii->mode == FILE_MODE_WRITE,PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first");
697       *gz = 0;
698       vascii->storecompressed = PETSC_TRUE;
699     }
700   }
701   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank));
702   if (rank == 0) {
703     PetscCall(PetscStrcmp(name,"stderr",&isstderr));
704     PetscCall(PetscStrcmp(name,"stdout",&isstdout));
705     /* empty filename means stdout */
706     if (name[0] == 0)  isstdout = PETSC_TRUE;
707     if (isstderr)      vascii->fd = PETSC_STDERR;
708     else if (isstdout) vascii->fd = PETSC_STDOUT;
709     else {
710 
711       PetscCall(PetscFixFilename(name,fname));
712       switch (vascii->mode) {
713       case FILE_MODE_READ:
714         vascii->fd = fopen(fname,"r");
715         break;
716       case FILE_MODE_WRITE:
717         vascii->fd = fopen(fname,"w");
718         break;
719       case FILE_MODE_APPEND:
720         vascii->fd = fopen(fname,"a");
721         break;
722       case FILE_MODE_UPDATE:
723         vascii->fd = fopen(fname,"r+");
724         if (!vascii->fd) vascii->fd = fopen(fname,"w+");
725         break;
726       case FILE_MODE_APPEND_UPDATE:
727         /* I really want a file which is opened at the end for updating,
728            not a+, which opens at the beginning, but makes writes at the end.
729         */
730         vascii->fd = fopen(fname,"r+");
731         if (!vascii->fd) vascii->fd = fopen(fname,"w+");
732         else {
733           PetscCall(fseek(vascii->fd, 0, SEEK_END));
734         }
735         break;
736       default:
737         SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[vascii->mode]);
738       }
739       PetscCheck(vascii->fd,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open PetscViewer file: %s",fname);
740     }
741   }
742 #if defined(PETSC_USE_LOG)
743   PetscLogObjectState((PetscObject)viewer,"File: %s",name);
744 #endif
745   PetscFunctionReturn(0);
746 }
747 
748 PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer,MPI_Comm subcomm,PetscViewer *outviewer)
749 {
750   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data,*ovascii;
751 
752   PetscFunctionBegin;
753   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
754   PetscCheck(!vascii->sviewer,PETSC_COMM_SELF,PETSC_ERR_ORDER,"SubViewer already obtained from PetscViewer and not restored");
755   /*
756      The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
757      because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
758      (since the count never gets to zero) in some examples this displays information that otherwise would be lost
759 
760      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
761      PCView_GASM().
762   */
763   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
764   PetscCall(PetscViewerCreate(subcomm,outviewer));
765   PetscCall(PetscViewerSetType(*outviewer,PETSCVIEWERASCII));
766   PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
767   ovascii      = (PetscViewer_ASCII*)(*outviewer)->data;
768   ovascii->fd  = vascii->fd;
769   ovascii->tab = vascii->tab;
770   ovascii->closefile = PETSC_FALSE;
771 
772   vascii->sviewer = *outviewer;
773   (*outviewer)->format  = viewer->format;
774   ((PetscViewer_ASCII*)((*outviewer)->data))->bviewer = viewer;
775   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer;
776   PetscFunctionReturn(0);
777 }
778 
779 PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
780 {
781   PetscViewer_ASCII *ascii  = (PetscViewer_ASCII*)viewer->data;
782 
783   PetscFunctionBegin;
784   PetscCheck(ascii->sviewer,PETSC_COMM_SELF,PETSC_ERR_ORDER,"SubViewer never obtained from PetscViewer");
785   PetscCheck(ascii->sviewer == *outviewer,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"This PetscViewer did not generate this SubViewer");
786 
787   PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
788   ascii->sviewer             = NULL;
789   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
790   PetscCall(PetscViewerDestroy(outviewer));
791   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
792   PetscFunctionReturn(0);
793 }
794 
795 PetscErrorCode  PetscViewerView_ASCII(PetscViewer v,PetscViewer viewer)
796 {
797   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)v->data;
798 
799   PetscFunctionBegin;
800   if (ascii->filename) {
801     PetscCall(PetscViewerASCIIPrintf(viewer,"Filename: %s\n",ascii->filename));
802   }
803   PetscFunctionReturn(0);
804 }
805 
806 /*MC
807    PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file
808 
809 .seealso: `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
810           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
811           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
812 
813   Level: beginner
814 
815 M*/
816 PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
817 {
818   PetscViewer_ASCII *vascii;
819 
820   PetscFunctionBegin;
821   PetscCall(PetscNewLog(viewer,&vascii));
822   viewer->data = (void*)vascii;
823 
824   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
825   viewer->ops->flush            = PetscViewerFlush_ASCII;
826   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
827   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
828   viewer->ops->view             = PetscViewerView_ASCII;
829   viewer->ops->read             = PetscViewerASCIIRead;
830 
831   /* defaults to stdout unless set with PetscViewerFileSetName() */
832   vascii->fd        = PETSC_STDOUT;
833   vascii->mode      = FILE_MODE_WRITE;
834   vascii->bviewer   = NULL;
835   vascii->subviewer = NULL;
836   vascii->sviewer   = NULL;
837   vascii->tab       = 0;
838   vascii->tab_store = 0;
839   vascii->filename  = NULL;
840   vascii->closefile = PETSC_TRUE;
841 
842   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_ASCII));
843   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",PetscViewerFileGetName_ASCII));
844   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_ASCII));
845   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_ASCII));
846   PetscFunctionReturn(0);
847 }
848 
849 /*@C
850     PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified file from
851     several processors.  Output of the first processor is followed by that of the
852     second, etc.
853 
854     Not Collective, must call collective PetscViewerFlush() to get the results out
855 
856     Input Parameters:
857 +   viewer - the ASCII PetscViewer
858 -   format - the usual printf() format string
859 
860     Level: intermediate
861 
862     Notes:
863     You must have previously called PetscViewerASCIIPushSynchronized() to allow this routine to be called.
864     Then you can do multiple independent calls to this routine.
865     The actual synchronized print is then done using PetscViewerFlush().
866     PetscViewerASCIIPopSynchronized() should be then called if we are already done with the synchronized output
867     to conclude the "synchronized session".
868     So the typical calling sequence looks like
869 $ PetscViewerASCIIPushSynchronized(viewer);
870 $ PetscViewerASCIISynchronizedPrintf(viewer, ...);
871 $ PetscViewerASCIISynchronizedPrintf(viewer, ...);
872 $ ...
873 $ PetscViewerFlush(viewer);
874 $ PetscViewerASCIISynchronizedPrintf(viewer, ...);
875 $ PetscViewerASCIISynchronizedPrintf(viewer, ...);
876 $ ...
877 $ PetscViewerFlush(viewer);
878 $ PetscViewerASCIIPopSynchronized(viewer);
879 
880     Fortran Note:
881       Can only print a single character* string
882 
883 .seealso: `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
884           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
885           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
886 @*/
887 PetscErrorCode  PetscViewerASCIISynchronizedPrintf(PetscViewer viewer,const char format[],...)
888 {
889   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
890   PetscMPIInt       rank;
891   PetscInt          tab = vascii->tab;
892   MPI_Comm          comm;
893   FILE              *fp;
894   PetscBool         iascii,hasbviewer = PETSC_FALSE;
895   int               err;
896 
897   PetscFunctionBegin;
898   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
899   PetscValidCharPointer(format,2);
900   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
901   PetscCheck(iascii,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Not ASCII PetscViewer");
902   PetscCheck(vascii->allowsynchronized,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"First call PetscViewerASCIIPushSynchronized() to allow this call");
903 
904   PetscCall(PetscObjectGetComm((PetscObject)viewer,&comm));
905   PetscCallMPI(MPI_Comm_rank(comm,&rank));
906 
907   if (vascii->bviewer) {
908     hasbviewer = PETSC_TRUE;
909     if (rank == 0) {
910       vascii = (PetscViewer_ASCII*)vascii->bviewer->data;
911       PetscCall(PetscObjectGetComm((PetscObject)viewer,&comm));
912       PetscCallMPI(MPI_Comm_rank(comm,&rank));
913     }
914   }
915 
916   fp   = vascii->fd;
917 
918   if (rank == 0 && !hasbviewer) {   /* First processor prints immediately to fp */
919     va_list Argp;
920     /* flush my own messages that I may have queued up */
921     PrintfQueue next = vascii->petsc_printfqueuebase,previous;
922     PetscInt    i;
923     for (i=0; i<vascii->petsc_printfqueuelength; i++) {
924       PetscCall(PetscFPrintf(comm,fp,"%s",next->string));
925       previous = next;
926       next     = next->next;
927       PetscCall(PetscFree(previous->string));
928       PetscCall(PetscFree(previous));
929     }
930     vascii->petsc_printfqueue       = NULL;
931     vascii->petsc_printfqueuelength = 0;
932 
933     while (tab--) {
934       PetscCall(PetscFPrintf(PETSC_COMM_SELF,fp,"  "));
935     }
936 
937     va_start(Argp,format);
938     PetscCall((*PetscVFPrintf)(fp,format,Argp));
939     err  = fflush(fp);
940     PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
941     if (petsc_history) {
942       va_start(Argp,format);
943       PetscCall((*PetscVFPrintf)(petsc_history,format,Argp));
944       err  = fflush(petsc_history);
945       PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
946     }
947     va_end(Argp);
948   } else { /* other processors add to queue */
949     char        *string;
950     va_list     Argp;
951     size_t      fullLength;
952     PrintfQueue next;
953 
954     PetscCall(PetscNew(&next));
955     if (vascii->petsc_printfqueue) {
956       vascii->petsc_printfqueue->next = next;
957       vascii->petsc_printfqueue       = next;
958     } else {
959       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
960     }
961     vascii->petsc_printfqueuelength++;
962     next->size = QUEUESTRINGSIZE;
963     PetscCall(PetscCalloc1(next->size, &next->string));
964     string     = next->string;
965     tab       *= 2;
966     while (tab--) {
967       *string++ = ' ';
968     }
969     va_start(Argp,format);
970     PetscCall(PetscVSNPrintf(string,next->size-2*vascii->tab,format,&fullLength,Argp));
971     va_end(Argp);
972     if (fullLength > (size_t) (next->size-2*vascii->tab)) {
973       PetscCall(PetscFree(next->string));
974       next->size = fullLength + 2*vascii->tab;
975       PetscCall(PetscCalloc1(next->size, &next->string));
976       string     = next->string;
977       tab        = 2*vascii->tab;
978       while (tab--) {
979         *string++ = ' ';
980       }
981       va_start(Argp,format);
982       PetscCall(PetscVSNPrintf(string,next->size-2*vascii->tab,format,NULL,Argp));
983       va_end(Argp);
984     }
985   }
986   PetscFunctionReturn(0);
987 }
988 
989 /*@C
990    PetscViewerASCIIRead - Reads from a ASCII file
991 
992    Only process 0 in the PetscViewer may call this
993 
994    Input Parameters:
995 +  viewer - the ascii viewer
996 .  data - location to write the data
997 .  num - number of items of data to read
998 -  datatype - type of data to read
999 
1000    Output Parameters:
1001 .  count - number of items of data actually read, or NULL
1002 
1003    Level: beginner
1004 
1005 .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1006           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1007           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1008 @*/
1009 PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype)
1010 {
1011   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
1012   FILE              *fd = vascii->fd;
1013   PetscInt           i;
1014   int                ret = 0;
1015   PetscMPIInt        rank;
1016 
1017   PetscFunctionBegin;
1018   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1019   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank));
1020   PetscCheck(rank == 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Can only be called from process 0 in the PetscViewer");
1021   for (i=0; i<num; i++) {
1022     if (dtype == PETSC_CHAR)         ret = fscanf(fd, "%c",  &(((char*)data)[i]));
1023     else if (dtype == PETSC_STRING)  ret = fscanf(fd, "%s",  &(((char*)data)[i]));
1024     else if (dtype == PETSC_INT)     ret = fscanf(fd, "%" PetscInt_FMT,  &(((PetscInt*)data)[i]));
1025     else if (dtype == PETSC_ENUM)    ret = fscanf(fd, "%d",  &(((int*)data)[i]));
1026     else if (dtype == PETSC_INT64)   ret = fscanf(fd, "%" PetscInt64_FMT,  &(((PetscInt64*)data)[i]));
1027     else if (dtype == PETSC_LONG)    ret = fscanf(fd, "%ld", &(((long*)data)[i]));
1028     else if (dtype == PETSC_FLOAT)   ret = fscanf(fd, "%f",  &(((float*)data)[i]));
1029     else if (dtype == PETSC_DOUBLE)  ret = fscanf(fd, "%lg", &(((double*)data)[i]));
1030 #if defined(PETSC_USE_REAL___FLOAT128)
1031     else if (dtype == PETSC___FLOAT128) {
1032       double tmp;
1033       ret = fscanf(fd, "%lg", &tmp);
1034       ((__float128*)data)[i] = tmp;
1035     }
1036 #endif
1037     else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Data type %d not supported", (int) dtype);
1038     PetscCheck(ret,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int) dtype);
1039     if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
1040   }
1041   if (count) *count = i;
1042   else PetscCheck(ret >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
1043   PetscFunctionReturn(0);
1044 }
1045