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