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:   PetscMPIInt        rank;
  9:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
 10:   int                err;

 13:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
 14:   if (rank == 0 && vascii->fd != stderr && vascii->fd != PETSC_STDOUT) {
 15:     if (vascii->fd && vascii->closefile) {
 16:       err = fclose(vascii->fd);
 18:     }
 19:     if (vascii->storecompressed) {
 20:       char  par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN];
 21:       FILE *fp;
 22:       PetscStrncpy(par, "gzip ", sizeof(par));
 23:       PetscStrlcat(par, vascii->filename, sizeof(par));
 24: #if defined(PETSC_HAVE_POPEN)
 25:       PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp);
 27:       PetscPClose(PETSC_COMM_SELF, fp);
 28: #else
 29:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
 30: #endif
 31:     }
 32:   }
 33:   PetscFree(vascii->filename);
 34:   return 0;
 35: }

 37: /* ----------------------------------------------------------------------*/
 38: PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
 39: {
 40:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
 41:   PetscViewerLink   *vlink;
 42:   PetscBool          flg;

 45:   PetscViewerFileClose_ASCII(viewer);
 46:   PetscFree(vascii);

 48:   /* remove the viewer from the list in the MPI Communicator */
 49:   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0);

 51:   MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg);
 52:   if (flg) {
 53:     if (vlink && vlink->viewer == viewer) {
 54:       if (vlink->next) {
 55:         MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next);
 56:       } else {
 57:         MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval);
 58:       }
 59:       PetscFree(vlink);
 60:     } else {
 61:       while (vlink && vlink->next) {
 62:         if (vlink->next->viewer == viewer) {
 63:           PetscViewerLink *nv = vlink->next;
 64:           vlink->next         = vlink->next->next;
 65:           PetscFree(nv);
 66:         }
 67:         vlink = vlink->next;
 68:       }
 69:     }
 70:   }

 72:   if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
 73:     PetscViewer aviewer;
 74:     MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, (PetscMPIInt *)&flg);
 75:     if (flg && aviewer == viewer) MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval);
 76:   }
 77:   if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
 78:     PetscViewer aviewer;
 79:     MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, (PetscMPIInt *)&flg);
 80:     if (flg && aviewer == viewer) MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval);
 81:   }
 82:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL);
 83:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL);
 84:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL);
 85:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL);
 86:   return 0;
 87: }

 89: PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
 90: {
 91:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

 93:   PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer);
 94:   return 0;
 95: }

 97: PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
 98: {
 99:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
100:   int                err;
101:   MPI_Comm           comm;
102:   PetscMPIInt        rank, size;
103:   FILE              *fd = vascii->fd;

106:   PetscObjectGetComm((PetscObject)viewer, &comm);
107:   MPI_Comm_rank(comm, &rank);
108:   MPI_Comm_size(comm, &size);

110:   if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) {
111:     err = fflush(vascii->fd);
113:   }

115:   if (vascii->allowsynchronized) {
116:     PetscMPIInt tag, i, j, n = 0, dummy = 0;
117:     char       *message;
118:     MPI_Status  status;

120:     PetscCommDuplicate(comm, &comm, &tag);

122:     /* First processor waits for messages from all other processors */
123:     if (rank == 0) {
124:       /* flush my own messages that I may have queued up */
125:       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
126:       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
127:         if (!vascii->bviewer) {
128:           PetscFPrintf(comm, fd, "%s", next->string);
129:         } else {
130:           PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string);
131:         }
132:         previous = next;
133:         next     = next->next;
134:         PetscFree(previous->string);
135:         PetscFree(previous);
136:       }
137:       vascii->petsc_printfqueue       = NULL;
138:       vascii->petsc_printfqueuelength = 0;
139:       for (i = 1; i < size; i++) {
140:         /* to prevent a flood of messages to process zero, request each message separately */
141:         MPI_Send(&dummy, 1, MPI_INT, i, tag, comm);
142:         MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status);
143:         for (j = 0; j < n; j++) {
144:           PetscMPIInt size = 0;

146:           MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status);
147:           PetscMalloc1(size, &message);
148:           MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status);
149:           if (!vascii->bviewer) {
150:             PetscFPrintf(comm, fd, "%s", message);
151:           } else {
152:             PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message);
153:           }
154:           PetscFree(message);
155:         }
156:       }
157:     } else { /* other processors send queue to processor 0 */
158:       PrintfQueue next = vascii->petsc_printfqueuebase, previous;

160:       MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status);
161:       MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm);
162:       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
163:         MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm);
164:         MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm);
165:         previous = next;
166:         next     = next->next;
167:         PetscFree(previous->string);
168:         PetscFree(previous);
169:       }
170:       vascii->petsc_printfqueue       = NULL;
171:       vascii->petsc_printfqueuelength = 0;
172:     }
173:     PetscCommDestroy(&comm);
174:   }
175:   return 0;
176: }

