xref: /petsc/src/sys/classes/viewer/impls/ascii/filev.c (revision dc424cfae46ffd055acbb99fbc61fc85fc92f9ad)
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_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelViewer,&Petsc_Viewer_keyval,(void*)0);CHKERRQ(ierr);
54   }
55 
56   ierr = MPI_Attr_get(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_Attr_put(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_keyval,vlink->next);CHKERRQ(ierr);
61       } else {
62         ierr = MPI_Attr_delete(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_Attr_get(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stdout_keyval,(void**)&aviewer,(PetscMPIInt*)&flg);CHKERRQ(ierr);
80     if (flg && aviewer == viewer) {
81       ierr = MPI_Attr_delete(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_Attr_get(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stderr_keyval,(void**)&aviewer,(PetscMPIInt*)&flg);CHKERRQ(ierr);
87     if (flg && aviewer == viewer) {
88       ierr = MPI_Attr_delete(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 
662   PetscFunctionBegin;
663   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
664   PetscValidCharPointer(name,2);
665   ierr = PetscTryMethod(viewer,"PetscViewerFileSetName_C",(PetscViewer,const char[]),(viewer,name));CHKERRQ(ierr);
666   PetscFunctionReturn(0);
667 }
668 
669 /*@C
670      PetscViewerFileGetName - Gets the name of the file the PetscViewer uses.
671 
672     Not Collective
673 
674   Input Parameter:
675 .  viewer - the PetscViewer; either ASCII or binary
676 
677   Output Parameter:
678 .  name - the name of the file it is using
679 
680     Level: advanced
681 
682 .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PetscViewerFileSetName()
683 
684 @*/
685 PetscErrorCode  PetscViewerFileGetName(PetscViewer viewer,const char **name)
686 {
687   PetscErrorCode ierr;
688 
689   PetscFunctionBegin;
690   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
691   ierr = PetscUseMethod(viewer,"PetscViewerFileGetName_C",(PetscViewer,const char**),(viewer,name));CHKERRQ(ierr);
692   PetscFunctionReturn(0);
693 }
694 
695 PetscErrorCode  PetscViewerFileGetName_ASCII(PetscViewer viewer,const char **name)
696 {
697   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
698 
699   PetscFunctionBegin;
700   *name = vascii->filename;
701   PetscFunctionReturn(0);
702 }
703 
704 PetscErrorCode  PetscViewerFileSetName_ASCII(PetscViewer viewer,const char name[])
705 {
706   PetscErrorCode    ierr;
707   size_t            len;
708   char              fname[PETSC_MAX_PATH_LEN],*gz;
709   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
710   PetscBool         isstderr,isstdout;
711   PetscMPIInt       rank;
712 
713   PetscFunctionBegin;
714   ierr = PetscViewerFileClose_ASCII(viewer);CHKERRQ(ierr);
715   if (!name) PetscFunctionReturn(0);
716   ierr = PetscStrallocpy(name,&vascii->filename);CHKERRQ(ierr);
717 
718   /* Is this file to be compressed */
719   vascii->storecompressed = PETSC_FALSE;
720 
721   ierr = PetscStrstr(vascii->filename,".gz",&gz);CHKERRQ(ierr);
722   if (gz) {
723     ierr = PetscStrlen(gz,&len);CHKERRQ(ierr);
724     if (len == 3) {
725       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");
726       *gz = 0;
727       vascii->storecompressed = PETSC_TRUE;
728     }
729   }
730   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
731   if (!rank) {
732     ierr = PetscStrcmp(name,"stderr",&isstderr);CHKERRQ(ierr);
733     ierr = PetscStrcmp(name,"stdout",&isstdout);CHKERRQ(ierr);
734     /* empty filename means stdout */
735     if (name[0] == 0)  isstdout = PETSC_TRUE;
736     if (isstderr)      vascii->fd = PETSC_STDERR;
737     else if (isstdout) vascii->fd = PETSC_STDOUT;
738     else {
739 
740 
741       ierr = PetscFixFilename(name,fname);CHKERRQ(ierr);
742       switch (vascii->mode) {
743       case FILE_MODE_READ:
744         vascii->fd = fopen(fname,"r");
745         break;
746       case FILE_MODE_WRITE:
747         vascii->fd = fopen(fname,"w");
748         break;
749       case FILE_MODE_APPEND:
750         vascii->fd = fopen(fname,"a");
751         break;
752       case FILE_MODE_UPDATE:
753         vascii->fd = fopen(fname,"r+");
754         if (!vascii->fd) vascii->fd = fopen(fname,"w+");
755         break;
756       case FILE_MODE_APPEND_UPDATE:
757         /* I really want a file which is opened at the end for updating,
758            not a+, which opens at the beginning, but makes writes at the end.
759         */
760         vascii->fd = fopen(fname,"r+");
761         if (!vascii->fd) vascii->fd = fopen(fname,"w+");
762         else {
763           ierr     = fseek(vascii->fd, 0, SEEK_END);CHKERRQ(ierr);
764         }
765         break;
766       default:
767         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Invalid file mode %d", vascii->mode);
768       }
769       if (!vascii->fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open PetscViewer file: %s",fname);
770     }
771   }
772 #if defined(PETSC_USE_LOG)
773   PetscLogObjectState((PetscObject)viewer,"File: %s",name);
774 #endif
775   PetscFunctionReturn(0);
776 }
777 
778 PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer,MPI_Comm subcomm,PetscViewer *outviewer)
779 {
780   PetscMPIInt       rank;
781   PetscErrorCode    ierr;
782   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data,*ovascii;
783 
784   PetscFunctionBegin;
785   if (vascii->sviewer) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"SubViewer already obtained from PetscViewer and not restored");
786   ierr         = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
787   ierr         = PetscViewerCreate(subcomm,outviewer);CHKERRQ(ierr);
788   ierr         = PetscViewerSetType(*outviewer,PETSCVIEWERASCII);CHKERRQ(ierr);
789   ierr         = PetscViewerASCIIPushSynchronized(*outviewer);CHKERRQ(ierr);
790   ovascii      = (PetscViewer_ASCII*)(*outviewer)->data;
791   ovascii->fd  = vascii->fd;
792   ovascii->tab = vascii->tab;
793   ovascii->closefile = PETSC_FALSE;
794 
795   vascii->sviewer = *outviewer;
796 
797   (*outviewer)->format  = viewer->format;
798 
799   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
800   ((PetscViewer_ASCII*)((*outviewer)->data))->bviewer = viewer;
801   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer;
802   PetscFunctionReturn(0);
803 }
804 
805 PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
806 {
807   PetscErrorCode    ierr;
808   PetscViewer_ASCII *ascii  = (PetscViewer_ASCII*)viewer->data;
809 
810   PetscFunctionBegin;
811   if (!ascii->sviewer) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"SubViewer never obtained from PetscViewer");
812   if (ascii->sviewer != *outviewer) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"This PetscViewer did not generate this SubViewer");
813 
814   ascii->sviewer             = 0;
815   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
816   ierr                       = PetscViewerDestroy(outviewer);CHKERRQ(ierr);
817   PetscFunctionReturn(0);
818 }
819 
820 PetscErrorCode  PetscViewerView_ASCII(PetscViewer v,PetscViewer viewer)
821 {
822   PetscErrorCode    ierr;
823   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)v->data;
824 
825   PetscFunctionBegin;
826   if (ascii->filename) {
827     ierr = PetscViewerASCIIPrintf(viewer,"Filename: %s\n",ascii->filename);CHKERRQ(ierr);
828   }
829   PetscFunctionReturn(0);
830 }
831 
832 /*MC
833    PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file
834 
835 
836 .seealso:  PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD,PetscViewerCreate(), PetscViewerASCIIOpen(),
837            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERBINARY, PETSCVIEWERMATLAB,
838            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()
839 
840   Level: beginner
841 
842 M*/
843 PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
844 {
845   PetscViewer_ASCII *vascii;
846   PetscErrorCode    ierr;
847 
848   PetscFunctionBegin;
849   ierr         = PetscNewLog(viewer,&vascii);CHKERRQ(ierr);
850   viewer->data = (void*)vascii;
851 
852   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
853   viewer->ops->flush            = PetscViewerFlush_ASCII;
854   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
855   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
856   viewer->ops->view             = PetscViewerView_ASCII;
857   viewer->ops->read             = PetscViewerASCIIRead;
858 
859   /* defaults to stdout unless set with PetscViewerFileSetName() */
860   vascii->fd        = PETSC_STDOUT;
861   vascii->mode      = FILE_MODE_WRITE;
862   vascii->bviewer   = 0;
863   vascii->subviewer = 0;
864   vascii->sviewer   = 0;
865   vascii->tab       = 0;
866   vascii->tab_store = 0;
867   vascii->filename  = 0;
868   vascii->closefile = PETSC_TRUE;
869 
870   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_ASCII);CHKERRQ(ierr);
871   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",PetscViewerFileGetName_ASCII);CHKERRQ(ierr);
872   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_ASCII);CHKERRQ(ierr);
873   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_ASCII);CHKERRQ(ierr);
874   PetscFunctionReturn(0);
875 }
876 
877 /*@C
878     PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified file from
879     several processors.  Output of the first processor is followed by that of the
880     second, etc.
881 
882     Not Collective, must call collective PetscViewerFlush() to get the results out
883 
884     Input Parameters:
885 +   viewer - the ASCII PetscViewer
886 -   format - the usual printf() format string
887 
888     Level: intermediate
889 
890     Notes: You must have previously called PetscViewerASCIISynchronizeAllow() to allow this routine to be called.
891 
892     Fortran Note:
893       Can only print a single character* string
894 
895 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(),
896           PetscFOpen(), PetscViewerFlush(), PetscViewerASCIIGetPointer(), PetscViewerDestroy(), PetscViewerASCIIOpen(),
897           PetscViewerASCIIPrintf(), PetscViewerASCIIPushSynchronized()
898 
899 @*/
900 PetscErrorCode  PetscViewerASCIISynchronizedPrintf(PetscViewer viewer,const char format[],...)
901 {
902   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
903   PetscErrorCode    ierr;
904   PetscMPIInt       rank;
905   PetscInt          tab = vascii->tab;
906   MPI_Comm          comm;
907   FILE              *fp;
908   PetscBool         iascii,hasbviewer = PETSC_FALSE;
909   int               err;
910 
911   PetscFunctionBegin;
912   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
913   PetscValidCharPointer(format,2);
914   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
915   if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Not ASCII PetscViewer");
916   if (!vascii->allowsynchronized) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"First call PetscViewerASCIIPushSynchronized() to allow this call");
917 
918   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
919   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
920 
921   if (vascii->bviewer) {
922     hasbviewer = PETSC_TRUE;
923     if (!rank) {
924       vascii = (PetscViewer_ASCII*)vascii->bviewer->data;
925       ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
926       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
927     }
928   }
929 
930   fp   = vascii->fd;
931 
932   if (!rank && !hasbviewer) {   /* First processor prints immediately to fp */
933     va_list Argp;
934     /* flush my own messages that I may have queued up */
935     PrintfQueue next = vascii->petsc_printfqueuebase,previous;
936     PetscInt    i;
937     for (i=0; i<vascii->petsc_printfqueuelength; i++) {
938       ierr = PetscFPrintf(comm,fp,"%s",next->string);CHKERRQ(ierr);
939       previous = next;
940       next     = next->next;
941       ierr     = PetscFree(previous->string);CHKERRQ(ierr);
942       ierr     = PetscFree(previous);CHKERRQ(ierr);
943     }
944     vascii->petsc_printfqueue       = 0;
945     vascii->petsc_printfqueuelength = 0;
946 
947     while (tab--) {
948       ierr = PetscFPrintf(PETSC_COMM_SELF,fp,"  ");CHKERRQ(ierr);
949     }
950 
951     va_start(Argp,format);
952     ierr = (*PetscVFPrintf)(fp,format,Argp);CHKERRQ(ierr);
953     err  = fflush(fp);
954     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
955     if (petsc_history) {
956       va_start(Argp,format);
957       ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr);
958       err  = fflush(petsc_history);
959       if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
960     }
961     va_end(Argp);
962   } else { /* other processors add to queue */
963     char        *string;
964     va_list     Argp;
965     size_t      fullLength;
966     PrintfQueue next;
967 
968     ierr = PetscNew(&next);CHKERRQ(ierr);
969     if (vascii->petsc_printfqueue) {
970       vascii->petsc_printfqueue->next = next;
971       vascii->petsc_printfqueue       = next;
972     } else {
973       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
974     }
975     vascii->petsc_printfqueuelength++;
976     next->size = QUEUESTRINGSIZE;
977     ierr       = PetscMalloc1(next->size, &next->string);CHKERRQ(ierr);
978     ierr       = PetscMemzero(next->string,next->size);CHKERRQ(ierr);
979     string     = next->string;
980     tab       *= 2;
981     while (tab--) {
982       *string++ = ' ';
983     }
984     va_start(Argp,format);
985     ierr = PetscVSNPrintf(string,next->size-2*vascii->tab,format,&fullLength,Argp);CHKERRQ(ierr);
986     va_end(Argp);
987   }
988   PetscFunctionReturn(0);
989 }
990 
991 /*@C
992    PetscViewerASCIIRead - Reads from am ASCII file
993 
994    Collective on MPI_Comm
995 
996    Input Parameters:
997 +  viewer - the ascii viewer
998 .  data - location to write the data
999 .  num - number of items of data to read
1000 -  datatype - type of data to read
1001 
1002    Output Parameters:
1003 .  count - number of items of data actually read, or NULL
1004 
1005    Level: beginner
1006 
1007    Concepts: ascii files
1008 
1009 .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
1010           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
1011           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
1012 @*/
1013 PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype)
1014 {
1015   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
1016   FILE              *fd = vascii->fd;
1017   PetscInt           i;
1018   int                ret = 0;
1019 
1020   PetscFunctionBegin;
1021   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1022   for (i=0; i<num; i++) {
1023     if (dtype == PETSC_CHAR)         ret = fscanf(fd, "%c",  &(((char*)data)[i]));
1024     else if (dtype == PETSC_STRING)  ret = fscanf(fd, "%s",  &(((char*)data)[i]));
1025     else if (dtype == PETSC_INT)     ret = fscanf(fd, "%" PetscInt_FMT,  &(((PetscInt*)data)[i]));
1026     else if (dtype == PETSC_ENUM)    ret = fscanf(fd, "%d",  &(((int*)data)[i]));
1027     else if (dtype == PETSC_FLOAT)   ret = fscanf(fd, "%f",  &(((float*)data)[i]));
1028     else if (dtype == PETSC_DOUBLE)  ret = fscanf(fd, "%lg", &(((double*)data)[i]));
1029 #if defined(PETSC_USE_REAL___FLOAT128)
1030     else if (dtype == PETSC___FLOAT128) {
1031       double tmp;
1032       ret = fscanf(fd, "%lg", &tmp);
1033       ((__float128*)data)[i] = tmp;
1034     }
1035 #endif
1036     else {SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Data type %d not supported", (int) dtype);}
1037     if (!ret) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int) dtype);
1038     else if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
1039   }
1040   if (count) *count = i;
1041   else if (ret < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %D < %D items", i, num);
1042   PetscFunctionReturn(0);
1043 }
1044 
1045