Date: 2026-03-31T05:46:29+00:00

Actual source code: petscvu.c

      1: #include <petsc/private/viewerimpl.h>

      3: #define QUEUESTRINGSIZE 1024

      5: typedef struct _PrintfQueue *PrintfQueue;
      6: struct _PrintfQueue {
      7:   char        string[QUEUESTRINGSIZE];
      8:   PrintfQueue next;
      9: };

     11: typedef struct {
     12:   FILE         *fd;
     13:   PetscFileMode mode; /* The mode in which to open the file */
     14:   char         *filename;
     15:   PetscBool     vecSeen; /* The flag indicating whether any vector has been viewed so far */
     16:   PrintfQueue   queue, queueBase;
     17:   int           queueLength;
     18: } PetscViewer_VU;

     20: static PetscErrorCode PetscViewerFileClose_VU(PetscViewer viewer)
     21: {
     22:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

     24:   PetscFunctionBegin;
     25:   if (vu->vecSeen) PetscCall(PetscViewerVUPrintDeferred(viewer, "};\n\n"));
     26:   PetscCall(PetscViewerVUFlushDeferred(viewer));
     27:   PetscCall(PetscFClose(PetscObjectComm((PetscObject)viewer), vu->fd));
     28:   vu->fd = NULL;
     29:   PetscCall(PetscFree(vu->filename));
     30:   PetscFunctionReturn(PETSC_SUCCESS);
     31: }

     33: static PetscErrorCode PetscViewerDestroy_VU(PetscViewer viewer)
     34: {
     35:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

     37:   PetscFunctionBegin;
     38:   PetscCall(PetscViewerFileClose_VU(viewer));
     39:   PetscCall(PetscFree(vu));
     40:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
     41:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
     42:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
     43:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
     44:   PetscFunctionReturn(PETSC_SUCCESS);
     45: }

     47: static PetscErrorCode PetscViewerFlush_VU(PetscViewer viewer)
     48: {
     49:   PetscMPIInt rank;

     51:   PetscFunctionBegin;
     52:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
     53:   if (rank == 0) PetscCall(PetscFFlush(((PetscViewer_VU *)viewer->data)->fd));
     54:   PetscFunctionReturn(PETSC_SUCCESS);
     55: }

     57: static PetscErrorCode PetscViewerFileSetMode_VU(PetscViewer viewer, PetscFileMode mode)
     58: {
     59:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

     61:   PetscFunctionBegin;
     62:   vu->mode = mode;
     63:   PetscFunctionReturn(PETSC_SUCCESS);
     64: }

     66: static PetscErrorCode PetscViewerFileGetMode_VU(PetscViewer viewer, PetscFileMode *type)
     67: {
     68:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

     70:   PetscFunctionBegin;
     71:   *type = vu->mode;
     72:   PetscFunctionReturn(PETSC_SUCCESS);
     73: }

     75: static PetscErrorCode PetscViewerFileGetName_VU(PetscViewer viewer, const char **name)
     76: {
     77:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

     79:   PetscFunctionBegin;
     80:   *name = vu->filename;
     81:   PetscFunctionReturn(PETSC_SUCCESS);
     82: }

     84: static PetscErrorCode PetscViewerFileSetName_VU(PetscViewer viewer, const char name[])
     85: {
     86:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
     87:   char            fname[PETSC_MAX_PATH_LEN];
     88:   int             rank;

     90:   PetscFunctionBegin;
     91:   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
     92:   PetscCall(PetscViewerFileClose_VU(viewer));
     93:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
     94:   if (rank != 0) PetscFunctionReturn(PETSC_SUCCESS);
     95:   PetscCall(PetscStrallocpy(name, &vu->filename));
     96:   PetscCall(PetscFixFilename(name, fname));
     97:   switch (vu->mode) {
     98:   case FILE_MODE_READ:
     99:     vu->fd = fopen(fname, "r");
    100:     break;
    101:   case FILE_MODE_WRITE:
    102:     vu->fd = fopen(fname, "w");
    103:     break;
    104:   case FILE_MODE_APPEND:
    105:     vu->fd = fopen(fname, "a");
    106:     break;
    107:   case FILE_MODE_UPDATE:
    108:     vu->fd = fopen(fname, "r+");
    109:     if (!vu->fd) vu->fd = fopen(fname, "w+");
    110:     break;
    111:   case FILE_MODE_APPEND_UPDATE:
    112:     /* I really want a file which is opened at the end for updating,
    113:        not a+, which opens at the beginning, but makes writes at the end.
    114:     */
    115:     vu->fd = fopen(fname, "r+");
    116:     if (!vu->fd) vu->fd = fopen(fname, "w+");
    117:     else {
    118:       int ret = fseek(vu->fd, 0, SEEK_END);
    119:       PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
    120:     }
    121:     break;
    122:   default:
    123:     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vu->mode]);
    124:   }

    126:   PetscCheck(vu->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname);
    127:   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
    128:   PetscFunctionReturn(PETSC_SUCCESS);
    129: }

    131: /*MC
    132:    PETSCVIEWERVU - A viewer that prints to a VU file

    134:   Level: beginner

    136: .seealso: [](sec_viewers), `PetscViewerVUFlushDeferred()`, `PetscViewerVUGetPointer()`, `PetscViewerVUSetVecSeen()`, `PetscViewerVUGetVecSeen()`,
    137:           `PetscViewerVUPrintDeferred()`
    138: M*/
    139: PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer)
    140: {
    141:   PetscViewer_VU *vu;

    143:   PetscFunctionBegin;
    144:   PetscCall(PetscNew(&vu));
    145:   viewer->data = (void *)vu;

    147:   viewer->ops->destroy          = PetscViewerDestroy_VU;
    148:   viewer->ops->flush            = PetscViewerFlush_VU;
    149:   viewer->ops->getsubviewer     = NULL;
    150:   viewer->ops->restoresubviewer = NULL;

    152:   vu->fd          = NULL;
    153:   vu->mode        = FILE_MODE_WRITE;
    154:   vu->filename    = NULL;
    155:   vu->vecSeen     = PETSC_FALSE;
    156:   vu->queue       = NULL;
    157:   vu->queueBase   = NULL;
    158:   vu->queueLength = 0;

    160:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_VU));
    161:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_VU));
    162:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_VU));
    163:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_VU));
    164:   PetscFunctionReturn(PETSC_SUCCESS);
    165: }

    167: /*@C
    168:   PetscViewerVUGetPointer - Extracts the file pointer from a `PETSCVIEWERVU` `PetscViewer`.

    170:   Not Collective

    172:   Input Parameter:
    173: . viewer - The `PetscViewer`

    175:   Output Parameter:
    176: . fd - The file pointer

    178:   Level: intermediate

    180: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerASCIIGetPointer()`
    181: @*/
    182: PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
    183: {
    184:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

    186:   PetscFunctionBegin;
    188:   PetscAssertPointer(fd, 2);
    189:   *fd = vu->fd;
    190:   PetscFunctionReturn(PETSC_SUCCESS);
    191: }

    193: /*@C
    194:   PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed
    195:   a vector. This is usually called internally rather than by a user.

    197:   Not Collective

    199:   Input Parameters:
    200: + viewer  - The `PETSCVIEWERVU` `PetscViewer`
    201: - vecSeen - The flag which indicates whether we have viewed a vector

    203:   Level: developer

    205: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
    206: @*/
    207: PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen)
    208: {
    209:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

    211:   PetscFunctionBegin;
    212:   vu->vecSeen = vecSeen;
    213:   PetscFunctionReturn(PETSC_SUCCESS);
    214: }

    216: /*@C
    217:   PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed
    218:   a vector. This is usually called internally rather than by a user.

    220:   Not Collective

    222:   Input Parameter:
    223: . viewer - The `PETSCVIEWERVU` `PetscViewer`

    225:   Output Parameter:
    226: . vecSeen - The flag which indicates whether we have viewed a vector

    228:   Level: advanced

    230: .seealso: [](sec_viewers), `PETSCVIEWERVU`
    231: @*/
    232: PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen)
    233: {
    234:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

    236:   PetscFunctionBegin;
    238:   PetscAssertPointer(vecSeen, 2);
    239:   *vecSeen = vu->vecSeen;
    240:   PetscFunctionReturn(PETSC_SUCCESS);
    241: }

    243: /*@C
    244:   PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.

    246:   Not Collective

    248:   Input Parameters:
    249: + viewer - The `PETSCVIEWERVU` `PetscViewer`
    250: - format - The format string

    252:   Level: intermediate

    254: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUFlushDeferred()`
    255: @*/
    256: PetscErrorCode PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...)
    257: {
    258:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
    259:   va_list         Argp;
    260:   size_t          fullLength;
    261:   PrintfQueue     next;

    263:   PetscFunctionBegin;
    264:   PetscCall(PetscNew(&next));
    265:   if (vu->queue) {
    266:     vu->queue->next = next;
    267:     vu->queue       = next;
    268:     vu->queue->next = NULL;
    269:   } else {
    270:     vu->queueBase = vu->queue = next;
    271:   }
    272:   vu->queueLength++;

    274:   va_start(Argp, format);
    275:   PetscCall(PetscArrayzero(next->string, QUEUESTRINGSIZE));
    276:   PetscCall(PetscVSNPrintf(next->string, QUEUESTRINGSIZE, format, &fullLength, Argp));
    277:   va_end(Argp);
    278:   PetscFunctionReturn(PETSC_SUCCESS);
    279: }

    281: /*@C
    282:   PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.

    284:   Not Collective

    286:   Input Parameter:
    287: . viewer - The `PETSCVIEWERVU` `PetscViewer`

    289:   Level: intermediate

    291: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUPrintDeferred()`
    292: @*/
    293: PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer)
    294: {
    295:   PetscViewer_VU *vu   = (PetscViewer_VU *)viewer->data;
    296:   PrintfQueue     next = vu->queueBase;
    297:   PrintfQueue     previous;
    298:   int             i;

    300:   PetscFunctionBegin;
    301:   for (i = 0; i < vu->queueLength; i++) {
    302:     PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string));
    303:     previous = next;
    304:     next     = next->next;
    305:     PetscCall(PetscFree(previous));
    306:   }
    307:   vu->queue       = NULL;
    308:   vu->queueLength = 0;
    309:   PetscFunctionReturn(PETSC_SUCCESS);
    310: }