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: /*@
 10:   PetscViewerASCIIGetStdout - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processors
 11:   in a communicator. Error returning version of `PETSC_VIEWER_STDOUT_()`

 13:   Collective

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

 18:   Output Parameter:
 19: . viewer - the viewer

 21:   Level: beginner

 23:   Note:
 24:   This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it

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

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

 37:   PetscFunctionBegin;
 38:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout));
 39:   PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
 40:   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));
 41:   PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, (PetscMPIInt *)&flg));
 42:   if (!flg) { /* PetscViewer not yet created */
 43:     PetscCall(PetscViewerASCIIOpen(ncomm, "stdout", viewer));
 44:     ((PetscObject)*viewer)->persistent = PETSC_TRUE;
 45:     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
 46:     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer));
 47:   }
 48:   PetscCall(PetscCommDestroy(&ncomm));
 49:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout));
 50:   PetscFunctionReturn(PETSC_SUCCESS);
 51: }

 53: /*@C
 54:    PETSC_VIEWER_STDOUT_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
 55:                     in a communicator.

 57:    Collective

 59:    Input Parameter:
 60: .  comm - the MPI communicator to share the `PetscViewer`

 62:    Level: beginner

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

 67:    Unlike almost all other PETSc routines, this does not return
 68:    an error code. Usually used in the form
 69: $      XXXView(XXX object, PETSC_VIEWER_STDOUT_(comm));

 71: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
 72:           `PETSC_VIEWER_STDOUT_SELF`
 73: @*/
 74: PetscViewer PETSC_VIEWER_STDOUT_(MPI_Comm comm)
 75: {
 76:   PetscErrorCode ierr;
 77:   PetscViewer    viewer;

 79:   PetscFunctionBegin;
 80:   ierr = PetscViewerASCIIGetStdout(comm, &viewer);
 81:   if (ierr) {
 82:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_STDOUT_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
 83:     PetscFunctionReturn(NULL);
 84:   }
 85:   PetscFunctionReturn(viewer);
 86: }

 88: /*
 89:     The variable Petsc_Viewer_Stderr_keyval is used to indicate an MPI attribute that
 90:   is attached to a communicator, in this case the attribute is a PetscViewer.
 91: */
 92: PetscMPIInt Petsc_Viewer_Stderr_keyval = MPI_KEYVAL_INVALID;

 94: /*@
 95:   PetscViewerASCIIGetStderr - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
 96:   in a communicator. Error returning version of `PETSC_VIEWER_STDERR_()`

 98:   Collective

100:   Input Parameter:
101: . comm - the MPI communicator to share the `PetscViewer`

103:   Output Parameter:
104: . viewer - the viewer

106:   Level: beginner

108:   Note:
109:   This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it

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

114: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDERR_WORLD`,
115:           `PETSC_VIEWER_STDERR_SELF`
116: @*/
117: PetscErrorCode PetscViewerASCIIGetStderr(MPI_Comm comm, PetscViewer *viewer)
118: {
119:   PetscBool flg;
120:   MPI_Comm  ncomm;

122:   PetscFunctionBegin;
123:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStderr));
124:   PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
125:   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));
126:   PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void **)viewer, (PetscMPIInt *)&flg));
127:   if (!flg) { /* PetscViewer not yet created */
128:     PetscCall(PetscViewerASCIIOpen(ncomm, "stderr", viewer));
129:     ((PetscObject)*viewer)->persistent = PETSC_TRUE;
130:     PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
131:     PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void *)*viewer));
132:   }
133:   PetscCall(PetscCommDestroy(&ncomm));
134:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStderr));
135:   PetscFunctionReturn(PETSC_SUCCESS);
136: }

138: /*@C
139:    PETSC_VIEWER_STDERR_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
140:                     in a communicator.

142:    Collective

144:    Input Parameter:
145: .  comm - the MPI communicator to share the `PetscViewer`

147:    Level: beginner

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

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

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

158: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDOUT_WORLD`,
159:           `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDERR_WORLD`, `PETSC_VIEWER_STDERR_SELF`
160: @*/
161: PetscViewer PETSC_VIEWER_STDERR_(MPI_Comm comm)
162: {
163:   PetscErrorCode ierr;
164:   PetscViewer    viewer;

166:   PetscFunctionBegin;
167:   ierr = PetscViewerASCIIGetStderr(comm, &viewer);
168:   if (ierr) {
169:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_STDERR_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
170:     PetscFunctionReturn(NULL);
171:   }
172:   PetscFunctionReturn(viewer);
173: }

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

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

182: */
183: PetscMPIInt MPIAPI Petsc_DelViewer(MPI_Comm comm, PetscMPIInt keyval, void *attr_val, void *extra_state)
184: {
185:   PetscFunctionBegin;
186:   (void)keyval;
187:   (void)attr_val;
188:   (void)extra_state;
189:   PetscCallMPI(PetscInfo(NULL, "Removing viewer data attribute in an MPI_Comm %" PETSC_INTPTR_T_FMT "\n", (PETSC_INTPTR_T)comm));
190:   PetscFunctionReturn(MPI_SUCCESS);
191: }

