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