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