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; No Fortran Support

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: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`,
195:           `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
196: @*/
197: PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
198: {
199:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

201:   *fd = vascii->fd;
202:   return 0;
203: }

205: PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
206: {
207:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

209:   *mode = vascii->mode;
210:   return 0;
211: }

213: PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
214: {
215:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

217:   vascii->mode = mode;
218:   return 0;
219: }

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

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

230:     Not Collective, but only first processor in set has any effect; No Fortran Support

232:     Input Parameters:
233: +    viewer - obtained with `PetscViewerASCIIOpen()`
234: -    tabs - number of tabs

236:     Level: developer

238: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIGetTab()`,
239:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
240:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
241: @*/
242: PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
243: {
244:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
245:   PetscBool          iascii;

248:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
249:   if (iascii) ascii->tab = tabs;
250:   return 0;
251: }

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

256:     Not Collective, meaningful on first processor only; No Fortran Support

258:     Input Parameters:
259: .    viewer - obtained with `PetscViewerASCIIOpen()`

261:     Output Parameters:
262: .    tabs - number of tabs

264:     Level: developer

266: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISetTab()`,
267:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
268:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
269: @*/
270: PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
271: {
272:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
273:   PetscBool          iascii;

276:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
277:   if (iascii && tabs) *tabs = ascii->tab;
278:   return 0;
279: }

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

284:     Not Collective, but only first processor in set has any effect; No Fortran Support

286:     Input Parameters:
287: +    viewer - obtained with `PetscViewerASCIIOpen()`
288: -    tabs - number of tabs

290:     Level: developer

292: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
293:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
294:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
295: @*/
296: PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
297: {
298:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
299:   PetscBool          iascii;

302:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
303:   if (iascii) ascii->tab += tabs;
304:   return 0;
305: }

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

310:     Not Collective, but only first processor in set has any effect; No Fortran Support

312:     Input Parameters:
313: +    viewer - obtained with `PetscViewerASCIIOpen()`
314: -    tabs - number of tabs

316:     Level: developer

318: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
319:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
320:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
321: @*/
322: PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
323: {
324:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
325:   PetscBool          iascii;

328:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
329:   if (iascii) ascii->tab -= tabs;
330:   return 0;
331: }

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

336:     Collective

338:     Input Parameters:
339: .    viewer - obtained with `PetscViewerASCIIOpen()`

341:     Level: intermediate

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

346: .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
347:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
348:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
349: @*/
350: PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
351: {
352:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
353:   PetscBool          iascii;

357:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
358:   if (iascii) ascii->allowsynchronized++;
359:   return 0;
360: }

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

365:     Collective

367:     Input Parameters:
368: .    viewer - obtained with `PetscViewerASCIIOpen()`

370:     Level: intermediate

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

375: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
376:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
377:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
378: @*/
379: PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
380: {
381:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
382:   PetscBool          iascii;

386:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
387:   if (iascii) {
388:     ascii->allowsynchronized--;
390:   }
391:   return 0;
392: }

394: /*@C
395:     PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
396:      lines are tabbed.

398:     Not Collective, but only first processor in set has any effect; No Fortran Support

400:     Input Parameters:
401: .    viewer - obtained with `PetscViewerASCIIOpen()`

403:     Level: developer

405: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
406:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
407:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
408: @*/
409: PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
410: {
411:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
412:   PetscBool          iascii;

415:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
416:   if (iascii) ascii->tab++;
417:   return 0;
418: }

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

423:     Not Collective, but only first processor in set has any effect; No Fortran Support

425:     Input Parameters:
426: .    viewer - obtained with `PetscViewerASCIIOpen()`

428:     Level: developer

