Actual source code: filev.c

  1: #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h>

  3: #define QUEUESTRINGSIZE 8192

  5: static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer)
  6: {
  7:   PetscMPIInt        rank;
  8:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
  9:   int                err;

 11:   PetscFunctionBegin;
 12:   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
 13:   PetscCallMPI(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);
 17:       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
 18:     }
 19:     if (vascii->storecompressed) {
 20:       char  par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN];
 21:       FILE *fp;
 22:       PetscCall(PetscStrncpy(par, "gzip ", sizeof(par)));
 23:       PetscCall(PetscStrlcat(par, vascii->filename, sizeof(par)));
 24: #if defined(PETSC_HAVE_POPEN)
 25:       PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp));
 26:       PetscCheck(!fgets(buf, 1024, fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from compression command %s %s", par, buf);
 27:       PetscCall(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:   PetscCall(PetscFree(vascii->filename));
 34:   PetscFunctionReturn(PETSC_SUCCESS);
 35: }

 37: static PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
 38: {
 39:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
 40:   PetscViewerLink   *vlink;
 41:   PetscMPIInt        iflg;

 43:   PetscFunctionBegin;
 44:   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
 45:   PetscCall(PetscViewerFileClose_ASCII(viewer));
 46:   PetscCall(PetscFree(vascii));

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

 51:   PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, &iflg));
 52:   if (iflg) {
 53:     if (vlink && vlink->viewer == viewer) {
 54:       if (vlink->next) {
 55:         PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next));
 56:       } else {
 57:         PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval));
 58:       }
 59:       PetscCall(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:           PetscCall(PetscFree(nv));
 66:         }
 67:         vlink = vlink->next;
 68:       }
 69:     }
 70:   }

 72:   if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
 73:     PetscViewer aviewer;
 74:     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, &iflg));
 75:     if (iflg && aviewer == viewer) PetscCallMPI(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:     PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, &iflg));
 80:     if (iflg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval));
 81:   }
 82:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
 83:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
 84:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
 85:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
 86:   PetscFunctionReturn(PETSC_SUCCESS);
 87: }

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

 93:   PetscFunctionBegin;
 94:   PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer));
 95:   PetscFunctionReturn(PETSC_SUCCESS);
 96: }

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

101:   Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer; No Fortran Support

103:   Input Parameter:
104: . viewer - `PetscViewer` context, obtained from `PetscViewerASCIIOpen()`

106:   Output Parameter:
107: . fd - file pointer

109:   Level: intermediate

111:   Note:
112:   For the standard `PETSCVIEWERASCII` the value is valid only on MPI rank 0 of the viewer