193: /*@C
194:   PetscViewerASCIIOpen - Opens an ASCII file for writing as a `PETSCVIEWERASCII` `PetscViewer`.

196:   Collective

198:   Input Parameters:
199: + comm - the communicator
200: - name - the file name

202:   Output Parameter:
203: . lab - the `PetscViewer` to use with the specified file

205:   Level: beginner

207:   Notes:
208:   To open a ASCII file as a viewer for reading one must use the sequence
209: .vb
210:    PetscViewerCreate(comm,&lab);
211:    PetscViewerSetType(lab,PETSCVIEWERASCII);
212:    PetscViewerFileSetMode(lab,FILE_MODE_READ);
213:    PetscViewerFileSetName(lab,name);
214: .ve

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

218:   The MPI communicator used here must match that used by the object one is viewing. For example if the
219:   Mat was created with a `PETSC_COMM_WORLD`, then the Viewer must be created with `PETSC_COMM_WORLD`

221:   As shown below, `PetscViewerASCIIOpen()` is useful in conjunction with
222:   `MatView()` and `VecView()`
223: .vb
224:      PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat.output",&viewer);
225:      MatView(matrix,viewer);
226: .ve

228: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIRead()`, `PETSCVIEWERASCII`
229:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
230:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`,
231: @*/
232: PetscErrorCode PetscViewerASCIIOpen(MPI_Comm comm, const char name[], PetscViewer *lab)
233: {
234:   PetscViewerLink *vlink, *nv;
235:   PetscBool        flg, eq;
236:   size_t           len;

238:   PetscFunctionBegin;
239:   PetscCall(PetscStrlen(name, &len));
240:   if (!len) {
241:     PetscCall(PetscViewerASCIIGetStdout(comm, lab));
242:     PetscCall(PetscObjectReference((PetscObject)*lab));
243:     PetscFunctionReturn(PETSC_SUCCESS);
244:   }
245:   PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockOpen));
246:   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0));
247:   /*
248:        It would be better to move this code to PetscFileSetName() but since it must return a preexiting communicator
249:      we cannot do that, since PetscFileSetName() takes a communicator that already exists.

251:       Plus if the original communicator that created the file has since been close this will not detect the old
252:       communictor and hence will overwrite the old data. It may be better to simply remove all this code
253:   */
254:   /* make sure communicator is a PETSc communicator */
255:   PetscCall(PetscCommDuplicate(comm, &comm, NULL));
256:   /* has file already been opened into a viewer */
257:   PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
258:   if (flg) {
259:     while (vlink) {
260:       PetscCall(PetscStrcmp(name, ((PetscViewer_ASCII *)(vlink->viewer->data))->filename, &eq));
261:       if (eq) {
262:         PetscCall(PetscObjectReference((PetscObject)vlink->viewer));
263:         *lab = vlink->viewer;
264:         PetscCall(PetscCommDestroy(&comm));
265:         PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen));
266:         PetscFunctionReturn(PETSC_SUCCESS);
267:       }
268:       vlink = vlink->next;
269:     }
270:   }
271:   PetscCall(PetscViewerCreate(comm, lab));
272:   PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII));
273:   if (name) PetscCall(PetscViewerFileSetName(*lab, name));
274:   /* save viewer into communicator if needed later */
275:   PetscCall(PetscNew(&nv));
276:   nv->viewer = *lab;
277:   if (!flg) {
278:     PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv));
279:   } else {
280:     PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
281:     if (vlink) {
282:       while (vlink->next) vlink = vlink->next;
283:       vlink->next = nv;
284:     } else {
285:       PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv));
286:     }
287:   }
288:   PetscCall(PetscCommDestroy(&comm));
289:   PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen));
290:   PetscFunctionReturn(PETSC_SUCCESS);
291: }

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

296:   Collective

298:   Input Parameters:
299: + comm - the communicator
300: - fd   - the `FILE` pointer

302:   Output Parameter:
303: . lab - the `PetscViewer` to use with the specified file

305:   Level: beginner

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

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

314:   Fortran Notes:
315:   Use `PetscViewerASCIIOpenWithFileUnit()`

317: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIOpenWithFileUnit()`,
318:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
319:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`
320: @*/
321: PetscErrorCode PetscViewerASCIIOpenWithFILE(MPI_Comm comm, FILE *fd, PetscViewer *lab)
322: {
323:   PetscFunctionBegin;
324:   PetscCall(PetscViewerCreate(comm, lab));
325:   PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII));
326:   PetscCall(PetscViewerASCIISetFILE(*lab, fd));
327:   PetscFunctionReturn(PETSC_SUCCESS);
328: }

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

333:   Not Collective

335:   Input Parameters:
336: + viewer - the `PetscViewer` to use with the specified file
337: - fd     - the `FILE` pointer

339:   Level: beginner

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

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

348:   Fortran Notes:
349:   Use `PetscViewerASCIISetFileUnit()`

351: .seealso: `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIISetFileUnit()`,
352:           `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
353:           `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIIOpenWithFILE()`, `PETSCVIEWERASCII`
354: @*/
355: PetscErrorCode PetscViewerASCIISetFILE(PetscViewer viewer, FILE *fd)
356: {
357:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;

359:   PetscFunctionBegin;
360:   vascii->fd        = fd;
361:   vascii->closefile = PETSC_FALSE;
362:   PetscFunctionReturn(PETSC_SUCCESS);
363: }