178: /*@C
179:     PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`.

181:     Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer

183:     Input Parameter:
184: .    viewer - PetscViewer context, obtained from `PetscViewerASCIIOpen()`

186:     Output Parameter:
187: .    fd - file pointer

189:     Level: intermediate

191:     Note:
192:     For the standard `PETSCVIEWERASCII` the value is valid only on process 0 of the viewer

194:     Fortran Note:
195:     This routine is not supported in Fortran.

197: .seealso: `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`,
198:           `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
199: @*/
200: PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
201: {
202:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

204:   *fd = vascii->fd;
205:   return 0;
206: }

208: PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
209: {
210:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

212:   *mode = vascii->mode;
213:   return 0;
214: }

216: PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
217: {
218:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

220:   vascii->mode = mode;
221:   return 0;
222: }

224: /*
225:    If petsc_history is on, then all Petsc*Printf() results are saved
226:    if the appropriate (usually .petschistory) file.
227: */
228: PETSC_INTERN FILE *petsc_history;

230: /*@
231:     PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times

233:     Not Collective, but only first processor in set has any effect

235:     Input Parameters:
236: +    viewer - obtained with `PetscViewerASCIIOpen()`
237: -    tabs - number of tabs

239:     Level: developer

241:     Fortran Note:
242:     This routine is not supported in Fortran.

244: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIGetTab()`,
245:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
246:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
247: @*/
248: PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
249: {
250:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
251:   PetscBool          iascii;

254:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
255:   if (iascii) ascii->tab = tabs;
256:   return 0;
257: }

259: /*@
260:     PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.

262:     Not Collective, meaningful on first processor only.

264:     Input Parameters:
265: .    viewer - obtained with `PetscViewerASCIIOpen()`

267:     Output Parameters:
268: .    tabs - number of tabs

270:     Level: developer

272:     Fortran Note:
273:     This routine is not supported in Fortran.

275: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISetTab()`,
276:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
277:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
278: @*/
279: PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
280: {
281:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
282:   PetscBool          iascii;

285:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
286:   if (iascii && tabs) *tabs = ascii->tab;
287:   return 0;
288: }

290: /*@
291:     PetscViewerASCIIAddTab - Add to the number of times an ASCII viewer tabs before printing

293:     Not Collective, but only first processor in set has any effect

295:     Input Parameters:
296: +    viewer - obtained with `PetscViewerASCIIOpen()`
297: -    tabs - number of tabs

299:     Level: developer

301:     Fortran Note:
302:     This routine is not supported in Fortran.

304: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
305:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
306:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
307: @*/
308: PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
309: {
310:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
311:   PetscBool          iascii;

314:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
315:   if (iascii) ascii->tab += tabs;
316:   return 0;
317: }

319: /*@
320:     PetscViewerASCIISubtractTab - Subtracts from the number of times an ASCII viewer tabs before printing

322:     Not Collective, but only first processor in set has any effect

324:     Input Parameters:
325: +    viewer - obtained with `PetscViewerASCIIOpen()`
326: -    tabs - number of tabs

328:     Level: developer

330:     Fortran Note:
331:     This routine is not supported in Fortran.

333: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
334:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
335:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
336: @*/
337: PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
338: {
339:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
340:   PetscBool          iascii;

343:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
344:   if (iascii) ascii->tab -= tabs;
345:   return 0;
346: }