114: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`,
115:           `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
116: @*/
117: PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
118: {
119:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

121:   PetscFunctionBegin;
122:   PetscCheck(!vascii->fileunit, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot request file pointer for viewers that use Fortran files");
123:   *fd = vascii->fd;
124:   PetscFunctionReturn(PETSC_SUCCESS);
125: }

127: static PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
128: {
129:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

131:   PetscFunctionBegin;
132:   *mode = vascii->mode;
133:   PetscFunctionReturn(PETSC_SUCCESS);
134: }

136: static PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
137: {
138:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

140:   PetscFunctionBegin;
141:   vascii->mode = mode;
142:   PetscFunctionReturn(PETSC_SUCCESS);
143: }

145: /*
146:    If petsc_history is on, then all Petsc*Printf() results are saved
147:    if the appropriate (usually .petschistory) file.
148: */
149: PETSC_INTERN FILE *petsc_history;

151: /*@
152:   PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times before printing

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

156:   Input Parameters:
157: + viewer - obtained with `PetscViewerASCIIOpen()`
158: - tabs   - number of tabs

160:   Level: developer

162:   Note:
163:   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage

165: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
166:           `PetscViewerASCIIGetTab()`,
167:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
168:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
169:           `PetscViewerASCIIPushTab()`
170: @*/
171: PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
172: {
173:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
174:   PetscBool          isascii;

176:   PetscFunctionBegin;
178:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
179:   if (isascii) ascii->tab = tabs;
180:   PetscFunctionReturn(PETSC_SUCCESS);
181: }

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

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

188:   Input Parameter:
189: . viewer - obtained with `PetscViewerASCIIOpen()`

191:   Output Parameter:
192: . tabs - number of tabs

194:   Level: developer

196: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
197:           `PetscViewerASCIISetTab()`,
198:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
199:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
200: @*/
201: PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
202: {
203:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
204:   PetscBool          isascii;

206:   PetscFunctionBegin;
208:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
209:   if (isascii && tabs) *tabs = ascii->tab;
210:   PetscFunctionReturn(PETSC_SUCCESS);
211: }

213: /*@
214:   PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing

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

218:   Input Parameters:
219: + viewer - obtained with `PetscViewerASCIIOpen()`
220: - tabs   - number of tabs

222:   Level: developer

224:   Note:
225:   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage

227: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
228:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
229:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
230: @*/
231: PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
232: {
233:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
234:   PetscBool          isascii;

236:   PetscFunctionBegin;
238:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
239:   if (isascii) ascii->tab += tabs;
240:   PetscFunctionReturn(PETSC_SUCCESS);
241: }

243: /*@
244:   PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing

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

248:   Input Parameters:
249: + viewer - obtained with `PetscViewerASCIIOpen()`
250: - tabs   - number of tabs

252:   Level: developer

254:   Note:
255:   `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage

257: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
258:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
259:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
260:           `PetscViewerASCIIPushTab()`
261: @*/
262: PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
263: {
264:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
265:   PetscBool          isascii;

267:   PetscFunctionBegin;
269:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
270:   if (isascii) ascii->tab -= tabs;
271:   PetscFunctionReturn(PETSC_SUCCESS);
272: }

274: /*@
275:   PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer

277:   Collective

279:   Input Parameter:
280: . viewer - obtained with `PetscViewerASCIIOpen()`

282:   Level: intermediate

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

287: .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
288:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
289:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
290: @*/
291: PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
292: {
293:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
294:   PetscBool          isascii;

296:   PetscFunctionBegin;
298:   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
299:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
300:   if (isascii) ascii->allowsynchronized++;
301:   PetscFunctionReturn(PETSC_SUCCESS);
302: }

304: /*@
305:   PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer

307:   Collective

309:   Input Parameter:
310: . viewer - obtained with `PetscViewerASCIIOpen()`

312:   Level: intermediate

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

317: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
318:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
319:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
320: @*/
321: PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
322: {
323:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
324:   PetscBool          isascii;

326:   PetscFunctionBegin;
328:   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
329:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
330:   if (isascii) {
331:     ascii->allowsynchronized--;
332:     PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()");
333:   }
334:   PetscFunctionReturn(PETSC_SUCCESS);
335: }

337: /*@
338:   PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
339:   lines are tabbed.

341:   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support

343:   Input Parameter:
344: . viewer - obtained with `PetscViewerASCIIOpen()`

346:   Level: developer

348: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
349:           `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
350:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
351: @*/
352: PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
353: {
354:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
355:   PetscBool          isascii;

357:   PetscFunctionBegin;
359:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
360:   if (isascii) ascii->tab++;
361:   PetscFunctionReturn(PETSC_SUCCESS);
362: }

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

368:   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support

370:   Input Parameter:
371: . viewer - obtained with `PetscViewerASCIIOpen()`

373:   Level: developer

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

384:   PetscFunctionBegin;
386:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
387:   if (isascii) {
388:     PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed");
389:     ascii->tab--;
390:   }
391:   PetscFunctionReturn(PETSC_SUCCESS);
392: }