430: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
431:           `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
432:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
433: @*/
434: PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
435: {
436:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
437:   PetscBool          iascii;

440:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
441:   if (iascii) {
443:     ascii->tab--;
444:   }
445:   return 0;
446: }

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

451:     Not Collective, but only first processor in set has any effect; No Fortran Support

453:     Input Parameters:
454: +    viewer - obtained with `PetscViewerASCIIOpen()`
455: -    flg - `PETSC_TRUE` or `PETSC_FALSE`

457:     Level: developer

459: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
460:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
461:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
462: @*/
463: PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
464: {
465:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
466:   PetscBool          iascii;

469:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
470:   if (iascii) {
471:     if (flg) ascii->tab = ascii->tab_store;
472:     else {
473:       ascii->tab_store = ascii->tab;
474:       ascii->tab       = 0;
475:     }
476:   }
477:   return 0;
478: }

480: /* ----------------------------------------------------------------------- */

482: /*@C
483:     PetscViewerASCIIPrintf - Prints to a file, only from the first
484:     processor in the PetscViewer

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

488:     Input Parameters:
489: +    viewer - obtained with `PetscViewerASCIIOpen()`
490: -    format - the usual printf() format string

492:     Level: developer

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

498: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
499:           `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
500:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
501: @*/
502: PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
503: {
504:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
505:   PetscMPIInt        rank;
506:   PetscInt           tab, intab = ascii->tab;
507:   FILE              *fd = ascii->fd;
508:   PetscBool          iascii;
509:   int                err;

514:   PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
516:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
517:   if (rank) return 0;

519:   if (ascii->bviewer) { /* pass string up to parent viewer */
520:     char   *string;
521:     va_list Argp;
522:     size_t  fullLength;

524:     PetscCalloc1(QUEUESTRINGSIZE, &string);
525:     va_start(Argp, format);
526:     PetscVSNPrintf(string, QUEUESTRINGSIZE, format, &fullLength, Argp);
527:     va_end(Argp);
528:     PetscViewerASCIISynchronizedPrintf(viewer, "%s", string);
529:     PetscFree(string);
530:   } else { /* write directly to file */
531:     va_list Argp;
532:     /* flush my own messages that I may have queued up */
533:     PrintfQueue next = ascii->petsc_printfqueuebase, previous;
534:     PetscInt    i;
535:     for (i = 0; i < ascii->petsc_printfqueuelength; i++) {
536:       PetscFPrintf(PETSC_COMM_SELF, fd, "%s", next->string);
537:       previous = next;
538:       next     = next->next;
539:       PetscFree(previous->string);
540:       PetscFree(previous);
541:     }
542:     ascii->petsc_printfqueue       = NULL;
543:     ascii->petsc_printfqueuelength = 0;
544:     tab                            = intab;
545:     while (tab--) PetscFPrintf(PETSC_COMM_SELF, fd, "  ");

547:     va_start(Argp, format);
548:     (*PetscVFPrintf)(fd, format, Argp);
549:     err = fflush(fd);
551:     if (petsc_history) {
552:       va_start(Argp, format);
553:       tab = intab;
554:       while (tab--) PetscFPrintf(PETSC_COMM_SELF, petsc_history, "  ");
555:       (*PetscVFPrintf)(petsc_history, format, Argp);
556:       err = fflush(petsc_history);
558:     }
559:     va_end(Argp);
560:   }
561:   return 0;
562: }

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

567:     Collective

