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