394: /*@
395:   PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer`

397:   Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support

399:   Input Parameters:
400: + viewer - obtained with `PetscViewerASCIIOpen()`
401: - flg    - `PETSC_TRUE` or `PETSC_FALSE`

403:   Level: developer

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

414:   PetscFunctionBegin;
416:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
417:   if (isascii) {
418:     if (flg) ascii->tab = ascii->tab_store;
419:     else {
420:       ascii->tab_store = ascii->tab;
421:       ascii->tab       = 0;
422:     }
423:   }
424:   PetscFunctionReturn(PETSC_SUCCESS);
425: }

427: #if defined(PETSC_USE_FORTRAN_BINDINGS)

429:   #if defined(PETSC_HAVE_FORTRAN_CAPS)
430:     #define petscviewerasciiopenwithfileunit_  PETSCVIEWERASCIIOPENWITHFILEUNIT
431:     #define petscviewerasciisetfileunit_       PETSCVIEWERASCIISETFILEUNIT
432:     #define petscviewerasciistdoutsetfileunit_ PETSCVIEWERASCIISTDOUTSETFILEUNIT
433:     #define petscfortranprinttofileunit_       PETSCFORTRANPRINTTOFILEUNIT
434:   #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
435:     #define petscviewerasciiopenwithfileunit_  petscviewerasciiopenwithfileunit
436:     #define petscviewerasciisetfileunit_       petscviewerasciisetfileunit
437:     #define petscviewerasciistdoutsetfileunit_ petscviewerasciistdoutsetfileunit
438:     #define petscfortranprinttofileunit_       petscfortranprinttofileunit
439:   #endif

441:   #if defined(__cplusplus)
442: extern "C" void petscfortranprinttofileunit_(int *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
443:   #else
444: extern void petscfortranprinttofileunit_(int *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
445:   #endif

447:   #define PETSCDEFAULTBUFFERSIZE 8 * 1024

449: static int PETSC_VIEWER_ASCII_STDOUT_fileunit = 0;

451: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
452: /*MC
453:   PetscViewerASCIIStdoutSetFileUnit - sets `PETSC_VIEWER_STDOUT_()` to write to a Fortran IO unit

455:   Synopsis:
456: #include <petscviewer.h>
457:   void PetscViewerASCIIStdoutSetFileUnit(PetscInt unit, PetscErrorCode ierr)

459:   Input Parameter:
460: . unit - the unit number

462:   Output Parameter:
463: . ierr - the error code

465:   Level: intermediate

467:   Notes:
468:   Can be called before `PetscInitialize()`

470:   Immediately changes the output for all `PETSC_VIEWER_STDOUT_()` viewers

472:   This may not work currently with some viewers that (improperly) use the `fd` directly instead of `PetscViewerASCIIPrintf()`

474:   With this option, for example, `-log_options` results will be saved to the Fortran file

476:   Any process may call this but only the unit passed on the first process is used

478:   Fortran Note:
479:   Only for Fortran

481:   Developer Note:
482:   `PetscViewerASCIIWORLDSetFilename()` and `PetscViewerASCIIWORLDSetFILE()` could be added

484: .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIStdoutSetFileUnit()`,
485:           `PETSC_VIEWER_STDOUT_()`, `PetscViewerASCIIGetStdout()`
486: M*/
487: PETSC_EXTERN void petscviewerasciistdoutsetfileunit_(int *unit, PetscErrorCode *ierr)
488: {
489:   #if defined(PETSC_USE_FORTRAN_BINDINGS)
490:   PETSC_VIEWER_ASCII_STDOUT_fileunit = *unit;
491:   #endif
492: }

494: #include <petsc/private/ftnimpl.h>

496: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
497: /*MC
498:   PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` `PetscViewer` to write to a Fortran IO unit

500:   Synopsis:
501: #include <petscviewer.h>
502:   void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr)

504:   Input Parameters:
505: + lab  - the viewer
506: - unit - the unit number

508:   Output Parameter:
509: . ierr - the error code

511:   Level: intermediate

513:   Note:
514:   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`

516:   Fortran Notes:
517:   Only for Fortran, use  `PetscViewerASCIISetFILE()` for C

519: .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIStdoutSetFileUnit()`
520: M*/
521: PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, int *unit, PetscErrorCode *ierr)
522: {
523:   PetscViewer_ASCII *vascii;
524:   PetscViewer        v;

526:   PetscPatchDefaultViewers_Fortran(lab, v);
527:   vascii = (PetscViewer_ASCII *)v->data;
528:   if (vascii->mode == FILE_MODE_READ) {
529:     *ierr = PETSC_ERR_ARG_WRONGSTATE;
530:     return;
531:   }
532:   vascii->fileunit = *unit;
533: }

535: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
536: /*MC
537:   PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit

539:   Synopsis:
540: #include <petscviewer.h>
541:   void PetscViewerASCIIOpenWithFileUnit((MPI_Fint comm, integer unit, PetscViewer viewer, PetscErrorCode ierr)

543:   Input Parameters:
544: + comm - the `MPI_Comm` to share the viewer
545: - unit - the unit number

547:   Output Parameters:
548: + lab  - the viewer
549: - ierr - the error code

551:   Level: intermediate

553:   Note:
554:   `PetscViewerDestroy()` does not close the unit for this `PetscViewer`

556:   Fortran Notes:
557:   Only for Fortran, use  `PetscViewerASCIIOpenWithFILE()` for C

559: .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()`
560: M*/
561: PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Fint *comm, int *unit, PetscViewer *lab, PetscErrorCode *ierr)
562: {
563:   *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab);
564:   if (*ierr) return;
565:   *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII);
566:   if (*ierr) return;
567:   *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE);
568:   if (*ierr) return;
569:   petscviewerasciisetfileunit_(lab, unit, ierr);
570: }

