Actual source code: vcreatea.c
2: #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h>
4: /*
5: The variable Petsc_Viewer_Stdout_keyval is used to indicate an MPI attribute that
6: is attached to a communicator, in this case the attribute is a PetscViewer.
7: */
8: PetscMPIInt Petsc_Viewer_Stdout_keyval = MPI_KEYVAL_INVALID;
10: /*@
11: PetscViewerASCIIGetStdout - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processors
12: in a communicator. Error returning version of `PETSC_VIEWER_STDOUT_()`
14: Collective
16: Input Parameter:
17: . comm - the MPI communicator to share the `PetscViewer`
19: Level: beginner
21: Note:
22: This should be used in all PETSc source code instead of `PETSC_VIEWER_STDOUT_()` since it allows error checking
24: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
25: `PETSC_VIEWER_STDOUT_SELF`
26: @*/
27: PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm, PetscViewer *viewer)
28: {
29: PetscBool flg;
30: MPI_Comm ncomm;
32: PetscFunctionBegin;
33: PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout));
34: PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
35: 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));
36: PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, (PetscMPIInt *)&flg));
37: if (!flg) { /* PetscViewer not yet created */
38: PetscCall(PetscViewerASCIIOpen(ncomm, "stdout", viewer));
39: PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
40: PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer));
41: }
42: PetscCall(PetscCommDestroy(&ncomm));
43: PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout));
44: PetscFunctionReturn(PETSC_SUCCESS);
45: }
47: /*@C
48: PETSC_VIEWER_STDOUT_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
49: in a communicator.
51: Collective
53: Input Parameter:
54: . comm - the MPI communicator to share the `PetscViewer`
56: Level: beginner
58: Note:
59: Unlike almost all other PETSc routines, this does not return
60: an error code. Usually used in the form
61: $ XXXView(XXX object, PETSC_VIEWER_STDOUT_(comm));
63: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
64: `PETSC_VIEWER_STDOUT_SELF`
65: @*/
66: PetscViewer PETSC_VIEWER_STDOUT_(MPI_Comm comm)
67: {
68: PetscErrorCode ierr;
69: PetscViewer viewer;
71: PetscFunctionBegin;
72: ierr = PetscViewerASCIIGetStdout(comm, &viewer);
73: if (ierr) {
74: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_STDOUT_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
75: PetscFunctionReturn(NULL);
76: }
77: PetscFunctionReturn(viewer);
78: }
80: /*
81: The variable Petsc_Viewer_Stderr_keyval is used to indicate an MPI attribute that
82: is attached to a communicator, in this case the attribute is a PetscViewer.
83: */
84: PetscMPIInt Petsc_Viewer_Stderr_keyval = MPI_KEYVAL_INVALID;
86: /*@
87: PetscViewerASCIIGetStderr - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
88: in a communicator. Error returning version of `PETSC_VIEWER_STDERR_()`
90: Collective
92: Input Parameter:
93: . comm - the MPI communicator to share the `PetscViewer`
95: Level: beginner
97: Note:
98: This should be used in all PETSc source code instead of `PETSC_VIEWER_STDERR_()` since it allows error checking
100: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDERR_WORLD`,
101: `PETSC_VIEWER_STDERR_SELF`
102: @*/
103: PetscErrorCode PetscViewerASCIIGetStderr(MPI_Comm comm, PetscViewer *viewer)
104: {
105: PetscBool flg;
106: MPI_Comm ncomm;
108: PetscFunctionBegin;
109: PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStderr));
110: PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
111: 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));
112: PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void **)viewer, (PetscMPIInt *)&flg));
113: if (!flg) { /* PetscViewer not yet created */
114: PetscCall(PetscViewerASCIIOpen(ncomm, "stderr", viewer));
115: PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
116: PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void *)*viewer));
117: }
118: PetscCall(PetscCommDestroy(&ncomm));
119: PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStderr));
120: PetscFunctionReturn(PETSC_SUCCESS);
121: }
123: /*@C
124: PETSC_VIEWER_STDERR_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
125: in a communicator.
127: Collective
129: Input Parameter:
130: . comm - the MPI communicator to share the `PetscViewer`
132: Level: beginner
134: Notes:
135: Unlike almost all other PETSc routines, this does not return
136: an error code. Usually used in the form
137: $ XXXView(XXX object, PETSC_VIEWER_STDERR_(comm));
139: `PetscViewerASCIIGetStderr()` is preferred since it allows error checking
141: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDOUT_WORLD`,
142: `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDERR_WORLD`, `PETSC_VIEWER_STDERR_SELF`
143: @*/
144: PetscViewer PETSC_VIEWER_STDERR_(MPI_Comm comm)
145: {
146: PetscErrorCode ierr;
147: PetscViewer viewer;
149: PetscFunctionBegin;
150: ierr = PetscViewerASCIIGetStderr(comm, &viewer);
151: if (ierr) {
152: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_STDERR_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
153: PetscFunctionReturn(NULL);
154: }
155: PetscFunctionReturn(viewer);
156: }
158: PetscMPIInt Petsc_Viewer_keyval = MPI_KEYVAL_INVALID;
159: /*
160: Called with MPI_Comm_free() is called on a communicator that has a viewer as an attribute. The viewer is not actually destroyed
161: because that is managed by PetscObjectDestroyRegisterAll(). PetscViewerASCIIGetStdout() registers the viewer with PetscObjectDestroyRegister() to be destroyed when PetscFinalize() is called.
163: This is called by MPI, not by users.
165: */
166: PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelViewer(MPI_Comm comm, PetscMPIInt keyval, void *attr_val, void *extra_state)
167: {
168: PetscFunctionBegin;
169: PetscCallMPI(PetscInfo(NULL, "Removing viewer data attribute in an MPI_Comm %ld\n", (long)comm));
170: PetscFunctionReturn(MPI_SUCCESS);
171: }
173: /*@C
174: PetscViewerASCIIOpen - Opens an ASCII file for writing as a `PETSCVIEWERASCII` `PetscViewer`.
176: Collective
178: Input Parameters:
179: + comm - the communicator
180: - name - the file name
182: Output Parameter:
183: . lab - the `PetscViewer` to use with the specified file
185: Level: beginner
187: Notes:
188: To open a ASCII file as a viewer for reading one must use the sequence
189: .vb
190: PetscViewerCreate(comm,&lab);
191: PetscViewerSetType(lab,PETSCVIEWERASCII);
192: PetscViewerFileSetMode(lab,FILE_MODE_READ);
193: PetscViewerFileSetName(lab,name);
194: .ve
196: This `PetscViewer` can be destroyed with `PetscViewerDestroy()`.
198: The MPI communicator used here must match that used by the object one is viewing. For example if the
199: Mat was created with a `PETSC_COMM_WORLD`, then the Viewer must be created with `PETSC_COMM_WORLD`
201: As shown below, `PetscViewerASCIIOpen()` is useful in conjunction with
202: `MatView()` and `VecView()`
203: .vb
204: PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat.output",&viewer);
205: MatView(matrix,viewer);
206: .ve
208: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIRead()`, `PETSCVIEWERASCII`
209: `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
210: `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`,
211: @*/
212: PetscErrorCode PetscViewerASCIIOpen(MPI_Comm comm, const char name[], PetscViewer *lab)
213: {
214: PetscViewerLink *vlink, *nv;
215: PetscBool flg, eq;
216: size_t len;
218: PetscFunctionBegin;
219: PetscCall(PetscStrlen(name, &len));
220: if (!len) {
221: PetscCall(PetscViewerASCIIGetStdout(comm, lab));
222: PetscCall(PetscObjectReference((PetscObject)*lab));
223: PetscFunctionReturn(PETSC_SUCCESS);
224: }
225: PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockOpen));
226: if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0));
227: /*
228: It would be better to move this code to PetscFileSetName() but since it must return a preexiting communicator
229: we cannot do that, since PetscFileSetName() takes a communicator that already exists.
231: Plus if the original communicator that created the file has since been close this will not detect the old
232: communictor and hence will overwrite the old data. It may be better to simply remove all this code
233: */
234: /* make sure communicator is a PETSc communicator */
235: PetscCall(PetscCommDuplicate(comm, &comm, NULL));
236: /* has file already been opened into a viewer */
237: PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
238: if (flg) {
239: while (vlink) {
240: PetscCall(PetscStrcmp(name, ((PetscViewer_ASCII *)(vlink->viewer->data))->filename, &eq));
241: if (eq) {
242: PetscCall(PetscObjectReference((PetscObject)vlink->viewer));
243: *lab = vlink->viewer;
244: PetscCall(PetscCommDestroy(&comm));
245: PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen));
246: PetscFunctionReturn(PETSC_SUCCESS);
247: }
248: vlink = vlink->next;
249: }
250: }
251: PetscCall(PetscViewerCreate(comm, lab));
252: PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII));
253: if (name) PetscCall(PetscViewerFileSetName(*lab, name));
254: /* save viewer into communicator if needed later */
255: PetscCall(PetscNew(&nv));
256: nv->viewer = *lab;
257: if (!flg) {
258: PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv));
259: } else {
260: PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
261: if (vlink) {
262: while (vlink->next) vlink = vlink->next;
263: vlink->next = nv;
264: } else {
265: PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv));
266: }
267: }
268: PetscCall(PetscCommDestroy(&comm));
269: PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen));
270: PetscFunctionReturn(PETSC_SUCCESS);
271: }
273: /*@C
274: PetscViewerASCIIOpenWithFILE - Given an open file creates an `PETSCVIEWERASCII` viewer that prints to it.
276: Collective
278: Input Parameters:
279: + comm - the communicator
280: - fd - the `FILE` pointer
282: Output Parameter:
283: . lab - the `PetscViewer` to use with the specified file
285: Level: beginner
287: Notes:
288: This `PetscViewer` can be destroyed with `PetscViewerDestroy()`, but the fd will NOT be closed.
290: If a multiprocessor communicator is used (such as `PETSC_COMM_WORLD`),
291: then only the first processor in the group uses the file. All other
292: processors send their data to the first processor to print.
294: .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`,
295: `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
296: `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`
297: @*/
298: PetscErrorCode PetscViewerASCIIOpenWithFILE(MPI_Comm comm, FILE *fd, PetscViewer *lab)
299: {
300: PetscFunctionBegin;
301: PetscCall(PetscViewerCreate(comm, lab));
302: PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII));
303: PetscCall(PetscViewerASCIISetFILE(*lab, fd));
304: PetscFunctionReturn(PETSC_SUCCESS);
305: }
307: /*@C
308: PetscViewerASCIISetFILE - Given an open file sets the `PETSCVIEWERASCII` viewer to use the file for output
310: Not Collective
312: Input Parameters:
313: + viewer - the `PetscViewer` to use with the specified file
314: - fd - the `FILE` pointer
316: Level: beginner
318: Notes:
319: This `PetscViewer` can be destroyed with `PetscViewerDestroy()`, but the `fd` will NOT be closed.
321: If a multiprocessor communicator is used (such as `PETSC_COMM_WORLD`),
322: then only the first processor in the group uses the file. All other
323: processors send their data to the first processor to print.
325: .seealso: `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`,
326: `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`,
327: `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIIOpenWithFILE()`, `PETSCVIEWERASCII`
328: @*/
329: PetscErrorCode PetscViewerASCIISetFILE(PetscViewer viewer, FILE *fd)
330: {
331: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
333: PetscFunctionBegin;
334: vascii->fd = fd;
335: vascii->closefile = PETSC_FALSE;
336: PetscFunctionReturn(PETSC_SUCCESS);
337: }