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:   PetscBool          flg;

 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, (PetscMPIInt *)&flg));
 52:   if (flg) {
 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, (PetscMPIInt *)&flg));
 75:     if (flg && 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, (PetscMPIInt *)&flg));
 80:     if (flg && 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          iascii;

176:   PetscFunctionBegin;
178:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
179:   if (iascii) 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          iascii;

206:   PetscFunctionBegin;
208:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
209:   if (iascii && 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          iascii;

236:   PetscFunctionBegin;
238:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
239:   if (iascii) 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          iascii;

267:   PetscFunctionBegin;
269:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
270:   if (iascii) 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          iascii;

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, &iascii));
300:   if (iascii) 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          iascii;

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, &iascii));
330:   if (iascii) {
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          iascii;

357:   PetscFunctionBegin;
359:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
360:   if (iascii) 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          iascii;

384:   PetscFunctionBegin;
386:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
387:   if (iascii) {
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          iascii;

414:   PetscFunctionBegin;
416:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
417:   if (iascii) {
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/fortranimpl.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:   PetscBool flg;
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, (PetscMPIInt *)&flg));
646:   if (!flg) { /* 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:       PetscCall(PetscViewerCreate(ncomm, viewer));
658:       PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
659:       PetscCall(PetscViewerFileSetName(*viewer, "stdout"));
660:     }
661:     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
662:     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer));
663:   }
664:   PetscCall(PetscCommDestroy(&ncomm));
665:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout));
666: #if defined(PETSC_USE_FORTRAN_BINDINGS)
667:   ((PetscViewer_ASCII *)(*viewer)->data)->fileunit = PETSC_VIEWER_ASCII_STDOUT_fileunit;
668: #endif
669:   PetscFunctionReturn(PETSC_SUCCESS);
670: }

672: /*@C
673:   PetscViewerASCIIPrintf - Prints to a file, only from the first
674:   processor in the `PetscViewer` of type `PETSCVIEWERASCII`

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

678:   Input Parameters:
679: + viewer - obtained with `PetscViewerASCIIOpen()`
680: - format - the usual printf() format string

682:   Level: developer

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

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

700:   PetscFunctionBegin;
702:   PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
703:   PetscAssertPointer(format, 2);
704:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
705:   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
706:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
707:   if (rank) PetscFunctionReturn(PETSC_SUCCESS);

709:   if (ascii->bviewer) { /* pass string up to parent viewer */
710:     char   *string;
711:     va_list Argp;
712:     size_t  fullLength;

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

724:     tab = intab;
725:     while (tab--) {
726:       if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "  "));
727:       else PetscCall(PetscFPrintfFortran(ascii->fileunit, "   "));
728:     }

730:     va_start(Argp, format);
731:     if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
732:     else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
733:     va_end(Argp);
734:     PetscCall(PetscFFlush(fd));
735:   }
736:   PetscFunctionReturn(PETSC_SUCCESS);
737: }

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

742:   Collective

744:   Input Parameters:
745: + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
746: - name   - the name of the file it should use

748:   Level: advanced

750:   Note:
751:   This will have no effect on viewers that are not related to files