348: /*@C
349:     PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer

351:     Collective on viewer

353:     Input Parameters:
354: .    viewer - obtained with `PetscViewerASCIIOpen()`

356:     Level: intermediate

358:     Note:
359:     See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.

361: .seealso: `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
362:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
363:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
364: @*/
365: PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
366: {
367:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
368:   PetscBool          iascii;

372:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
373:   if (iascii) ascii->allowsynchronized++;
374:   return 0;
375: }

377: /*@C
378:     PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer

380:     Collective on viewer

382:     Input Parameters:
383: .    viewer - obtained with `PetscViewerASCIIOpen()`

385:     Level: intermediate

387:     Note:
388:     See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.

390: .seealso: `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
391:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
392:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
393: @*/
394: PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
395: {
396:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
397:   PetscBool          iascii;

401:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
402:   if (iascii) {
403:     ascii->allowsynchronized--;
405:   }
406:   return 0;
407: }

409: /*@C
410:     PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
411:      lines are tabbed.

413:     Not Collective, but only first processor in set has any effect

415:     Input Parameters:
416: .    viewer - obtained with `PetscViewerASCIIOpen()`

418:     Level: developer

420:     Fortran Note:
421:     This routine is not supported in Fortran.

423: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
424:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
425:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
426: @*/
427: PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
428: {
429:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
430:   PetscBool          iascii;

433:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
434:   if (iascii) ascii->tab++;
435:   return 0;
436: }

438: /*@C
439:     PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by `PetscViewerASCIIPushTab()`

441:     Not Collective, but only first processor in set has any effect

443:     Input Parameters:
444: .    viewer - obtained with `PetscViewerASCIIOpen()`

446:     Level: developer

448:     Fortran Note:
449:     This routine is not supported in Fortran.

451: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
452:           `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
453:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
454: @*/
455: PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
456: {
457:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
458:   PetscBool          iascii;

461:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
462:   if (iascii) {
464:     ascii->tab--;
465:   }
466:   return 0;
467: }

469: /*@
470:     PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the ASCII `PetscViewer`

472:     Not Collective, but only first processor in set has any effect

474:     Input Parameters:
475: +    viewer - obtained with `PetscViewerASCIIOpen()`
476: -    flg - `PETSC_TRUE` or `PETSC_FALSE`

478:     Level: developer

480:     Fortran Note:
481:     This routine is not supported in Fortran.

483: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
484:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
485:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
486: @*/
487: PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
488: {
489:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
490:   PetscBool          iascii;

493:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
494:   if (iascii) {
495:     if (flg) ascii->tab = ascii->tab_store;
496:     else {
497:       ascii->tab_store = ascii->tab;
498:       ascii->tab       = 0;
499:     }
500:   }
501:   return 0;
502: }

504: /* ----------------------------------------------------------------------- */

506: /*@C
507:     PetscViewerASCIIPrintf - Prints to a file, only from the first
508:     processor in the PetscViewer

510:     Not Collective, but only first processor in set has any effect

512:     Input Parameters:
513: +    viewer - obtained with `PetscViewerASCIIOpen()`
514: -    format - the usual printf() format string

516:     Level: developer

518:     Fortran Note:
519:     The call sequence is `PetscViewerASCIIPrintf`(PetscViewer, character(*), int ierr) from Fortran.
520:     That is, you can only pass a single character string from Fortran.

522: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
523:           `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
524:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
525: @*/
526: PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
527: {
528:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
529:   PetscMPIInt        rank;
530:   PetscInt           tab, intab = ascii->tab;
531:   FILE              *fd = ascii->fd;
532:   PetscBool          iascii;
533:   int                err;

538:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
540:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
541:   if (rank) return 0;

543:   if (ascii->bviewer) { /* pass string up to parent viewer */
544:     char   *string;
545:     va_list Argp;
546:     size_t  fullLength;

548:     PetscCalloc1(QUEUESTRINGSIZE, &string);
549:     va_start(Argp, format);
550:     PetscVSNPrintf(string, QUEUESTRINGSIZE, format, &fullLength, Argp);
551:     va_end(Argp);
552:     PetscViewerASCIISynchronizedPrintf(viewer, "%s", string);
553:     PetscFree(string);
554:   } else { /* write directly to file */
555:     va_list Argp;
556:     /* flush my own messages that I may have queued up */
557:     PrintfQueue next = ascii->petsc_printfqueuebase, previous;
558:     PetscInt    i;
559:     for (i = 0; i < ascii->petsc_printfqueuelength; i++) {
560:       PetscFPrintf(PETSC_COMM_SELF, fd, "%s", next->string);
561:       previous = next;
562:       next     = next->next;
563:       PetscFree(previous->string);
564:       PetscFree(previous);
565:     }
566:     ascii->petsc_printfqueue       = NULL;
567:     ascii->petsc_printfqueuelength = 0;
568:     tab                            = intab;
569:     while (tab--) PetscFPrintf(PETSC_COMM_SELF, fd, "  ");

571:     va_start(Argp, format);
572:     (*PetscVFPrintf)(fd, format, Argp);
573:     err = fflush(fd);
575:     if (petsc_history) {
576:       va_start(Argp, format);
577:       tab = intab;
578:       while (tab--) PetscFPrintf(PETSC_COMM_SELF, petsc_history, "  ");
579:       (*PetscVFPrintf)(petsc_history, format, Argp);
580:       err = fflush(petsc_history);
582:     }
583:     va_end(Argp);
584:   }
585:   return 0;
586: }

