xref: /petsc/src/sys/classes/viewer/impls/ascii/vcreatea.c (revision 5c6496ba940341816c82c3b7fcda2e06e7ddfa20)
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 @*/
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);CHKERRMPI(ierr);
41   }
42   ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Stdout_keyval,(void**)viewer,(PetscMPIInt*)&flg);CHKERRMPI(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);CHKERRMPI(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 @*/
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 @*/
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);CHKERRMPI(ierr);
121   }
122   ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Stderr_keyval,(void**)viewer,(PetscMPIInt*)&flg);CHKERRMPI(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);CHKERRMPI(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 @*/
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 PetscMPIInt Petsc_Viewer_keyval = MPI_KEYVAL_INVALID;
164 /*
165    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
166    PetscObjectDestroyRegisterAll(). PetscViewerASCIIGetStdout() registers the viewer with PetscObjectDestroyRegister() to be destroyed when PetscFinalize() is called.
167 
168   This is called by MPI, not by users.
169 
170 */
171 PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelViewer(MPI_Comm comm,PetscMPIInt keyval,void *attr_val,void *extra_state)
172 {
173   PetscErrorCode ierr;
174 
175   PetscFunctionBegin;
176   ierr = PetscInfo(NULL,"Removing viewer data attribute in an MPI_Comm %ld\n",(long)comm);CHKERRMPI(ierr);
177   PetscFunctionReturn(MPI_SUCCESS);
178 }
179 
180 /*@C
181    PetscViewerASCIIOpen - Opens an ASCII file for writing as a PetscViewer.
182 
183    Collective
184 
185    Input Parameters:
186 +  comm - the communicator
187 -  name - the file name
188 
189    Output Parameter:
190 .  lab - the PetscViewer to use with the specified file
191 
192    Level: beginner
193 
194    Notes:
195    To open a ASCII file as a viewer for reading one must use the sequence
196 $     PetscViewerCreate(comm,&lab);
197 $     PetscViewerSetType(lab,PETSCVIEWERASCII);
198 $     PetscViewerFileSetMode(lab,FILE_MODE_READ);
199 $     PetscViewerFileSetName(lab,name);
200 
201    This PetscViewer can be destroyed with PetscViewerDestroy().
202 
203    The MPI communicator used here must match that used by the object one is viewing. For example if the
204    Mat was created with a PETSC_COMM_WORLD, then the Viewer must be created with PETSC_COMM_WORLD
205 
206    As shown below, PetscViewerASCIIOpen() is useful in conjunction with
207    MatView() and VecView()
208 .vb
209      PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat.output",&viewer);
210      MatView(matrix,viewer);
211 .ve
212 
213 .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerBinaryOpen(), PetscViewerASCIIRead()
214           PetscViewerASCIIGetPointer(), PetscViewerPushFormat(), PETSC_VIEWER_STDOUT_, PETSC_VIEWER_STDERR_,
215           PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF,
216 @*/
217 PetscErrorCode  PetscViewerASCIIOpen(MPI_Comm comm,const char name[],PetscViewer *lab)
218 {
219   PetscErrorCode  ierr;
220   PetscViewerLink *vlink,*nv;
221   PetscBool       flg,eq;
222   size_t          len;
223 
224   PetscFunctionBegin;
225   ierr = PetscStrlen(name,&len);CHKERRQ(ierr);
226   if (!len) {
227     ierr = PetscViewerASCIIGetStdout(comm,lab);CHKERRQ(ierr);
228     ierr = PetscObjectReference((PetscObject)*lab);CHKERRQ(ierr);
229     PetscFunctionReturn(0);
230   }
231   ierr = PetscSpinlockLock(&PetscViewerASCIISpinLockOpen);CHKERRQ(ierr);
232   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) {
233     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,Petsc_DelViewer,&Petsc_Viewer_keyval,(void*)0);CHKERRMPI(ierr);
234   }
235   /*
236        It would be better to move this code to PetscFileSetName() but since it must return a preexiting communicator
237      we cannot do that, since PetscFileSetName() takes a communicator that already exists.
238 
239       Plus if the original communicator that created the file has since been close this will not detect the old
240       communictor and hence will overwrite the old data. It may be better to simply remove all this code
241   */
242   /* make sure communicator is a PETSc communicator */
243   ierr = PetscCommDuplicate(comm,&comm,NULL);CHKERRQ(ierr);
244   /* has file already been opened into a viewer */
245   ierr = MPI_Comm_get_attr(comm,Petsc_Viewer_keyval,(void**)&vlink,(PetscMPIInt*)&flg);CHKERRMPI(ierr);
246   if (flg) {
247     while (vlink) {
248       ierr = PetscStrcmp(name,((PetscViewer_ASCII*)(vlink->viewer->data))->filename,&eq);CHKERRQ(ierr);
249       if (eq) {
250         ierr = PetscObjectReference((PetscObject)vlink->viewer);CHKERRQ(ierr);
251         *lab = vlink->viewer;
252         ierr = PetscCommDestroy(&comm);CHKERRQ(ierr);
253         ierr = PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen);CHKERRQ(ierr);
254         PetscFunctionReturn(0);
255       }
256       vlink = vlink->next;
257     }
258   }
259   ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr);
260   ierr = PetscViewerSetType(*lab,PETSCVIEWERASCII);CHKERRQ(ierr);
261   if (name) {
262     ierr = PetscViewerFileSetName(*lab,name);CHKERRQ(ierr);
263   }
264   /* save viewer into communicator if needed later */
265   ierr       = PetscNew(&nv);CHKERRQ(ierr);
266   nv->viewer = *lab;
267   if (!flg) {
268     ierr = MPI_Comm_set_attr(comm,Petsc_Viewer_keyval,nv);CHKERRMPI(ierr);
269   } else {
270     ierr = MPI_Comm_get_attr(comm,Petsc_Viewer_keyval,(void**)&vlink,(PetscMPIInt*)&flg);CHKERRMPI(ierr);
271     if (vlink) {
272       while (vlink->next) vlink = vlink->next;
273       vlink->next = nv;
274     } else {
275       ierr = MPI_Comm_set_attr(comm,Petsc_Viewer_keyval,nv);CHKERRMPI(ierr);
276     }
277   }
278   ierr = PetscCommDestroy(&comm);CHKERRQ(ierr);
279   ierr = PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen);CHKERRQ(ierr);
280   PetscFunctionReturn(0);
281 }
282 
283 /*@C
284    PetscViewerASCIIOpenWithFILE - Given an open file creates an ASCII viewer that prints to it.
285 
286    Collective
287 
288    Input Parameters:
289 +  comm - the communicator
290 -  fd - the FILE pointer
291 
292    Output Parameter:
293 .  lab - the PetscViewer to use with the specified file
294 
295    Level: beginner
296 
297    Notes:
298    This PetscViewer can be destroyed with PetscViewerDestroy(), but the fd will NOT be closed.
299 
300    If a multiprocessor communicator is used (such as PETSC_COMM_WORLD),
301    then only the first processor in the group uses the file.  All other
302    processors send their data to the first processor to print.
303 
304 .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerBinaryOpen(),
305           PetscViewerASCIIGetPointer(), PetscViewerPushFormat(), PETSC_VIEWER_STDOUT_, PETSC_VIEWER_STDERR_,
306           PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_STDOUT_SELF, PetscViewerASCIIOpen()
307 @*/
308 PetscErrorCode  PetscViewerASCIIOpenWithFILE(MPI_Comm comm,FILE *fd,PetscViewer *lab)
309 {
310   PetscErrorCode ierr;
311 
312   PetscFunctionBegin;
313   ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr);
314   ierr = PetscViewerSetType(*lab,PETSCVIEWERASCII);CHKERRQ(ierr);
315   ierr = PetscViewerASCIISetFILE(*lab,fd);CHKERRQ(ierr);
316   PetscFunctionReturn(0);
317 }
318 
319 PetscErrorCode  PetscViewerASCIISetFILE(PetscViewer viewer,FILE *fd)
320 {
321   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
322 
323   PetscFunctionBegin;
324   vascii->fd        = fd;
325   vascii->closefile = PETSC_FALSE;
326   PetscFunctionReturn(0);
327 }
328