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