572: static PetscErrorCode PetscVFPrintfFortran(int unit, const char format[], va_list Argp)
573: {
574:   PetscErrorCode ierr;
575:   char           str[PETSCDEFAULTBUFFERSIZE];
576:   size_t         len;

578:   PetscFunctionBegin;
579:   PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp));
580:   PetscCall(PetscStrlen(str, &len));
581:   petscfortranprinttofileunit_(&unit, str, &ierr, (int)len);
582:   PetscFunctionReturn(PETSC_SUCCESS);
583: }

585: static PetscErrorCode PetscFPrintfFortran(int unit, const char str[])
586: {
587:   PetscErrorCode ierr;
588:   size_t         len;

590:   PetscFunctionBegin;
591:   PetscCall(PetscStrlen(str, &len));
592:   petscfortranprinttofileunit_(&unit, str, &ierr, (int)len);
593:   PetscFunctionReturn(PETSC_SUCCESS);
594: }

596: #else

598: /* these will never be used; but are needed to link with */
599: static PetscErrorCode PetscVFPrintfFortran(int unit, const char format[], va_list Argp)
600: {
601:   PetscFunctionBegin;
602:   PetscFunctionReturn(PETSC_SUCCESS);
603: }

605: static PetscErrorCode PetscFPrintfFortran(int unit, const char str[])
606: {
607:   PetscFunctionBegin;
608:   PetscFunctionReturn(PETSC_SUCCESS);
609: }
610: #endif

612: /*@
613:   PetscViewerASCIIGetStdout - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processes
614:   in a communicator that prints to `stdout`. Error returning version of `PETSC_VIEWER_STDOUT_()`

616:   Collective

618:   Input Parameter:
619: . comm - the MPI communicator to share the `PetscViewer`

621:   Output Parameter:
622: . viewer - the viewer

624:   Level: beginner

626:   Note:
627:   Use `PetscViewerDestroy()` to destroy it

629:   Developer Note:
630:   This should be used in all PETSc source code instead of `PETSC_VIEWER_STDOUT_()` since it allows error checking

632: .seealso: [](sec_viewers), `PetscViewerASCIIGetStderr()`, `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
633:           `PETSC_VIEWER_STDOUT_SELF`
634: @*/
635: PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm, PetscViewer *viewer)
636: {
637:   PetscMPIInt iflg;
638:   MPI_Comm    ncomm;

640:   PetscFunctionBegin;
641:   PetscAssertPointer(viewer, 2);
642:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout));
643:   PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
644:   if (Petsc_Viewer_Stdout_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Stdout_keyval, NULL));
645:   PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, &iflg));
646:   if (!iflg) { /* PetscViewer not yet created */
647: #if defined(PETSC_USE_FORTRAN_BINDINGS)
648:     PetscCallMPI(MPI_Bcast(&PETSC_VIEWER_ASCII_STDOUT_fileunit, 1, MPI_INT, 0, comm));
649:     if (PETSC_VIEWER_ASCII_STDOUT_fileunit) {
650:       PetscErrorCode ierr;
651:       MPI_Fint       fcomm = MPI_Comm_c2f(ncomm);

653:       petscviewerasciiopenwithfileunit_(&fcomm, &PETSC_VIEWER_ASCII_STDOUT_fileunit, viewer, &ierr);
654:     } else
655: #endif
656:     {
657:       PetscViewerFormat format;
658:       PetscBool         set;

660:       PetscCall(PetscViewerCreate(ncomm, viewer));
661:       PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
662:       PetscCall(PetscOptionsGetEnum(NULL, NULL, "-petsc_viewer_stdout_format", PetscViewerFormats, (PetscEnum *)&format, &set));
663:       if (set) PetscCall(PetscViewerPushFormat(*viewer, format));
664:       PetscCall(PetscViewerFileSetName(*viewer, "stdout"));
665:     }
666:     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
667:     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer));
668:   }
669:   PetscCall(PetscCommDestroy(&ncomm));
670:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout));
671: #if defined(PETSC_USE_FORTRAN_BINDINGS)
672:   ((PetscViewer_ASCII *)(*viewer)->data)->fileunit = PETSC_VIEWER_ASCII_STDOUT_fileunit;
673: #endif
674:   PetscFunctionReturn(PETSC_SUCCESS);
675: }

