1 #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h> /*I "petscviewer.h" I*/
2
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;
8
9 /*@C
10 PETSC_VIEWER_STDOUT_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
11 in a communicator.
12
13 Collective
14
15 Input Parameter:
16 . comm - the MPI communicator to share the `PetscViewer`
17
18 Level: beginner
19
20 Notes:
21 This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it
22
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
28
29 .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
30 `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIGetStdout()`, `PetscViewerASCIIGetStderr()`
31 @*/
PETSC_VIEWER_STDOUT_(MPI_Comm comm)32 PetscViewer PETSC_VIEWER_STDOUT_(MPI_Comm comm)
33 {
34 PetscViewer viewer;
35
36 PetscFunctionBegin;
37 PetscCallNull(PetscViewerASCIIGetStdout(comm, &viewer));
38 PetscFunctionReturn(viewer);
39 }
40
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;
46
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_()`
50
51 Collective
52
53 Input Parameter:
54 . comm - the MPI communicator to share the `PetscViewer`
55
56 Output Parameter:
57 . viewer - the viewer
58
59 Level: beginner
60
61 Note:
62 Use `PetscViewerDestroy()` to destroy it
63
64 Developer Note:
65 This should be used in all PETSc source code instead of `PETSC_VIEWER_STDERR_()` since it allows error checking
66
67 .seealso: [](sec_viewers), `PetscViewerASCIIGetStdout()`, `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDERR_WORLD`,
68 `PETSC_VIEWER_STDERR_SELF`
69 @*/
PetscViewerASCIIGetStderr(MPI_Comm comm,PetscViewer * viewer)70 PetscErrorCode PetscViewerASCIIGetStderr(MPI_Comm comm, PetscViewer *viewer)
71 {
72 PetscMPIInt iflg;
73 MPI_Comm ncomm;
74
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 }
91
92 /*@C
93 PETSC_VIEWER_STDERR_ - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all MPI processes
94 in a communicator.
95
96 Collective
97
98 Input Parameter:
99 . comm - the MPI communicator to share the `PetscViewer`
100
101 Level: beginner
102
103 Notes:
104 This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it
105
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));
109
110 `PetscViewerASCIIGetStderr()` is preferred since it allows error checking
111
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 @*/
PETSC_VIEWER_STDERR_(MPI_Comm comm)115 PetscViewer PETSC_VIEWER_STDERR_(MPI_Comm comm)
116 {
117 PetscViewer viewer;
118
119 PetscFunctionBegin;
120 PetscCallNull(PetscViewerASCIIGetStderr(comm, &viewer));
121 PetscFunctionReturn(viewer);
122 }
123
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.
128
129 This is called by MPI, not by users.
130
131 */
Petsc_DelViewer(MPI_Comm comm,PetscMPIInt keyval,void * attr_val,void * extra_state)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 }
141
142 /*@
143 PetscViewerASCIIOpen - Opens an ASCII file for writing as a `PETSCVIEWERASCII` `PetscViewer`.
144
145 Collective
146
147 Input Parameters:
148 + comm - the communicator
149 - name - the file name
150
151 Output Parameter:
152 . viewer - the `PetscViewer` to use with the specified file
153
154 Level: beginner
155
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
164
165 This `PetscViewer` can be destroyed with `PetscViewerDestroy()`.
166
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`
169
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
176
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.
180
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 @*/
PetscViewerASCIIOpen(MPI_Comm comm,const char name[],PetscViewer * viewer)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;
191
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.
201
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 }
243
244 /*@C
245 PetscViewerASCIIOpenWithFILE - Given an open file creates an `PETSCVIEWERASCII` viewer that prints to it.
246
247 Collective
248
249 Input Parameters:
250 + comm - the communicator
251 - fd - the `FILE` pointer
252
253 Output Parameter:
254 . viewer - the `PetscViewer` to use with the specified file
255
256 Level: beginner
257
258 Notes:
259 This `PetscViewer` can be destroyed with `PetscViewerDestroy()`, but the fd will NOT be closed.
260
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.
264
265 Fortran Notes:
266 Use `PetscViewerASCIIOpenWithFileUnit()`
267
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 @*/
PetscViewerASCIIOpenWithFILE(MPI_Comm comm,FILE * fd,PetscViewer * viewer)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 }
280
281 /*@C
282 PetscViewerASCIISetFILE - Given an open file sets the `PETSCVIEWERASCII` viewer to use the file for output
283
284 Not Collective
285
286 Input Parameters:
287 + viewer - the `PetscViewer` to use with the specified file
288 - fd - the `FILE` pointer
289
290 Level: beginner
291
292 Notes:
293 This `PetscViewer` can be destroyed with `PetscViewerDestroy()`, but the `fd` will NOT be closed.
294
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.
298
299 Fortran Note:
300 Use `PetscViewerASCIISetFileUnit()`
301
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 @*/
PetscViewerASCIISetFILE(PetscViewer viewer,FILE * fd)306 PetscErrorCode PetscViewerASCIISetFILE(PetscViewer viewer, FILE *fd)
307 {
308 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
309
310 PetscFunctionBegin;
311 vascii->fd = fd;
312 vascii->closefile = PETSC_FALSE;
313 PetscFunctionReturn(PETSC_SUCCESS);
314 }
315