588: /*@C
589:      PetscViewerFileSetName - Sets the name of the file the `PetscViewer` uses.

591:     Collective on viewer

593:   Input Parameters:
594: +  viewer - the PetscViewer; either `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
595: -  name - the name of the file it should use

597:     Level: advanced

599: .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
600:           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
601: @*/
602: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
603: {
604:   char filename[PETSC_MAX_PATH_LEN];

608:   PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename));
609:   PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
610:   return 0;
611: }

613: /*@C
614:      PetscViewerFileGetName - Gets the name of the file the `PetscViewer` uses.

616:     Not Collective

618:   Input Parameter:
619: .  viewer - the `PetscViewer`; either `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`

621:   Output Parameter:
622: .  name - the name of the file it is using

624:     Level: advanced

626: .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
627: @*/
628: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
629: {
632:   PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
633:   return 0;
634: }

636: PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
637: {
638:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

640:   *name = vascii->filename;
641:   return 0;
642: }

644: PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
645: {
646:   size_t             len;
647:   char               fname[PETSC_MAX_PATH_LEN], *gz;
648:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
649:   PetscBool          isstderr, isstdout;
650:   PetscMPIInt        rank;

652:   PetscViewerFileClose_ASCII(viewer);
653:   if (!name) return 0;
654:   PetscStrallocpy(name, &vascii->filename);

656:   /* Is this file to be compressed */
657:   vascii->storecompressed = PETSC_FALSE;

659:   PetscStrstr(vascii->filename, ".gz", &gz);
660:   if (gz) {
661:     PetscStrlen(gz, &len);
662:     if (len == 3) {
664:       *gz                     = 0;
665:       vascii->storecompressed = PETSC_TRUE;
666:     }
667:   }
668:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
669:   if (rank == 0) {
670:     PetscStrcmp(name, "stderr", &isstderr);
671:     PetscStrcmp(name, "stdout", &isstdout);
672:     /* empty filename means stdout */
673:     if (name[0] == 0) isstdout = PETSC_TRUE;
674:     if (isstderr) vascii->fd = PETSC_STDERR;
675:     else if (isstdout) vascii->fd = PETSC_STDOUT;
676:     else {
677:       PetscFixFilename(name, fname);
678:       switch (vascii->mode) {
679:       case FILE_MODE_READ:
680:         vascii->fd = fopen(fname, "r");
681:         break;
682:       case FILE_MODE_WRITE:
683:         vascii->fd = fopen(fname, "w");
684:         break;
685:       case FILE_MODE_APPEND:
686:         vascii->fd = fopen(fname, "a");
687:         break;
688:       case FILE_MODE_UPDATE:
689:         vascii->fd = fopen(fname, "r+");
690:         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
691:         break;
692:       case FILE_MODE_APPEND_UPDATE:
693:         /* I really want a file which is opened at the end for updating,
694:            not a+, which opens at the beginning, but makes writes at the end.
695:         */
696:         vascii->fd = fopen(fname, "r+");
697:         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
698:         else fseek(vascii->fd, 0, SEEK_END);
699:         break;
700:       default:
701:         SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
702:       }
704:     }
705:   }
706: #if defined(PETSC_USE_LOG)
707:   PetscLogObjectState((PetscObject)viewer, "File: %s", name);
708: #endif
709:   return 0;
710: }