677: /*@C
678:   PetscViewerASCIIPrintf - Prints to a file, only from the first
679:   processor in the `PetscViewer` of type `PETSCVIEWERASCII`

681:   Not Collective, but only the first MPI rank in the viewer has any effect

683:   Input Parameters:
684: + viewer - obtained with `PetscViewerASCIIOpen()`
685: - format - the usual printf() format string

687:   Level: developer

689:   Fortran Notes:
690:   The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran.
691:   That is, you can only pass a single character string from Fortran.

693: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
694:           `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
695:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
696: @*/
697: PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
698: {
699:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
700:   PetscMPIInt        rank;
701:   PetscInt           tab = 0, intab = ascii->tab;
702:   FILE              *fd = ascii->fd;
703:   PetscBool          isascii;

705:   PetscFunctionBegin;
707:   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
708:   PetscAssertPointer(format, 2);
709:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
710:   PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
711:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
712:   if (rank) PetscFunctionReturn(PETSC_SUCCESS);

714:   if (ascii->bviewer) { /* pass string up to parent viewer */
715:     char   *string;
716:     va_list Argp;
717:     size_t  fullLength;

719:     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
720:     for (; tab < ascii->tab; tab++) string[2 * tab] = string[2 * tab + 1] = ' ';
721:     va_start(Argp, format);
722:     PetscCall(PetscVSNPrintf(string + 2 * intab, QUEUESTRINGSIZE - 2 * intab, format, &fullLength, Argp));
723:     va_end(Argp);
724:     PetscCall(PetscViewerASCIISynchronizedPrintf(ascii->bviewer, "%s", string));
725:     PetscCall(PetscFree(string));
726:   } else { /* write directly to file */
727:     va_list Argp;

729:     tab = intab;
730:     while (tab--) {
731:       if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "  "));
732:       else PetscCall(PetscFPrintfFortran(ascii->fileunit, "   "));
733:     }

735:     va_start(Argp, format);
736:     if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
737:     else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
738:     va_end(Argp);
739:     PetscCall(PetscFFlush(fd));
740:   }
741:   PetscFunctionReturn(PETSC_SUCCESS);
742: }

744: /*@
745:   PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.

747:   Collective

749:   Input Parameters:
750: + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
751: - name   - the name of the file it should use

753:   Level: advanced

755:   Note:
756:   This will have no effect on viewers that are not related to files

758: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
759:           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
760: @*/
761: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
762: {
763:   char filename[PETSC_MAX_PATH_LEN];

765:   PetscFunctionBegin;
767:   PetscAssertPointer(name, 2);
768:   PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
769:   PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
770:   PetscFunctionReturn(PETSC_SUCCESS);
771: }

773: /*@C
774:   PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using

776:   Not Collective

778:   Input Parameter:
779: . viewer - the `PetscViewer`

781:   Output Parameter:
782: . name - the name of the file it is using

784:   Level: advanced

786:   Note:
787:   This will have no effect on viewers that are not related to files

789: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
790: @*/
791: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char *name[])
792: {
793:   PetscFunctionBegin;
795:   PetscAssertPointer(name, 2);
796:   PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
797:   PetscFunctionReturn(PETSC_SUCCESS);
798: }

800: static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
801: {
802:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

804:   PetscFunctionBegin;
805:   *name = vascii->filename;
806:   PetscFunctionReturn(PETSC_SUCCESS);
807: }