569:   Input Parameters:
570: +  viewer - the PetscViewer; either `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
571: -  name - the name of the file it should use

573:     Level: advanced

575: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
576:           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
577: @*/
578: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
579: {
580:   char filename[PETSC_MAX_PATH_LEN];

584:   PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename));
585:   PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
586:   return 0;
587: }

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

592:     Not Collective

594:   Input Parameter:
595: .  viewer - the `PetscViewer`; either `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`

597:   Output Parameter:
598: .  name - the name of the file it is using

600:     Level: advanced

602: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
603: @*/
604: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
605: {
608:   PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
609:   return 0;
610: }

612: PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
613: {
614:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

616:   *name = vascii->filename;
617:   return 0;
618: }

620: PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
621: {
622:   size_t             len;
623:   char               fname[PETSC_MAX_PATH_LEN], *gz;
624:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
625:   PetscBool          isstderr, isstdout;
626:   PetscMPIInt        rank;

628:   PetscViewerFileClose_ASCII(viewer);
629:   if (!name) return 0;
630:   PetscStrallocpy(name, &vascii->filename);

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

635:   PetscStrstr(vascii->filename, ".gz", &gz);
636:   if (gz) {
637:     PetscStrlen(gz, &len);
638:     if (len == 3) {
640:       *gz                     = 0;
641:       vascii->storecompressed = PETSC_TRUE;
642:     }
643:   }
644:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
645:   if (rank == 0) {
646:     PetscStrcmp(name, "stderr", &isstderr);
647:     PetscStrcmp(name, "stdout", &isstdout);
648:     /* empty filename means stdout */
649:     if (name[0] == 0) isstdout = PETSC_TRUE;
650:     if (isstderr) vascii->fd = PETSC_STDERR;
651:     else if (isstdout) vascii->fd = PETSC_STDOUT;
652:     else {
653:       PetscFixFilename(name, fname);
654:       switch (vascii->mode) {
655:       case FILE_MODE_READ:
656:         vascii->fd = fopen(fname, "r");
657:         break;
658:       case FILE_MODE_WRITE:
659:         vascii->fd = fopen(fname, "w");
660:         break;
661:       case FILE_MODE_APPEND:
662:         vascii->fd = fopen(fname, "a");
663:         break;
664:       case FILE_MODE_UPDATE:
665:         vascii->fd = fopen(fname, "r+");
666:         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
667:         break;
668:       case FILE_MODE_APPEND_UPDATE:
669:         /* I really want a file which is opened at the end for updating,
670:            not a+, which opens at the beginning, but makes writes at the end.
671:         */
672:         vascii->fd = fopen(fname, "r+");
673:         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
674:         else fseek(vascii->fd, 0, SEEK_END);
675:         break;
676:       default:
677:         SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
678:       }
680:     }
681:   }
682: #if defined(PETSC_USE_LOG)
683:   PetscLogObjectState((PetscObject)viewer, "File: %s", name);
684: #endif
685:   return 0;
686: }

688: PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
689: {
690:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;

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

699:      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
700:      PCView_GASM().
701:   */
702:   PetscViewerASCIIPushSynchronized(viewer);
703:   PetscViewerCreate(subcomm, outviewer);
704:   PetscViewerSetType(*outviewer, PETSCVIEWERASCII);
705:   PetscViewerASCIIPushSynchronized(*outviewer);
706:   ovascii            = (PetscViewer_ASCII *)(*outviewer)->data;
707:   ovascii->fd        = vascii->fd;
708:   ovascii->tab       = vascii->tab;
709:   ovascii->closefile = PETSC_FALSE;

711:   vascii->sviewer                                      = *outviewer;
712:   (*outviewer)->format                                 = viewer->format;
713:   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
714:   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
715:   return 0;
716: }

718: PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
719: {
720:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;


725:   PetscViewerASCIIPopSynchronized(*outviewer);
726:   ascii->sviewer             = NULL;
727:   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
728:   PetscViewerDestroy(outviewer);
729:   PetscViewerASCIIPopSynchronized(viewer);
730:   return 0;
731: }

733: PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
734: {
735:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;

737:   if (ascii->filename) PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename);
738:   return 0;
739: }

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

744:   Level: beginner

746: .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
747:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
748:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
749: M*/
750: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
751: {
752:   PetscViewer_ASCII *vascii;

754:   PetscNew(&vascii);
755:   viewer->data = (void *)vascii;

757:   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
758:   viewer->ops->flush            = PetscViewerFlush_ASCII;
759:   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
760:   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
761:   viewer->ops->view             = PetscViewerView_ASCII;
762:   viewer->ops->read             = PetscViewerASCIIRead;

764:   /* defaults to stdout unless set with PetscViewerFileSetName() */
765:   vascii->fd        = PETSC_STDOUT;
766:   vascii->mode      = FILE_MODE_WRITE;
767:   vascii->bviewer   = NULL;
768:   vascii->subviewer = NULL;
769:   vascii->sviewer   = NULL;
770:   vascii->tab       = 0;
771:   vascii->tab_store = 0;
772:   vascii->filename  = NULL;
773:   vascii->closefile = PETSC_TRUE;

775:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII);
776:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII);
777:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII);
778:   PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII);
779:   return 0;
780: }

782: /*@C
783:     PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified file from
784:     several processors.  Output of the first processor is followed by that of the
785:     second, etc.

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

789:     Input Parameters:
790: +   viewer - the `PETSCVIEWERASCII` `PetscViewer`
791: -   format - the usual printf() format string

793:     Level: intermediate

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

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

803:     So the typical calling sequence looks like
804: .vb
805:     PetscViewerASCIIPushSynchronized(viewer);
806:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
807:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
808:     ...
809:     PetscViewerFlush(viewer);
810:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
811:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
812:     ...
813:     PetscViewerFlush(viewer);
814:    PetscViewerASCIIPopSynchronized(viewer);
815: .ve

817:     Fortran Note:
818:       Can only print a single character* string

820: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
821:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
822:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
823: @*/
824: PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
825: {
826:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
827:   PetscMPIInt        rank;
828:   PetscInt           tab = vascii->tab;
829:   MPI_Comm           comm;
830:   FILE              *fp;
831:   PetscBool          iascii, hasbviewer = PETSC_FALSE;
832:   int                err;

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

840:   PetscObjectGetComm((PetscObject)viewer, &comm);
841:   MPI_Comm_rank(comm, &rank);

843:   if (vascii->bviewer) {
844:     hasbviewer = PETSC_TRUE;
845:     if (rank == 0) {
846:       vascii = (PetscViewer_ASCII *)vascii->bviewer->data;
847:       PetscObjectGetComm((PetscObject)viewer, &comm);
848:       MPI_Comm_rank(comm, &rank);
849:     }
850:   }

852:   fp = vascii->fd;

854:   if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */
855:     va_list Argp;
856:     /* flush my own messages that I may have queued up */
857:     PrintfQueue next = vascii->petsc_printfqueuebase, previous;
858:     PetscInt    i;
859:     for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
860:       PetscFPrintf(comm, fp, "%s", next->string);
861:       previous = next;
862:       next     = next->next;
863:       PetscFree(previous->string);
864:       PetscFree(previous);
865:     }
866:     vascii->petsc_printfqueue       = NULL;
867:     vascii->petsc_printfqueuelength = 0;

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

871:     va_start(Argp, format);
872:     (*PetscVFPrintf)(fp, format, Argp);
873:     err = fflush(fp);
875:     if (petsc_history) {
876:       va_start(Argp, format);
877:       (*PetscVFPrintf)(petsc_history, format, Argp);
878:       err = fflush(petsc_history);
880:     }
881:     va_end(Argp);
882:   } else { /* other processors add to queue */
883:     char       *string;
884:     va_list     Argp;
885:     size_t      fullLength;
886:     PrintfQueue next;

888:     PetscNew(&next);
889:     if (vascii->petsc_printfqueue) {
890:       vascii->petsc_printfqueue->next = next;
891:       vascii->petsc_printfqueue       = next;
892:     } else {
893:       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
894:     }
895:     vascii->petsc_printfqueuelength++;
896:     next->size = QUEUESTRINGSIZE;
897:     PetscCalloc1(next->size, &next->string);
898:     string = next->string;
899:     tab *= 2;
900:     while (tab--) *string++ = ' ';
901:     va_start(Argp, format);
902:     PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp);
903:     va_end(Argp);
904:     if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
905:       PetscFree(next->string);
906:       next->size = fullLength + 2 * vascii->tab;
907:       PetscCalloc1(next->size, &next->string);
908:       string = next->string;
909:       tab    = 2 * vascii->tab;
910:       while (tab--) *string++ = ' ';
911:       va_start(Argp, format);
912:       PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp);
913:       va_end(Argp);
914:     }
915:   }
916:   return 0;
917: }

919: /*@C
920:    PetscViewerASCIIRead - Reads from a ASCII file

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

924:    Input Parameters:
925: +  viewer - the ascii viewer
926: .  data - location to write the data
927: .  num - number of items of data to read
928: -  datatype - type of data to read

930:    Output Parameters:
931: .  count - number of items of data actually read, or NULL

933:    Level: beginner

935: .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
936:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
937:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
938: @*/
939: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
940: {
941:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
942:   FILE              *fd     = vascii->fd;
943:   PetscInt           i;
944:   int                ret = 0;
945:   PetscMPIInt        rank;

948:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
950:   for (i = 0; i < num; i++) {
951:     if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
952:     else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
953:     else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
954:     else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
955:     else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
956:     else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
957:     else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
958:     else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
959: #if defined(PETSC_USE_REAL___FLOAT128)
960:     else if (dtype == PETSC___FLOAT128) {
961:       double tmp;
962:       ret                     = fscanf(fd, "%lg", &tmp);
963:       ((__float128 *)data)[i] = tmp;
964:     }
965: #endif
966:     else
967:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
969:     if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
970:   }
971:   if (count) *count = i;
973:   return 0;
974: }