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