809: #include <errno.h>
810: static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
811: {
812:   size_t             len;
813:   char               fname[PETSC_MAX_PATH_LEN], *gz = NULL;
814:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
815:   PetscBool          isstderr, isstdout;
816:   PetscMPIInt        rank;

818:   PetscFunctionBegin;
819:   PetscCall(PetscViewerFileClose_ASCII(viewer));
820:   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
821:   PetscCall(PetscStrallocpy(name, &vascii->filename));

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

826:   PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
827:   if (gz) {
828:     PetscCall(PetscStrlen(gz, &len));
829:     if (len == 3) {
830:       PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first");
831:       *gz                     = 0;
832:       vascii->storecompressed = PETSC_TRUE;
833:     }
834:   }
835:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
836:   if (rank == 0) {
837:     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
838:     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
839:     /* empty filename means stdout */
840:     if (name[0] == 0) isstdout = PETSC_TRUE;
841:     if (isstderr) vascii->fd = PETSC_STDERR;
842:     else if (isstdout) vascii->fd = PETSC_STDOUT;
843:     else {
844:       PetscCall(PetscFixFilename(name, fname));
845:       switch (vascii->mode) {
846:       case FILE_MODE_READ:
847:         vascii->fd = fopen(fname, "r");
848:         break;
849:       case FILE_MODE_WRITE:
850:         vascii->fd = fopen(fname, "w");
851:         break;
852:       case FILE_MODE_APPEND:
853:         vascii->fd = fopen(fname, "a");
854:         break;
855:       case FILE_MODE_UPDATE:
856:         vascii->fd = fopen(fname, "r+");
857:         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
858:         break;
859:       case FILE_MODE_APPEND_UPDATE:
860:         /* I really want a file which is opened at the end for updating,
861:            not a+, which opens at the beginning, but makes writes at the end.
862:         */
863:         vascii->fd = fopen(fname, "r+");
864:         if (!vascii->fd) vascii->fd = fopen(fname, "w+");
865:         else {
866:           int ret = fseek(vascii->fd, 0, SEEK_END);
867:           PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
868:         }
869:         break;
870:       default:
871:         SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
872:       }
873:       PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
874:     }
875:   }
876:   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
877:   PetscFunctionReturn(PETSC_SUCCESS);
878: }

880: static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
881: {
882:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;

884:   PetscFunctionBegin;
885:   PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
886:   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
887:   /*
888:      The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
889:      because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
890:      (since the count never gets to zero) in some examples this displays information that otherwise would be lost

892:      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
893:      PCView_GASM().
894:   */
895:   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
896:   PetscCall(PetscViewerFlush(viewer));
897:   PetscCall(PetscViewerCreate(subcomm, outviewer));
898:   PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
899:   PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
900:   ovascii            = (PetscViewer_ASCII *)(*outviewer)->data;
901:   ovascii->fd        = vascii->fd;
902:   ovascii->fileunit  = vascii->fileunit;
903:   ovascii->closefile = PETSC_FALSE;

905:   vascii->sviewer                                      = *outviewer;
906:   (*outviewer)->format                                 = viewer->format;
907:   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
908:   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
909:   PetscFunctionReturn(PETSC_SUCCESS);
910: }

912: static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
913: {
914:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;

916:   PetscFunctionBegin;
917:   PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
918:   PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");

920:   PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
921:   ascii->sviewer             = NULL;
922:   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
923:   PetscCall(PetscViewerDestroy(outviewer));
924:   PetscCall(PetscViewerFlush(viewer));
925:   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
926:   PetscFunctionReturn(PETSC_SUCCESS);
927: }

929: static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
930: {
931:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;

933:   PetscFunctionBegin;
934:   if (ascii->fileunit) PetscCall(PetscViewerASCIIPrintf(viewer, "Fortran FILE UNIT: %d\n", ascii->fileunit));
935:   else if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
936:   PetscFunctionReturn(PETSC_SUCCESS);
937: }

939: static PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
940: {
941:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
942:   MPI_Comm           comm;
943:   PetscMPIInt        rank, size;
944:   FILE              *fd = vascii->fd;

946:   PetscFunctionBegin;
947:   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
948:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
949:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
950:   PetscCallMPI(MPI_Comm_size(comm, &size));

952:   if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd));

