xref: /petsc/src/sys/classes/viewer/impls/ascii/vcreatea.c (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
1 
2 #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h>  /*I     "petscsys.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 /*@C
13    PetscViewerASCIIGetStdout - Creates a ASCII PetscViewer shared by all processors
14                     in a communicator. Error returning version of PETSC_VIEWER_STDOUT_()
15 
16    Collective on MPI_Comm
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 @*/
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,0);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 on MPI_Comm
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 @*/
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(0);}
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 /*@C
93    PetscViewerASCIIGetStderr - Creates a ASCII PetscViewer shared by all processors
94                     in a communicator. Error returning version of PETSC_VIEWER_STDERR_()
95 
96    Collective on MPI_Comm
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 @*/
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,0);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 on MPI_Comm
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 @*/
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(0);}
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 */
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(0,"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 as a PetscViewer.
183 
184    Collective on MPI_Comm
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    This PetscViewer can be destroyed with PetscViewerDestroy().
197 
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
200 
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
207 
208   Concepts: PetscViewerASCII^creating
209   Concepts: printf
210   Concepts: printing
211   Concepts: accessing remote file
212   Concepts: remote file
213 
214 .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerBinaryOpen(),
215           PetscViewerASCIIGetPointer(), PetscViewerPushFormat(), PETSC_VIEWER_STDOUT_, PETSC_VIEWER_STDERR_,
216           PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF,
217 @*/
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 on MPI_Comm
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   Concepts: PetscViewerASCII^creating
306   Concepts: printf
307   Concepts: printing
308   Concepts: accessing remote file
309   Concepts: remote file
310 
311 .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerBinaryOpen(),
312           PetscViewerASCIIGetPointer(), PetscViewerPushFormat(), PETSC_VIEWER_STDOUT_, PETSC_VIEWER_STDERR_,
313           PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF, PetscViewerASCIIOpen()
314 @*/
315 PetscErrorCode  PetscViewerASCIIOpenWithFILE(MPI_Comm comm,FILE *fd,PetscViewer *lab)
316 {
317   PetscErrorCode ierr;
318 
319   PetscFunctionBegin;
320   ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr);
321   ierr = PetscViewerSetType(*lab,PETSCVIEWERASCII);CHKERRQ(ierr);
322   ierr = PetscViewerASCIISetFILE(*lab,fd);CHKERRQ(ierr);
323   PetscFunctionReturn(0);
324 }
325 
326 PetscErrorCode  PetscViewerASCIISetFILE(PetscViewer viewer,FILE *fd)
327 {
328   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
329 
330   PetscFunctionBegin;
331   vascii->fd        = fd;
332   vascii->closefile = PETSC_FALSE;
333   PetscFunctionReturn(0);
334 }
335 
336 
337 
338