753: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
754:           `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
755: @*/
756: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
757: {
758:   char filename[PETSC_MAX_PATH_LEN];

760:   PetscFunctionBegin;
762:   PetscAssertPointer(name, 2);
763:   PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
764:   PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
765:   PetscFunctionReturn(PETSC_SUCCESS);
766: }

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

771:   Not Collective

773:   Input Parameter:
774: . viewer - the `PetscViewer`

776:   Output Parameter:
777: . name - the name of the file it is using

779:   Level: advanced

781:   Note:
782:   This will have no effect on viewers that are not related to files

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

795: static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
796: {
797:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

799:   PetscFunctionBegin;
800:   *name = vascii->filename;
801:   PetscFunctionReturn(PETSC_SUCCESS);
802: }

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

813:   PetscFunctionBegin;
814:   PetscCall(PetscViewerFileClose_ASCII(viewer));
815:   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
816:   PetscCall(PetscStrallocpy(name, &vascii->filename));

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

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

875: static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
876: {
877:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;

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

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

900:   vascii->sviewer                                      = *outviewer;
901:   (*outviewer)->format                                 = viewer->format;
902:   ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
903:   (*outviewer)->ops->destroy                           = PetscViewerDestroy_ASCII_SubViewer;
904:   PetscFunctionReturn(PETSC_SUCCESS);
905: }

907: static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
908: {
909:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;

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

915:   PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
916:   ascii->sviewer             = NULL;
917:   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
918:   PetscCall(PetscViewerDestroy(outviewer));
919:   PetscCall(PetscViewerFlush(viewer));
920:   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
921:   PetscFunctionReturn(PETSC_SUCCESS);
922: }

924: static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
925: {
926:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;

928:   PetscFunctionBegin;
929:   if (ascii->fileunit) PetscCall(PetscViewerASCIIPrintf(viewer, "Fortran FILE UNIT: %d\n", ascii->fileunit));
930:   else if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
931:   PetscFunctionReturn(PETSC_SUCCESS);
932: }

934: static PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
935: {
936:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
937:   MPI_Comm           comm;
938:   PetscMPIInt        rank, size;
939:   FILE              *fd = vascii->fd;

941:   PetscFunctionBegin;
942:   PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
943:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
944:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
945:   PetscCallMPI(MPI_Comm_size(comm, &size));

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

949:   if (vascii->allowsynchronized) {
950:     PetscMPIInt tag, i, j, n = 0, dummy = 0;
951:     char       *message;
952:     MPI_Status  status;

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

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

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

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

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

1017:   Level: beginner

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

1027:   PetscFunctionBegin;
1028:   PetscCall(PetscNew(&vascii));
1029:   viewer->data = (void *)vascii;

1031:   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
1032:   viewer->ops->flush            = PetscViewerFlush_ASCII;
1033:   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
1034:   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
1035:   viewer->ops->view             = PetscViewerView_ASCII;
1036:   viewer->ops->read             = PetscViewerASCIIRead;

1038:   /* defaults to stdout unless set with PetscViewerFileSetName() */
1039:   vascii->fd        = PETSC_STDOUT;
1040:   vascii->mode      = FILE_MODE_WRITE;
1041:   vascii->bviewer   = NULL;
1042:   vascii->subviewer = NULL;
1043:   vascii->sviewer   = NULL;
1044:   vascii->tab       = 0;
1045:   vascii->tab_store = 0;
1046:   vascii->filename  = NULL;
1047:   vascii->closefile = PETSC_TRUE;

1049:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
1050:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
1051:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
1052:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
1053:   PetscFunctionReturn(PETSC_SUCCESS);
1054: }

1056: /*@C
1057:   PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
1058:   several processors.  Output of the first processor is followed by that of the
1059:   second, etc.

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

1063:   Input Parameters:
1064: + viewer - the `PETSCVIEWERASCII` `PetscViewer`
1065: - format - the usual printf() format string

1067:   Level: intermediate

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

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

1077:   So the typical calling sequence looks like
1078: .vb
1079:     PetscViewerASCIIPushSynchronized(viewer);
1080:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1081:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1082:     ...
1083:     PetscViewerFlush(viewer);
1084:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1085:     PetscViewerASCIISynchronizedPrintf(viewer, ...);
1086:     ...
1087:     PetscViewerFlush(viewer);
1088:     PetscViewerASCIIPopSynchronized(viewer);
1089: .ve

1091:   Fortran Notes:
1092:   Can only print a single character* string

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

1106:   PetscFunctionBegin;
1108:   PetscAssertPointer(format, 2);
1109:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1110:   PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
1111:   PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");

1113:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1114:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

1116:   if (vascii->bviewer) {
1117:     char   *string;
1118:     va_list Argp;
1119:     size_t  fullLength;

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

1132:     tab = vascii->tab;
1133:     while (tab--) {
1134:       if (!vascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, "  "));
1135:       else PetscCall(PetscFPrintfFortran(vascii->fileunit, "   "));
1136:     }

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

1155:     PetscCall(PetscNew(&next));
1156:     if (vascii->petsc_printfqueue) {
1157:       vascii->petsc_printfqueue->next = next;
1158:       vascii->petsc_printfqueue       = next;
1159:     } else {
1160:       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1161:     }
1162:     vascii->petsc_printfqueuelength++;
1163:     next->size = QUEUESTRINGSIZE;
1164:     PetscCall(PetscCalloc1(next->size, &next->string));
1165:     string = next->string;

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

1188: /*@C
1189:   PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file

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

1193:   Input Parameters:
1194: + viewer - the `PETSCVIEWERASCII` viewer
1195: . data   - location to write the data, treated as an array of type indicated by `datatype`
1196: . num    - number of items of data to read
1197: - dtype  - type of data to read

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

1202:   Level: beginner

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

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