954:   if (vascii->allowsynchronized) {
955:     PetscMPIInt tag, i, j, n = 0, dummy = 0;
956:     char       *message;
957:     MPI_Status  status;

959:     PetscCall(PetscCommDuplicate(comm, &comm, &tag));

961:     /* First processor waits for messages from all other processors */
962:     if (rank == 0) {
963:       /* flush my own messages that I may have queued up */
964:       PrintfQueue next = vascii->petsc_printfqueuebase, previous;
965:       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
966:         if (!vascii->bviewer) {
967:           if (!vascii->fileunit) PetscCall(PetscFPrintf(comm, fd, "%s", next->string));
968:           else PetscCall(PetscFPrintfFortran(vascii->fileunit, next->string));
969:         } else {
970:           PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string));
971:         }
972:         previous = next;
973:         next     = next->next;
974:         PetscCall(PetscFree(previous->string));
975:         PetscCall(PetscFree(previous));
976:       }
977:       vascii->petsc_printfqueue       = NULL;
978:       vascii->petsc_printfqueuelength = 0;
979:       for (i = 1; i < size; i++) {
980:         /* to prevent a flood of messages to process zero, request each message separately */
981:         PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
982:         PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
983:         for (j = 0; j < n; j++) {
984:           size_t size;

986:           PetscCallMPI(MPI_Recv(&size, 1, MPIU_SIZE_T, i, tag, comm, &status));
987:           PetscCall(PetscMalloc1(size, &message));
988:           PetscCallMPI(MPI_Recv(message, (PetscMPIInt)size, MPI_CHAR, i, tag, comm, &status));
989:           if (!vascii->bviewer) {
990:             if (!vascii->fileunit) PetscCall(PetscFPrintf(comm, fd, "%s", message));
991:             else PetscCall(PetscFPrintfFortran(vascii->fileunit, message));
992:           } else {
993:             PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message));
994:           }
995:           PetscCall(PetscFree(message));
996:         }
997:       }
998:     } else { /* other processors send queue to processor 0 */
999:       PrintfQueue next = vascii->petsc_printfqueuebase, previous;

1001:       PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
1002:       PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
1003:       for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
1004:         PetscCallMPI(MPI_Send(&next->size, 1, MPIU_SIZE_T, 0, tag, comm));
1005:         PetscCallMPI(MPI_Send(next->string, (PetscMPIInt)next->size, MPI_CHAR, 0, tag, comm));
1006:         previous = next;
1007:         next     = next->next;
1008:         PetscCall(PetscFree(previous->string));
1009:         PetscCall(PetscFree(previous));
1010:       }
1011:       vascii->petsc_printfqueue       = NULL;
1012:       vascii->petsc_printfqueuelength = 0;
1013:     }
1014:     PetscCall(PetscCommDestroy(&comm));
1015:   }
1016:   PetscFunctionReturn(PETSC_SUCCESS);
1017: }

1019: /*MC
1020:    PETSCVIEWERASCII - A viewer that prints to `stdout`, `stderr`, or an ASCII file

1022:   Level: beginner

1024: .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1025:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
1026:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
1027: M*/
1028: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
1029: {
1030:   PetscViewer_ASCII *vascii;

1032:   PetscFunctionBegin;
1033:   PetscCall(PetscNew(&vascii));
1034:   viewer->data = (void *)vascii;

1036:   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
1037:   viewer->ops->flush            = PetscViewerFlush_ASCII;
1038:   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
1039:   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
1040:   viewer->ops->view             = PetscViewerView_ASCII;
1041:   viewer->ops->read             = PetscViewerASCIIRead;

1043:   /* defaults to stdout unless set with PetscViewerFileSetName() */
1044:   vascii->fd        = PETSC_STDOUT;
1045:   vascii->mode      = FILE_MODE_WRITE;
1046:   vascii->bviewer   = NULL;
1047:   vascii->subviewer = NULL;
1048:   vascii->sviewer   = NULL;
1049:   vascii->tab       = 0;
1050:   vascii->tab_store = 0;
1051:   vascii->filename  = NULL;
1052:   vascii->closefile = PETSC_TRUE;

1054:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
1055:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
1056:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
1057:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
1058:   PetscFunctionReturn(PETSC_SUCCESS);
1059: }

1061: /*@C
1062:   PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
1063:   several processors.  Output of the first processor is followed by that of the
1064:   second, etc.

1066:   Not Collective, must call collective `PetscViewerFlush()` to get the results flushed

1068:   Input Parameters:
1069: + viewer - the `PETSCVIEWERASCII` `PetscViewer`
1070: - format - the usual printf() format string

1072:   Level: intermediate

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

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

1082:   So the typical calling sequence looks like
1083: .vb
1084:     PetscViewerASCIIPushSynchronized(viewer);
1085:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1086:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1087:     ...
1088:     PetscViewerFlush(viewer);
1089:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1090:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1091:     ...
1092:     PetscViewerFlush(viewer);
1093:     PetscViewerASCIIPopSynchronized(viewer);
1094: .ve

1096:   Fortran Notes:
1097:   Can only print a single character* string

1099: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
1100:           `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
1101:           `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
1102: @*/
1103: PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
1104: {
1105:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1106:   PetscMPIInt        rank;
1107:   PetscInt           tab = 0;
1108:   MPI_Comm           comm;
1109:   PetscBool          isascii;

1111:   PetscFunctionBegin;
1113:   PetscAssertPointer(format, 2);
1114:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1115:   PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
1116:   PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");

1118:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1119:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

1121:   if (vascii->bviewer) {
1122:     char   *string;
1123:     va_list Argp;
1124:     size_t  fullLength;

1126:     PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
1127:     for (; tab < vascii->tab; tab++) string[2 * tab] = string[2 * tab + 1] = ' ';
1128:     va_start(Argp, format);
1129:     PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp));
1130:     va_end(Argp);
1131:     PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string));
1132:     PetscCall(PetscFree(string));
1133:   } else if (rank == 0) { /* First processor prints immediately to fp */
1134:     va_list Argp;
1135:     FILE   *fp = vascii->fd;

1137:     tab = vascii->tab;
1138:     while (tab--) {
1139:       if (!vascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, "  "));
1140:       else PetscCall(PetscFPrintfFortran(vascii->fileunit, "   "));
1141:     }

