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