712: PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
713: {
714:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;

716:   PetscViewerASCIIPushSynchronized(viewer);
718:   /*
719:      The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
720:      because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
721:      (since the count never gets to zero) in some examples this displays information that otherwise would be lost

723:      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
724:      PCView_GASM().
725:   */
726:   PetscViewerASCIIPushSynchronized(viewer);
727:   PetscViewerCreate(subcomm, outviewer);
728:   PetscViewerSetType(*outviewer, PETSCVIEWERASCII);
729:   PetscViewerASCIIPushSynchronized(*outviewer);
730:   ovascii            = (PetscViewer_ASCII *)(*outviewer)->data;
731:   ovascii->fd        = vascii->fd;
732:   ovascii->tab       = vascii->tab;
733:   ovascii->closefile = PETSC_FALSE;

735:   vascii->sviewer                                      = *outviewer;
736:   (*outviewer)->format                                 = viewer->format;
737:   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
738:   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
739:   return 0;
740: }

742: PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
743: {
744:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;


749:   PetscViewerASCIIPopSynchronized(*outviewer);
750:   ascii->sviewer             = NULL;
751:   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
752:   PetscViewerDestroy(outviewer);
753:   PetscViewerASCIIPopSynchronized(viewer);
754:   return 0;
755: }

757: PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
758: {
759:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;

761:   if (ascii->filename) PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename);
762:   return 0;
763: }

765: /*MC
766:    PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file

768:   Level: beginner

770: .seealso: `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
771:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
772:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
773: M*/
774: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
775: {
776:   PetscViewer_ASCII *vascii;

778:   PetscNew(&vascii);
779:   viewer->data = (void *)vascii;

781:   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
782:   viewer->ops->flush            = PetscViewerFlush_ASCII;
783:   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
784:   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
785:   viewer->ops->view             = PetscViewerView_ASCII;
786:   viewer->ops->read             = PetscViewerASCIIRead;

788:   /* defaults to stdout unless set with PetscViewerFileSetName() */
789:   vascii->fd        = PETSC_STDOUT;
790:   vascii->mode      = FILE_MODE_WRITE;
791:   vascii->bviewer   = NULL;
792:   vascii->subviewer = NULL;
793:   vascii->sviewer   = NULL;
794:   vascii->tab       = 0;
795:   vascii->tab_store = 0;
796:   vascii->filename  = NULL;
797:   vascii->closefile = PETSC_TRUE;

799:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII);
800:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII);
801:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII);
802:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII);
803:   return 0;
804: }

806: /*@C
807:     PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified file from
808:     several processors.  Output of the first processor is followed by that of the
809:     second, etc.

811:     Not Collective, must call collective `PetscViewerFlush()` to get the results out

813:     Input Parameters:
814: +   viewer - the `PETSCVIEWERASCII` `PetscViewer`
815: -   format - the usual printf() format string

817:     Level: intermediate

819:     Notes:
820:     You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
821:     Then you can do multiple independent calls to this routine.

823:     The actual synchronized print is then done using `PetscViewerFlush()`.
824:     `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
825:     to conclude the "synchronized session".

827:     So the typical calling sequence looks like
828: .vb
829:     PetscViewerASCIIPushSynchronized(viewer);
830:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
831:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
832:     ...
833:     PetscViewerFlush(viewer);
834:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
835:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
836:     ...
837:     PetscViewerFlush(viewer);
838:    PetscViewerASCIIPopSynchronized(viewer);
839: .ve

841:     Fortran Note:
842:       Can only print a single character* string

844: .seealso: `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
845:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
846:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
847: @*/
848: PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
849: {
850:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
851:   PetscMPIInt        rank;
852:   PetscInt           tab = vascii->tab;
853:   MPI_Comm           comm;
854:   FILE              *fp;
855:   PetscBool          iascii, hasbviewer = PETSC_FALSE;
856:   int                err;

860:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);

