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