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: $      XXXView(XXX object, PETSC_VIEWER_STDOUT_(comm));

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

 34:   PetscFunctionBegin;
 35:   PetscCallNull(PetscViewerASCIIGetStdout(comm, &viewer));
 36:   PetscFunctionReturn(viewer);
 37: }

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

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

 49:   Collective

 51:   Input Parameter:
 52: . comm - the MPI communicator to share the `PetscViewer`

 54:   Output Parameter:
 55: . viewer - the viewer

 57:   Level: beginner

 59:   Note:
 60:   Use `PetscViewerDestroy()` to destroy it

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

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

 73:   PetscFunctionBegin;
 74:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStderr));
 75:   PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
 76:   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));
 77:   PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void **)viewer, (PetscMPIInt *)&flg));
 78:   if (!flg) { /* PetscViewer not yet created */
 79:     PetscCall(PetscViewerCreate(ncomm, viewer));
 80:     PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
 81:     PetscCall(PetscViewerFileSetName(*viewer, "stderr"));
 82:     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
 83:     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void *)*viewer));
 84:   }
 85:   PetscCall(PetscCommDestroy(&ncomm));
 86:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStderr));
 87:   PetscFunctionReturn(PETSC_SUCCESS);
 88: }

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

 94:    Collective

 96:    Input Parameter:
 97: .  comm - the MPI communicator to share the `PetscViewer`

 99:    Level: beginner

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

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

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

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

117:   PetscFunctionBegin;
118:   PetscCallNull(PetscViewerASCIIGetStderr(comm, &viewer));
119:   PetscFunctionReturn(viewer);
120: }

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

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

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

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

143:   Collective

145:   Input Parameters:
146: + comm - the communicator
147: - name - the file name

149:   Output Parameter:
150: . viewer - the `PetscViewer` to use with the specified file

152:   Level: beginner

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

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

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

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

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

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

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

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

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

244:   Collective

246:   Input Parameters:
247: + comm - the communicator
248: - fd   - the `FILE` pointer

250:   Output Parameter:
251: . viewer - the `PetscViewer` to use with the specified file

253:   Level: beginner

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

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

262:   Fortran Notes:
263:   Use `PetscViewerASCIIOpenWithFileUnit()`

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

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

281:   Not Collective

283:   Input Parameters:
284: + viewer - the `PetscViewer` to use with the specified file
285: - fd     - the `FILE` pointer

287:   Level: beginner

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

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

296:   Fortran Notes:
297:   Use `PetscViewerASCIISetFileUnit()`

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

307:   PetscFunctionBegin;
308:   vascii->fd        = fd;
309:   vascii->closefile = PETSC_FALSE;
310:   PetscFunctionReturn(PETSC_SUCCESS);
311: }