1143:     va_start(Argp, format);
1144:     if (!vascii->fileunit) PetscCall((*PetscVFPrintf)(fp, format, Argp));
1145:     else PetscCall(PetscVFPrintfFortran(vascii->fileunit, format, Argp));
1146:     va_end(Argp);
1147:     PetscCall(PetscFFlush(fp));
1148:     if (petsc_history) {
1149:       va_start(Argp, format);
1150:       PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1151:       va_end(Argp);
1152:       PetscCall(PetscFFlush(petsc_history));
1153:     }
1154:   } else { /* other processors add to queue */
1155:     char       *string;
1156:     va_list     Argp;
1157:     size_t      fullLength;
1158:     PrintfQueue next;

1160:     PetscCall(PetscNew(&next));
1161:     if (vascii->petsc_printfqueue) {
1162:       vascii->petsc_printfqueue->next = next;
1163:       vascii->petsc_printfqueue       = next;
1164:     } else {
1165:       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1166:     }
1167:     vascii->petsc_printfqueuelength++;
1168:     next->size = QUEUESTRINGSIZE;
1169:     PetscCall(PetscCalloc1(next->size, &next->string));
1170:     string = next->string;

1172:     tab = vascii->tab;
1173:     tab *= 2;
1174:     while (tab--) *string++ = ' ';
1175:     va_start(Argp, format);
1176:     PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
1177:     va_end(Argp);
1178:     if (fullLength > next->size - 2 * vascii->tab) {
1179:       PetscCall(PetscFree(next->string));
1180:       next->size = fullLength + 2 * vascii->tab;
1181:       PetscCall(PetscCalloc1(next->size, &next->string));
1182:       string = next->string;
1183:       tab    = 2 * vascii->tab;
1184:       while (tab--) *string++ = ' ';
1185:       va_start(Argp, format);
1186:       PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
1187:       va_end(Argp);
1188:     }
1189:   }
1190:   PetscFunctionReturn(PETSC_SUCCESS);
1191: }

1193: /*@C
1194:   PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file

1196:   Only MPI rank 0 in the `PetscViewer` may call this

1198:   Input Parameters:
1199: + viewer - the `PETSCVIEWERASCII` viewer
1200: . data   - location to write the data, treated as an array of type indicated by `datatype`
1201: . num    - number of items of data to read
1202: - dtype  - type of data to read

1204:   Output Parameter:
1205: . count - number of items of data actually read, or `NULL`

1207:   Level: beginner

1209: .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1210:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1211:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1212: @*/
1213: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1214: {
1215:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1216:   FILE              *fd     = vascii->fd;
1217:   PetscInt           i;
1218:   int                ret = 0;
1219:   PetscMPIInt        rank;

1221:   PetscFunctionBegin;
1223:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1224:   PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1225:   for (i = 0; i < num; i++) {
1226:     if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1227:     else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1228:     else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1229:     else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
1230:     else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1231:     else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1232:     else if (dtype == PETSC_COUNT) ret = fscanf(fd, "%" PetscCount_FMT, &(((PetscCount *)data)[i]));
1233:     else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1234:     else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1235: #if defined(PETSC_USE_REAL___FLOAT128)
1236:     else if (dtype == PETSC___FLOAT128) {
1237:       double tmp;
1238:       ret                     = fscanf(fd, "%lg", &tmp);
1239:       ((__float128 *)data)[i] = tmp;
1240:     }
1241: #endif
1242:     else
1243:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
1244:     PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1245:     if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
1246:   }
1247:   if (count) *count = i;
1248:   else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
1249:   PetscFunctionReturn(PETSC_SUCCESS);
1250: }