864:   PetscObjectGetComm((PetscObject)viewer, &comm);
865:   MPI_Comm_rank(comm, &rank);

867:   if (vascii->bviewer) {
868:     hasbviewer = PETSC_TRUE;
869:     if (rank == 0) {
870:       vascii = (PetscViewer_ASCII *)vascii->bviewer->data;
871:       PetscObjectGetComm((PetscObject)viewer, &comm);
872:       MPI_Comm_rank(comm, &rank);
873:     }
874:   }

876:   fp = vascii->fd;

878:   if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */
879:     va_list Argp;
880:     /* flush my own messages that I may have queued up */
881:     PrintfQueue next = vascii->petsc_printfqueuebase, previous;
882:     PetscInt    i;
883:     for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
884:       PetscFPrintf(comm, fp, "%s", next->string);
885:       previous = next;
886:       next     = next->next;
887:       PetscFree(previous->string);
888:       PetscFree(previous);
889:     }
890:     vascii->petsc_printfqueue       = NULL;
891:     vascii->petsc_printfqueuelength = 0;

893:     while (tab--) PetscFPrintf(PETSC_COMM_SELF, fp, "  ");

895:     va_start(Argp, format);
896:     (*PetscVFPrintf)(fp, format, Argp);
897:     err = fflush(fp);
899:     if (petsc_history) {
900:       va_start(Argp, format);
901:       (*PetscVFPrintf)(petsc_history, format, Argp);
902:       err = fflush(petsc_history);
904:     }
905:     va_end(Argp);
906:   } else { /* other processors add to queue */
907:     char       *string;
908:     va_list     Argp;
909:     size_t      fullLength;
910:     PrintfQueue next;

912:     PetscNew(&next);
913:     if (vascii->petsc_printfqueue) {
914:       vascii->petsc_printfqueue->next = next;
915:       vascii->petsc_printfqueue       = next;
916:     } else {
917:       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
918:     }
919:     vascii->petsc_printfqueuelength++;
920:     next->size = QUEUESTRINGSIZE;
921:     PetscCalloc1(next->size, &next->string);
922:     string = next->string;
923:     tab *= 2;
924:     while (tab--) *string++ = ' ';
925:     va_start(Argp, format);
926:     PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp);
927:     va_end(Argp);
928:     if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
929:       PetscFree(next->string);
930:       next->size = fullLength + 2 * vascii->tab;
931:       PetscCalloc1(next->size, &next->string);
932:       string = next->string;
933:       tab    = 2 * vascii->tab;
934:       while (tab--) *string++ = ' ';
935:       va_start(Argp, format);
936:       PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp);
937:       va_end(Argp);
938:     }
939:   }
940:   return 0;
941: }

943: /*@C
944:    PetscViewerASCIIRead - Reads from a ASCII file

946:    Only process 0 in the `PetscViewer` may call this

948:    Input Parameters:
949: +  viewer - the ascii viewer
950: .  data - location to write the data
951: .  num - number of items of data to read
952: -  datatype - type of data to read

954:    Output Parameters:
955: .  count - number of items of data actually read, or NULL

957:    Level: beginner

959: .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
960:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
961:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
962: @*/
963: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
964: {
965:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
966:   FILE              *fd     = vascii->fd;
967:   PetscInt           i;
968:   int                ret = 0;
969:   PetscMPIInt        rank;

972:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
974:   for (i = 0; i < num; i++) {
975:     if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
976:     else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
977:     else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
978:     else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
979:     else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
980:     else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
981:     else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
982:     else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
983: #if defined(PETSC_USE_REAL___FLOAT128)
984:     else if (dtype == PETSC___FLOAT128) {
985:       double tmp;
986:       ret                     = fscanf(fd, "%lg", &tmp);
987:       ((__float128 *)data)[i] = tmp;
988:     }
989: #endif
990:     else
991:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
993:     if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
994:   }
995:   if (count) *count = i;
997:   return 0;
998: }