Actual source code: vcreatea.c

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

      3: /*
      4:     The variable Petsc_Viewer_Stdout_keyval is used to indicate an MPI attribute that
      5:   is attached to a communicator, in this case the attribute is a PetscViewer.
      6: */
      7: PetscMPIInt Petsc_Viewer_Stdout_keyval = MPI_KEYVAL_INVALID;

      9: /*@C
     10:    PETSC_VIEWER_STDOUT_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
     11:                     in a communicator.

     13:    Collective

     15:    Input Parameter:
     16: .  comm - the MPI communicator to share the `PetscViewer`

     18:    Level: beginner

     20:    Notes:
     21:    This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it

     23:    Unlike almost all other PETSc routines, this does not return
     24:    an error code. Usually used in the form
     25: .vb
     26:   XXXView(XXX object, PETSC_VIEWER_STDOUT_(comm));
     27: .ve

     29: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
     30:           `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIGetStdout()`, `PetscViewerASCIIGetStderr()`
     31: @*/
     32: PetscViewer PETSC_VIEWER_STDOUT_(MPI_Comm comm)
     33: {
     34:   PetscViewer viewer;

     36:   PetscFunctionBegin;
     37:   PetscCallNull(PetscViewerASCIIGetStdout(comm, &viewer));
     38:   PetscFunctionReturn(viewer);
     39: }

     41: /*
     42:     The variable Petsc_Viewer_Stderr_keyval is used to indicate an MPI attribute that
     43:   is attached to a communicator, in this case the attribute is a PetscViewer.
     44: */
     45: PetscMPIInt Petsc_Viewer_Stderr_keyval = MPI_KEYVAL_INVALID;

     47: /*@
     48:   PetscViewerASCIIGetStderr - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
     49:   in a communicator that prints to `stderr`. Error returning version of `PETSC_VIEWER_STDERR_()`

     51:   Collective

     53:   Input Parameter:
     54: . comm - the MPI communicator to share the `PetscViewer`

     56:   Output Parameter:
     57: . viewer - the viewer

     59:   Level: beginner

     61:   Note:
     62:   Use `PetscViewerDestroy()` to destroy it

     64:   Developer Note:
     65:   This should be used in all PETSc source code instead of `PETSC_VIEWER_STDERR_()` since it allows error checking

     67: .seealso: [](sec_viewers), `PetscViewerASCIIGetStdout()`, `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDERR_WORLD`,
     68:           `PETSC_VIEWER_STDERR_SELF`
     69: @*/
     70: PetscErrorCode PetscViewerASCIIGetStderr(MPI_Comm comm, PetscViewer *viewer)
     71: {
     72:   PetscMPIInt iflg;
     73:   MPI_Comm    ncomm;

     75:   PetscFunctionBegin;
     76:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStderr));
     77:   PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
     78:   if (Petsc_Viewer_Stderr_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Stderr_keyval, NULL));
     79:   PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void **)viewer, &iflg));
     80:   if (!iflg) { /* PetscViewer not yet created */
     81:     PetscCall(PetscViewerCreate(ncomm, viewer));
     82:     PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
     83:     PetscCall(PetscViewerFileSetName(*viewer, "stderr"));
     84:     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
     85:     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void *)*viewer));
     86:   }
     87:   PetscCall(PetscCommDestroy(&ncomm));
     88:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStderr));
     89:   PetscFunctionReturn(PETSC_SUCCESS);
     90: }

     92: /*@C
     93:    PETSC_VIEWER_STDERR_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
     94:                     in a communicator.

     96:    Collective

     98:    Input Parameter:
     99: .  comm - the MPI communicator to share the `PetscViewer`

    101:    Level: beginner

    103:    Notes:
    104:    This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it

    106:    Unlike almost all other PETSc routines, this does not return
    107:    an error code. Usually used in the form
    108: $      XXXView(XXX object, PETSC_VIEWER_STDERR_(comm));

    110:    `PetscViewerASCIIGetStderr()` is preferred  since it allows error checking

    112: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDOUT_WORLD`,
    113:           `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDERR_WORLD`, `PETSC_VIEWER_STDERR_SELF`
    114: @*/
    115: PetscViewer PETSC_VIEWER_STDERR_(MPI_Comm comm)
    116: {
    117:   PetscViewer viewer;

    119:   PetscFunctionBegin;
    120:   PetscCallNull(PetscViewerASCIIGetStderr(comm, &viewer));
    121:   PetscFunctionReturn(viewer);
    122: }

    124: PetscMPIInt Petsc_Viewer_keyval = MPI_KEYVAL_INVALID;
    125: /*
    126:    Called with MPI_Comm_free() is called on a communicator that has a viewer as an attribute. The viewer is not actually destroyed
    127:    because that is managed by PetscObjectDestroyRegisterAll(). PetscViewerASCIIGetStdout() registers the viewer with PetscObjectDestroyRegister() to be destroyed when PetscFinalize() is called.

    129:   This is called by MPI, not by users.

    131: */
    132: PetscMPIInt MPIAPI Petsc_DelViewer(MPI_Comm comm, PetscMPIInt keyval, void *attr_val, void *extra_state)
    133: {
    134:   PetscFunctionBegin;
    135:   (void)keyval;
    136:   (void)attr_val;
    137:   (void)extra_state;
    138:   PetscCallReturnMPI(PetscInfo(NULL, "Removing viewer data attribute in an MPI_Comm %" PETSC_INTPTR_T_FMT "\n", (PETSC_INTPTR_T)comm));
    139:   PetscFunctionReturn(MPI_SUCCESS);
    140: }

    142: /*@
    143:   PetscViewerASCIIOpen - Opens an ASCII file for writing as a `PETSCVIEWERASCII` `PetscViewer`.

    145:   Collective

    147:   Input Parameters:
    148: + comm - the communicator
    149: - name - the file name

    151:   Output Parameter:
    152: . viewer - the `PetscViewer` to use with the specified file

    154:   Level: beginner

    156:   Notes:
    157:   This routine only opens files for writing. To open a ASCII file as a `PetscViewer` for reading use the sequence
    158: .vb
    159:    PetscViewerCreate(comm,&viewer);
    160:    PetscViewerSetType(viewer,PETSCVIEWERASCII);
    161:    PetscViewerFileSetMode(viewer,FILE_MODE_READ);
    162:    PetscViewerFileSetName(viewer,name);
    163: .ve

    165:   This `PetscViewer` can be destroyed with `PetscViewerDestroy()`.

    167:   The MPI communicator used here must match that used by the object viewed. For example if the
    168:   Mat was created with a `PETSC_COMM_WORLD`, then `viewer` must be created with `PETSC_COMM_WORLD`

    170:   As shown below, `PetscViewerASCIIOpen()` is useful in conjunction with
    171:   `MatView()` and `VecView()`
    172: .vb
    173:      PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat.output",&viewer);
    174:      MatView(matrix,viewer);
    175: .ve

    177:   Developer Note:
    178:   When called with `NULL`, `stdout`, or `stderr` this does not return the same communicator as `PetscViewerASCIIGetStdout()` or `PetscViewerASCIIGetStderr()`
    179:   but that is ok.

    181: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIRead()`, `PETSCVIEWERASCII`,
    182:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
    183:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIGetStdout()`, `PetscViewerASCIIGetStderr()`
    184: @*/
    185: PetscErrorCode PetscViewerASCIIOpen(MPI_Comm comm, const char name[], PetscViewer *viewer)
    186: {
    187:   PetscViewerLink *vlink, *nv;
    188:   PetscMPIInt      iflg;
    189:   PetscBool        eq;
    190:   size_t           len;

    192:   PetscFunctionBegin;
    193:   PetscAssertPointer(viewer, 3);
    194:   PetscCall(PetscStrlen(name, &len));
    195:   if (!len) name = "stdout";
    196:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockOpen));
    197:   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, NULL));
    198:   /*
    199:        It would be better to move this code to PetscFileSetName() but since it must return a preexiting communicator
    200:      we cannot do that, since PetscFileSetName() takes a communicator that already exists.

    202:       Plus if the original communicator that created the file has since been close this will not detect the old
    203:       communictor and hence will overwrite the old data. It may be better to simply remove all this code
    204:   */
    205:   /* make sure communicator is a PETSc communicator */
    206:   PetscCall(PetscCommDuplicate(comm, &comm, NULL));
    207:   /* has file already been opened into a viewer */
    208:   PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, &iflg));
    209:   if (iflg) {
    210:     while (vlink) {
    211:       PetscCall(PetscStrcmp(name, ((PetscViewer_ASCII *)vlink->viewer->data)->filename, &eq));
    212:       if (eq) {
    213:         PetscCall(PetscObjectReference((PetscObject)vlink->viewer));
    214:         *viewer = vlink->viewer;
    215:         PetscCall(PetscCommDestroy(&comm));
    216:         PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen));
    217:         PetscFunctionReturn(PETSC_SUCCESS);
    218:       }
    219:       vlink = vlink->next;
    220:     }
    221:   }
    222:   PetscCall(PetscViewerCreate(comm, viewer));
    223:   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
    224:   PetscCall(PetscViewerFileSetName(*viewer, name));
    225:   /* save viewer into communicator if needed later */
    226:   PetscCall(PetscNew(&nv));
    227:   nv->viewer = *viewer;
    228:   if (!iflg) {
    229:     PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv));
    230:   } else {
    231:     PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, &iflg));
    232:     if (vlink) {
    233:       while (vlink->next) vlink = vlink->next;
    234:       vlink->next = nv;
    235:     } else {
    236:       PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv));
    237:     }
    238:   }
    239:   PetscCall(PetscCommDestroy(&comm));
    240:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen));
    241:   PetscFunctionReturn(PETSC_SUCCESS);
    242: }

    244: /*@C
    245:   PetscViewerASCIIOpenWithFILE - Given an open file creates an `PETSCVIEWERASCII` viewer that prints to it.

    247:   Collective

    249:   Input Parameters:
    250: + comm - the communicator
    251: - fd   - the `FILE` pointer

    253:   Output Parameter:
    254: . viewer - the `PetscViewer` to use with the specified file

    256:   Level: beginner

    258:   Notes:
    259:   This `PetscViewer` can be destroyed with `PetscViewerDestroy()`, but the fd will NOT be closed.

    261:   If a multiprocessor communicator is used (such as `PETSC_COMM_WORLD`),
    262:   then only the first processor in the group uses the file.  All other
    263:   processors send their data to the first processor to print.

    265:   Fortran Notes:
    266:   Use `PetscViewerASCIIOpenWithFileUnit()`

    268: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIOpenWithFileUnit()`,
    269:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
    270:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`
    271: @*/
    272: PetscErrorCode PetscViewerASCIIOpenWithFILE(MPI_Comm comm, FILE *fd, PetscViewer *viewer)
    273: {
    274:   PetscFunctionBegin;
    275:   PetscCall(PetscViewerCreate(comm, viewer));
    276:   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
    277:   PetscCall(PetscViewerASCIISetFILE(*viewer, fd));
    278:   PetscFunctionReturn(PETSC_SUCCESS);
    279: }

    281: /*@C
    282:   PetscViewerASCIISetFILE - Given an open file sets the `PETSCVIEWERASCII` viewer to use the file for output

    284:   Not Collective

    286:   Input Parameters:
    287: + viewer - the `PetscViewer` to use with the specified file
    288: - fd     - the `FILE` pointer

    290:   Level: beginner

    292:   Notes:
    293:   This `PetscViewer` can be destroyed with `PetscViewerDestroy()`, but the `fd` will NOT be closed.

    295:   If a multiprocessor communicator is used (such as `PETSC_COMM_WORLD`),
    296:   then only the first processor in the group uses the file.  All other
    297:   processors send their data to the first processor to print.

    299:   Fortran Note:
    300:   Use `PetscViewerASCIISetFileUnit()`

    302: .seealso: `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIISetFileUnit()`,
    303:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
    304:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIIOpenWithFILE()`, `PETSCVIEWERASCII`
    305: @*/
    306: PetscErrorCode PetscViewerASCIISetFILE(PetscViewer viewer, FILE *fd)
    307: {
    308:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

    310:   PetscFunctionBegin;
    311:   vascii->fd        = fd;
    312:   vascii->closefile = PETSC_FALSE;
    313:   PetscFunctionReturn(PETSC_SUCCESS);
    314: }