Actual source code: filev.c
2: #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h>
4: #define QUEUESTRINGSIZE 8192
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;
14: if (vascii->sviewer) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_WRONGSTATE,"Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
15: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
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: PetscStrncpy(par,"gzip ",sizeof(par));
25: PetscStrlcat(par,vascii->filename,sizeof(par));
26: #if defined(PETSC_HAVE_POPEN)
27: PetscPOpen(PETSC_COMM_SELF,NULL,par,"r",&fp);
28: if (fgets(buf,1024,fp)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error from compression command %s\n%s",par,buf);
29: PetscPClose(PETSC_COMM_SELF,fp);
30: #else
31: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
32: #endif
33: }
34: }
35: PetscFree(vascii->filename);
36: return(0);
37: }
39: /* ----------------------------------------------------------------------*/
40: PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
41: {
42: PetscErrorCode ierr;
43: PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
44: PetscViewerLink *vlink;
45: PetscBool flg;
48: if (vascii->sviewer) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_WRONGSTATE,"Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
49: PetscViewerFileClose_ASCII(viewer);
50: PetscFree(vascii);
52: /* remove the viewer from the list in the MPI Communicator */
53: if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) {
54: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,Petsc_DelViewer,&Petsc_Viewer_keyval,(void*)0);
55: }
57: MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_keyval,(void**)&vlink,(PetscMPIInt*)&flg);
58: if (flg) {
59: if (vlink && vlink->viewer == viewer) {
60: if (vlink->next) {
61: MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_keyval,vlink->next);
62: } else {
63: MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_keyval);
64: }
65: PetscFree(vlink);
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: PetscFree(nv);
72: }
73: vlink = vlink->next;
74: }
75: }
76: }
78: if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
79: PetscViewer aviewer;
80: MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stdout_keyval,(void**)&aviewer,(PetscMPIInt*)&flg);
81: if (flg && aviewer == viewer) {
82: MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stdout_keyval);
83: }
84: }
85: if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
86: PetscViewer aviewer;
87: MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stderr_keyval,(void**)&aviewer,(PetscMPIInt*)&flg);
88: if (flg && aviewer == viewer) {
89: MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stderr_keyval);
90: }
91: }
92: return(0);
93: }
95: PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
96: {
97: PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
98: PetscErrorCode ierr;
101: PetscViewerRestoreSubViewer(vascii->bviewer,0,&viewer);
102: return(0);
103: }
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;
115: if (vascii->sviewer) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_WRONGSTATE,"Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
116: PetscObjectGetComm((PetscObject)viewer,&comm);
117: MPI_Comm_rank(comm,&rank);
118: MPI_Comm_size(comm,&size);
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: }
125: if (vascii->allowsynchronized) {
126: PetscMPIInt tag,i,j,n = 0,dummy = 0;
127: char *message;
128: MPI_Status status;
130: PetscCommDuplicate(comm,&comm,&tag);
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: PetscFPrintf(comm,fd,"%s",next->string);
139: } else {
140: PetscViewerASCIISynchronizedPrintf(vascii->bviewer,"%s",next->string);
141: }
142: previous = next;
143: next = next->next;
144: PetscFree(previous->string);
145: PetscFree(previous);
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: MPI_Send(&dummy,1,MPI_INT,i,tag,comm);
152: MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);
153: for (j=0; j<n; j++) {
154: PetscMPIInt size = 0;
156: MPI_Recv(&size,1,MPI_INT,i,tag,comm,&status);
157: PetscMalloc1(size, &message);
158: MPI_Recv(message,size,MPI_CHAR,i,tag,comm,&status);
159: if (!vascii->bviewer) {
160: PetscFPrintf(comm,fd,"%s",message);
161: } else {
162: PetscViewerASCIISynchronizedPrintf(vascii->bviewer,"%s",message);
163: }
164: PetscFree(message);
165: }
166: }
167: } else { /* other processors send queue to processor 0 */
168: PrintfQueue next = vascii->petsc_printfqueuebase,previous;
170: MPI_Recv(&dummy,1,MPI_INT,0,tag,comm,&status);
171: MPI_Send(&vascii->petsc_printfqueuelength,1,MPI_INT,0,tag,comm);
172: for (i=0; i<vascii->petsc_printfqueuelength; i++) {
173: MPI_Send(&next->size,1,MPI_INT,0,tag,comm);
174: MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm);
175: previous = next;
176: next = next->next;
177: PetscFree(previous->string);
178: PetscFree(previous);
179: }
180: vascii->petsc_printfqueue = NULL;
181: vascii->petsc_printfqueuelength = 0;
182: }
183: PetscCommDestroy(&comm);
184: }
185: return(0);
186: }
188: /*@C
189: PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII PetscViewer.
191: Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer
193: Input Parameter:
194: . viewer - PetscViewer context, obtained from PetscViewerASCIIOpen()
196: Output Parameter:
197: . fd - file pointer
199: Notes: for the standard PETSCVIEWERASCII the value is valid only on process 0 of the viewer
201: Level: intermediate
203: Fortran Note:
204: This routine is not supported in Fortran.
207: .seealso: PetscViewerASCIIOpen(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerCreate(), PetscViewerASCIIPrintf(),
208: PetscViewerASCIISynchronizedPrintf(), PetscViewerFlush()
209: @*/
210: PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer,FILE **fd)
211: {
212: PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
215: *fd = vascii->fd;
216: return(0);
217: }
219: PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
220: {
221: PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
224: *mode = vascii->mode;
225: return(0);
226: }
228: PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
229: {
230: PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
233: vascii->mode = mode;
234: return(0);
235: }
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;
243: /*@
244: PetscViewerASCIISetTab - Causes PetscViewer to tab in a number of times
246: Not Collective, but only first processor in set has any effect
248: Input Parameters:
249: + viewer - obtained with PetscViewerASCIIOpen()
250: - tabs - number of tabs
252: Level: developer
254: Fortran Note:
255: This routine is not supported in Fortran.
258: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIIGetTab(),
259: PetscViewerASCIIPopTab(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIOpen(),
260: PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer(), PetscViewerASCIIPushTab()
261: @*/
262: PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer,PetscInt tabs)
263: {
264: PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
265: PetscBool iascii;
266: PetscErrorCode ierr;
270: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
271: if (iascii) ascii->tab = tabs;
272: return(0);
273: }
275: /*@
276: PetscViewerASCIIGetTab - Return the number of tabs used by PetscViewer.
278: Not Collective, meaningful on first processor only.
280: Input Parameters:
281: . viewer - obtained with PetscViewerASCIIOpen()
283: Output Parameters:
284: . tabs - number of tabs
286: Level: developer
288: Fortran Note:
289: This routine is not supported in Fortran.
292: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISetTab(),
293: PetscViewerASCIIPopTab(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIOpen(),
294: PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer(), PetscViewerASCIIPushTab()
295: @*/
296: PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer,PetscInt *tabs)
297: {
298: PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
299: PetscBool iascii;
300: PetscErrorCode ierr;
304: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
305: if (iascii && tabs) *tabs = ascii->tab;
306: return(0);
307: }
309: /*@
310: PetscViewerASCIIAddTab - Add to the number of times an ASCII viewer tabs before printing
312: Not Collective, but only first processor in set has any effect
314: Input Parameters:
315: + viewer - obtained with PetscViewerASCIIOpen()
316: - tabs - number of tabs
318: Level: developer
320: Fortran Note:
321: This routine is not supported in Fortran.
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;
336: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
337: if (iascii) ascii->tab += tabs;
338: return(0);
339: }
341: /*@
342: PetscViewerASCIISubtractTab - Subtracts from the number of times an ASCII viewer tabs before printing
344: Not Collective, but only first processor in set has any effect
346: Input Parameters:
347: + viewer - obtained with PetscViewerASCIIOpen()
348: - tabs - number of tabs
350: Level: developer
352: Fortran Note:
353: This routine is not supported in Fortran.
356: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
357: PetscViewerASCIIPopTab(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIOpen(),
358: PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer(), PetscViewerASCIIPushTab()
359: @*/
360: PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer,PetscInt tabs)
361: {
362: PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
363: PetscBool iascii;
364: PetscErrorCode ierr;
368: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
369: if (iascii) ascii->tab -= tabs;
370: return(0);
371: }
373: /*@C
374: PetscViewerASCIIPushSynchronized - Allows calls to PetscViewerASCIISynchronizedPrintf() for this viewer
376: Collective on PetscViewer
378: Input Parameters:
379: . viewer - obtained with PetscViewerASCIIOpen()
381: Level: intermediate
383: Notes:
384: See documentation of PetscViewerASCIISynchronizedPrintf() for more details how the synchronized output should be done properly.
387: .seealso: PetscViewerASCIISynchronizedPrintf(), PetscViewerFlush(), PetscViewerASCIIPopSynchronized(),
388: PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIIOpen(),
389: PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType()
390: @*/
391: PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
392: {
393: PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
394: PetscBool iascii;
395: PetscErrorCode ierr;
399: if (ascii->sviewer) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_WRONGSTATE,"Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
400: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
401: if (iascii) ascii->allowsynchronized++;
402: return(0);
403: }
405: /*@C
406: PetscViewerASCIIPopSynchronized - Undoes most recent PetscViewerASCIIPushSynchronized() for this viewer
408: Collective on PetscViewer
410: Input Parameters:
411: . viewer - obtained with PetscViewerASCIIOpen()
413: Level: intermediate
415: Notes:
416: See documentation of PetscViewerASCIISynchronizedPrintf() for more details how the synchronized output should be done properly.
419: .seealso: PetscViewerASCIIPushSynchronized(), PetscViewerASCIISynchronizedPrintf(), PetscViewerFlush(),
420: PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIIOpen(),
421: PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType()
422: @*/
423: PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
424: {
425: PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
426: PetscBool iascii;
427: PetscErrorCode ierr;
431: if (ascii->sviewer) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_WRONGSTATE,"Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
432: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
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: return(0);
438: }
440: /*@C
441: PetscViewerASCIIPushTab - Adds one more tab to the amount that PetscViewerASCIIPrintf()
442: lines are tabbed.
444: Not Collective, but only first processor in set has any effect
446: Input Parameters:
447: . viewer - obtained with PetscViewerASCIIOpen()
449: Level: developer
451: Fortran Note:
452: This routine is not supported in Fortran.
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;
467: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
468: if (iascii) ascii->tab++;
469: return(0);
470: }
472: /*@C
473: PetscViewerASCIIPopTab - Removes one tab from the amount that PetscViewerASCIIPrintf()
474: lines are tabbed.
476: Not Collective, but only first processor in set has any effect
478: Input Parameters:
479: . viewer - obtained with PetscViewerASCIIOpen()
481: Level: developer
483: Fortran Note:
484: This routine is not supported in Fortran.
487: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
488: PetscViewerASCIIPushTab(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIOpen(),
489: PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer()
490: @*/
491: PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
492: {
493: PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
494: PetscErrorCode ierr;
495: PetscBool iascii;
499: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
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: return(0);
505: }
507: /*@
508: PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the ASCII PetscViewer
510: Not Collective, but only first processor in set has any effect
512: Input Parameters:
513: + viewer - obtained with PetscViewerASCIIOpen()
514: - flg - PETSC_TRUE or PETSC_FALSE
516: Level: developer
518: Fortran Note:
519: This routine is not supported in Fortran.
522: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
523: PetscViewerASCIIPopTab(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPushTab(), PetscViewerASCIIOpen(),
524: PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer()
525: @*/
526: PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer,PetscBool flg)
527: {
528: PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
529: PetscBool iascii;
530: PetscErrorCode ierr;
534: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
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: return(0);
543: }
545: /* ----------------------------------------------------------------------- */
548: /*@C
549: PetscViewerASCIIPrintf - Prints to a file, only from the first
550: processor in the PetscViewer
552: Not Collective, but only first processor in set has any effect
554: Input Parameters:
555: + viewer - obtained with PetscViewerASCIIOpen()
556: - format - the usual printf() format string
558: Level: developer
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.
564: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIOpen(),
565: PetscViewerASCIIPushTab(), PetscViewerASCIIPopTab(), PetscViewerASCIISynchronizedPrintf(),
566: PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer(), PetscViewerASCIIPushSynchronized()
567: @*/
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;
580: if (ascii->sviewer) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_WRONGSTATE,"Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
582: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
583: if (!iascii) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Not ASCII PetscViewer");
584: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
585: if (rank) return(0);
587: if (ascii->bviewer) { /* pass string up to parent viewer */
588: char *string;
589: va_list Argp;
590: size_t fullLength;
592: PetscCalloc1(QUEUESTRINGSIZE, &string);
593: va_start(Argp,format);
594: PetscVSNPrintf(string,QUEUESTRINGSIZE,format,&fullLength,Argp);
595: va_end(Argp);
596: PetscViewerASCIISynchronizedPrintf(viewer,"%s",string);
597: PetscFree(string);
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: PetscFPrintf(PETSC_COMM_SELF,fd,"%s",next->string);
605: previous = next;
606: next = next->next;
607: PetscFree(previous->string);
608: PetscFree(previous);
609: }
610: ascii->petsc_printfqueue = NULL;
611: ascii->petsc_printfqueuelength = 0;
612: tab = intab;
613: while (tab--) {
614: PetscFPrintf(PETSC_COMM_SELF,fd," ");
615: }
617: va_start(Argp,format);
618: (*PetscVFPrintf)(fd,format,Argp);
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: PetscFPrintf(PETSC_COMM_SELF,petsc_history," ");
626: }
627: (*PetscVFPrintf)(petsc_history,format,Argp);
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: return(0);
634: }
636: /*@C
637: PetscViewerFileSetName - Sets the name of the file the PetscViewer uses.
639: Collective on PetscViewer
641: Input Parameters:
642: + viewer - the PetscViewer; either ASCII or binary
643: - name - the name of the file it should use
645: Level: advanced
647: .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PetscViewerDestroy(),
648: PetscViewerASCIIGetPointer(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()
650: @*/
651: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer,const char name[])
652: {
654: char filename[PETSC_MAX_PATH_LEN];
659: PetscStrreplace(PetscObjectComm((PetscObject)viewer),name,filename,sizeof(filename));
660: PetscTryMethod(viewer,"PetscViewerFileSetName_C",(PetscViewer,const char[]),(viewer,filename));
661: return(0);
662: }
664: /*@C
665: PetscViewerFileGetName - Gets the name of the file the PetscViewer uses.
667: Not Collective
669: Input Parameter:
670: . viewer - the PetscViewer; either ASCII or binary
672: Output Parameter:
673: . name - the name of the file it is using
675: Level: advanced
677: .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PetscViewerFileSetName()
679: @*/
680: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer,const char **name)
681: {
687: PetscUseMethod(viewer,"PetscViewerFileGetName_C",(PetscViewer,const char**),(viewer,name));
688: return(0);
689: }
691: PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer,const char **name)
692: {
693: PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
696: *name = vascii->filename;
697: return(0);
698: }
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;
710: PetscViewerFileClose_ASCII(viewer);
711: if (!name) return(0);
712: PetscStrallocpy(name,&vascii->filename);
714: /* Is this file to be compressed */
715: vascii->storecompressed = PETSC_FALSE;
717: PetscStrstr(vascii->filename,".gz",&gz);
718: if (gz) {
719: PetscStrlen(gz,&len);
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: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
727: if (!rank) {
728: PetscStrcmp(name,"stderr",&isstderr);
729: PetscStrcmp(name,"stdout",&isstdout);
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 {
737: PetscFixFilename(name,fname);
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: fseek(vascii->fd, 0, SEEK_END);
760: }
761: break;
762: default:
763: SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[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: return(0);
772: }
774: PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer,MPI_Comm subcomm,PetscViewer *outviewer)
775: {
776: PetscErrorCode ierr;
777: PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data,*ovascii;
780: PetscViewerASCIIPushSynchronized(viewer);
781: if (vascii->sviewer) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"SubViewer already obtained from PetscViewer and not restored");
782: /*
783: The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
784: because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
785: (since the count never gets to zero) in some examples this displays information that otherwise would be lost
787: This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
788: PCView_GASM().
789: */
790: PetscViewerASCIIPushSynchronized(viewer);
791: PetscViewerCreate(subcomm,outviewer);
792: PetscViewerSetType(*outviewer,PETSCVIEWERASCII);
793: PetscViewerASCIIPushSynchronized(*outviewer);
794: ovascii = (PetscViewer_ASCII*)(*outviewer)->data;
795: ovascii->fd = vascii->fd;
796: ovascii->tab = vascii->tab;
797: ovascii->closefile = PETSC_FALSE;
799: vascii->sviewer = *outviewer;
800: (*outviewer)->format = viewer->format;
801: ((PetscViewer_ASCII*)((*outviewer)->data))->bviewer = viewer;
802: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer;
803: return(0);
804: }
806: PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
807: {
808: PetscErrorCode ierr;
809: PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
812: if (!ascii->sviewer) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"SubViewer never obtained from PetscViewer");
813: if (ascii->sviewer != *outviewer) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"This PetscViewer did not generate this SubViewer");
815: PetscViewerASCIIPopSynchronized(*outviewer);
816: ascii->sviewer = NULL;
817: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
818: PetscViewerDestroy(outviewer);
819: PetscViewerASCIIPopSynchronized(viewer);
820: return(0);
821: }
823: PetscErrorCode PetscViewerView_ASCII(PetscViewer v,PetscViewer viewer)
824: {
825: PetscErrorCode ierr;
826: PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)v->data;
829: if (ascii->filename) {
830: PetscViewerASCIIPrintf(viewer,"Filename: %s\n",ascii->filename);
831: }
832: return(0);
833: }
835: /*MC
836: PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file
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()
843: Level: beginner
845: M*/
846: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
847: {
848: PetscViewer_ASCII *vascii;
849: PetscErrorCode ierr;
852: PetscNewLog(viewer,&vascii);
853: viewer->data = (void*)vascii;
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;
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;
873: PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_ASCII);
874: PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",PetscViewerFileGetName_ASCII);
875: PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_ASCII);
876: PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_ASCII);
877: return(0);
878: }
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.
885: Not Collective, must call collective PetscViewerFlush() to get the results out
887: Input Parameters:
888: + viewer - the ASCII PetscViewer
889: - format - the usual printf() format string
891: Level: intermediate
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);
911: Fortran Note:
912: Can only print a single character* string
914: .seealso: PetscViewerASCIIPushSynchronized(), PetscViewerFlush(), PetscViewerASCIIPopSynchronized(),
915: PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIIOpen(),
916: PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType()
917: @*/
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;
932: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
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");
936: PetscObjectGetComm((PetscObject)viewer,&comm);
937: MPI_Comm_rank(comm,&rank);
939: if (vascii->bviewer) {
940: hasbviewer = PETSC_TRUE;
941: if (!rank) {
942: vascii = (PetscViewer_ASCII*)vascii->bviewer->data;
943: PetscObjectGetComm((PetscObject)viewer,&comm);
944: MPI_Comm_rank(comm,&rank);
945: }
946: }
948: fp = vascii->fd;
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: PetscFPrintf(comm,fp,"%s",next->string);
957: previous = next;
958: next = next->next;
959: PetscFree(previous->string);
960: PetscFree(previous);
961: }
962: vascii->petsc_printfqueue = NULL;
963: vascii->petsc_printfqueuelength = 0;
965: while (tab--) {
966: PetscFPrintf(PETSC_COMM_SELF,fp," ");
967: }
969: va_start(Argp,format);
970: (*PetscVFPrintf)(fp,format,Argp);
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: (*PetscVFPrintf)(petsc_history,format,Argp);
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;
986: PetscNew(&next);
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: PetscCalloc1(next->size, &next->string);
996: string = next->string;
997: tab *= 2;
998: while (tab--) {
999: *string++ = ' ';
1000: }
1001: va_start(Argp,format);
1002: PetscVSNPrintf(string,next->size-2*vascii->tab,format,&fullLength,Argp);
1003: va_end(Argp);
1004: if (fullLength > (size_t) (next->size-2*vascii->tab)) {
1005: PetscFree(next->string);
1006: next->size = fullLength + 2*vascii->tab;
1007: PetscCalloc1(next->size, &next->string);
1008: string = next->string;
1009: tab = 2*vascii->tab;
1010: while (tab--) {
1011: *string++ = ' ';
1012: }
1013: va_start(Argp,format);
1014: PetscVSNPrintf(string,next->size-2*vascii->tab,format,NULL,Argp);
1015: va_end(Argp);
1016: }
1017: }
1018: return(0);
1019: }
1021: /*@C
1022: PetscViewerASCIIRead - Reads from a ASCII file
1024: Only process 0 in the PetscViewer may call this
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
1032: Output Parameters:
1033: . count - number of items of data actually read, or NULL
1035: Level: beginner
1037: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerFileSetMode(), PetscViewerFileSetName()
1038: VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
1039: PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
1040: @*/
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;
1052: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
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: return(0);
1077: }