xref: /petsc/src/sys/classes/viewer/interface/viewreg.c (revision 581c22b574bc9dee711e5db25f021d7222af108c)
1 
2 #include <petsc/private/viewerimpl.h>  /*I "petscviewer.h" I*/
3 #if defined(PETSC_HAVE_SAWS)
4 #include <petscviewersaws.h>
5 #endif
6 
7 PetscFunctionList PetscViewerList = 0;
8 
9 /*
10   Use a hash set to prevent the same help message from being printed multiple times
11 */
12 
13 #include "../src/sys/utils/hash.h"
14 
15 KHASH_SET_INIT_STR(PetscOptionsGetViewerPrinted)
16 static khash_t(PetscOptionsGetViewerPrinted) *PrintedOptions = NULL;
17 static PetscSegBuffer strings = NULL;
18 
19 static PetscErrorCode PetscOptionsGetViewerPrintedDestroy(void)
20 {
21   PetscErrorCode ierr;
22   kh_destroy(PetscOptionsGetViewerPrinted,PrintedOptions);
23   ierr = PetscSegBufferDestroy(&strings);CHKERRQ(ierr);
24   return 0;
25 }
26 
27 #undef __FUNCT__
28 #define __FUNCT__ "PetscOptionsGetViewer"
29 /*@C
30    PetscOptionsGetViewer - Gets a viewer appropriate for the type indicated by the user
31 
32    Collective on MPI_Comm
33 
34    Input Parameters:
35 +  comm - the communicator to own the viewer
36 .  pre - the string to prepend to the name or NULL
37 -  name - the option one is seeking
38 
39    Output Parameter:
40 +  viewer - the viewer, pass NULL if not needed
41 .  format - the PetscViewerFormat requested by the user, pass NULL if not needed
42 -  set - PETSC_TRUE if found, else PETSC_FALSE
43 
44    Level: intermediate
45 
46    Notes: If no value is provided ascii:stdout is used
47 $       ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
48                                                   for example ascii::ascii_info prints just the information about the object not all details
49                                                   unless :append is given filename opens in write mode, overwriting what was already there
50 $       binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
51 $       draw[:drawtype]                           for example, draw:tikz  or draw:x
52 $       socket[:port]                             defaults to the standard output port
53 $       saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
54 
55    Use PetscViewerDestroy() after using the viewer, otherwise a memory leak will occur
56 
57    If PETSc is configured with --with-viewfromoptions=0 this function always returns with *set of PETSC_FALSE
58 
59 .seealso: PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
60           PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
61           PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
62           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
63           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
64           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
65           PetscOptionsFList(), PetscOptionsEList()
66 @*/
67 PetscErrorCode  PetscOptionsGetViewer(MPI_Comm comm,const char pre[],const char name[],PetscViewer *viewer,PetscViewerFormat *format,PetscBool  *set)
68 {
69   char                 *value;
70   PetscErrorCode       ierr;
71   PetscBool            flag,hashelp;
72 
73   PetscFunctionBegin;
74   PetscValidCharPointer(name,3);
75 
76   if (set) *set = PETSC_FALSE;
77 #if defined(PETSC_SKIP_VIEWFROMOPTIONS)
78   PetscFunctionReturn(0);
79 #endif
80 
81   ierr = PetscOptionsHasName(NULL,NULL,"-help",&hashelp);CHKERRQ(ierr);
82   if (hashelp) {
83     khint_t newitem;
84     if (!PrintedOptions) {
85       PrintedOptions = kh_init(PetscOptionsGetViewerPrinted);
86       ierr = PetscSegBufferCreate(sizeof(char),10000,&strings);CHKERRQ(ierr);
87       ierr = PetscRegisterFinalize(PetscOptionsGetViewerPrintedDestroy);CHKERRQ(ierr);
88     }
89     if (!pre) {
90       kh_put(PetscOptionsGetViewerPrinted,PrintedOptions,name+1,&newitem);
91     } else {
92       size_t l1,l2;
93       char   *both;
94 
95       ierr = PetscStrlen(pre,&l1);CHKERRQ(ierr);
96       ierr = PetscStrlen(name+1,&l2);CHKERRQ(ierr);
97       ierr = PetscSegBufferGet(strings,l1+l2+1,&both);CHKERRQ(ierr);
98       ierr = PetscStrcpy(both,pre);CHKERRQ(ierr);
99       ierr = PetscStrcat(both,name+1);CHKERRQ(ierr);
100       kh_put(PetscOptionsGetViewerPrinted,PrintedOptions,both,&newitem);
101     }
102     if (newitem) {
103       if (viewer) {
104         ierr = (*PetscHelpPrintf)(comm,"\n  -%s%s ascii[:[filename][:[format][:append]]]: %s (%s)\n",pre ? pre : "",name+1,"Prints object to stdout or ASCII file","PetscOptionsGetViewer");CHKERRQ(ierr);
105         ierr = (*PetscHelpPrintf)(comm,"    -%s%s binary[:[filename][:[format][:append]]]: %s (%s)\n",pre ? pre : "",name+1,"Saves object to a binary file","PetscOptionsGetViewer");CHKERRQ(ierr);
106         ierr = (*PetscHelpPrintf)(comm,"    -%s%s draw[:drawtype]: %s (%s)\n",pre ? pre : "",name+1,"Draws object","PetscOptionsGetViewer");CHKERRQ(ierr);
107         ierr = (*PetscHelpPrintf)(comm,"    -%s%s socket[:port]: %s (%s)\n",pre ? pre : "",name+1,"Pushes object to a Unix socket","PetscOptionsGetViewer");CHKERRQ(ierr);
108         ierr = (*PetscHelpPrintf)(comm,"    -%s%s saws[:communicatorname]: %s (%s)\n\n",pre ? pre : "",name+1,"Publishes object to SAWs","PetscOptionsGetViewer");CHKERRQ(ierr);
109       } else {
110         ierr = (*PetscHelpPrintf)(comm,"    -%s%s\n",pre ? pre : "",name+1);CHKERRQ(ierr);
111       }
112     }
113   }
114 
115   if (format) *format = PETSC_VIEWER_DEFAULT;
116   ierr = PetscOptionsFindPair_Private(NULL,pre,name,&value,&flag);CHKERRQ(ierr);
117   if (flag) {
118     if (set) *set = PETSC_TRUE;
119     if (!value) {
120       if (viewer) {
121         ierr = PetscViewerASCIIGetStdout(comm,viewer);CHKERRQ(ierr);
122         ierr = PetscObjectReference((PetscObject)*viewer);CHKERRQ(ierr);
123       }
124     } else {
125       char       *loc0_vtype,*loc1_fname,*loc2_fmt = NULL,*loc3_fmode = NULL;
126       PetscInt   cnt;
127       const char *viewers[] = {PETSCVIEWERASCII,PETSCVIEWERBINARY,PETSCVIEWERDRAW,PETSCVIEWERSOCKET,PETSCVIEWERMATLAB,PETSCVIEWERSAWS,PETSCVIEWERVTK,PETSCVIEWERHDF5,0};
128 
129       ierr = PetscStrallocpy(value,&loc0_vtype);CHKERRQ(ierr);
130       ierr = PetscStrchr(loc0_vtype,':',&loc1_fname);CHKERRQ(ierr);
131       if (loc1_fname) {
132         *loc1_fname++ = 0;
133         ierr = PetscStrchr(loc1_fname,':',&loc2_fmt);CHKERRQ(ierr);
134       }
135       if (loc2_fmt) {
136         *loc2_fmt++ = 0;
137         ierr = PetscStrchr(loc2_fmt,':',&loc3_fmode);CHKERRQ(ierr);
138       }
139       if (loc3_fmode) *loc3_fmode++ = 0;
140       ierr = PetscStrendswithwhich(*loc0_vtype ? loc0_vtype : "ascii",viewers,&cnt);CHKERRQ(ierr);
141       if (cnt > (PetscInt) sizeof(viewers)-1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Unknown viewer type: %s",loc0_vtype);
142       if (viewer) {
143         if (!loc1_fname) {
144           switch (cnt) {
145           case 0:
146             ierr = PetscViewerASCIIGetStdout(comm,viewer);CHKERRQ(ierr);
147             break;
148           case 1:
149             if (!(*viewer = PETSC_VIEWER_BINARY_(comm))) CHKERRQ(PETSC_ERR_PLIB);
150             break;
151           case 2:
152             if (!(*viewer = PETSC_VIEWER_DRAW_(comm))) CHKERRQ(PETSC_ERR_PLIB);
153             break;
154 #if defined(PETSC_USE_SOCKET_VIEWER)
155           case 3:
156             if (!(*viewer = PETSC_VIEWER_SOCKET_(comm))) CHKERRQ(PETSC_ERR_PLIB);
157             break;
158 #endif
159 #if defined(PETSC_HAVE_MATLAB_ENGINE)
160           case 4:
161             if (!(*viewer = PETSC_VIEWER_MATLAB_(comm))) CHKERRQ(PETSC_ERR_PLIB);
162             break;
163 #endif
164 #if defined(PETSC_HAVE_SAWS)
165           case 5:
166             if (!(*viewer = PETSC_VIEWER_SAWS_(comm))) CHKERRQ(PETSC_ERR_PLIB);
167             break;
168 #endif
169 #if defined(PETSC_HAVE_HDF5)
170           case 7:
171             if (!(*viewer = PETSC_VIEWER_HDF5_(comm))) CHKERRQ(PETSC_ERR_PLIB);
172             break;
173 #endif
174           default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported viewer %s",loc0_vtype);
175           }
176           ierr = PetscObjectReference((PetscObject)*viewer);CHKERRQ(ierr);
177         } else {
178           if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */
179             ierr = PetscViewerASCIIGetStdout(comm,viewer);CHKERRQ(ierr);
180             ierr = PetscObjectReference((PetscObject)*viewer);CHKERRQ(ierr);
181           } else {
182             PetscFileMode fmode;
183             ierr = PetscViewerCreate(comm,viewer);CHKERRQ(ierr);
184             ierr = PetscViewerSetType(*viewer,*loc0_vtype ? loc0_vtype : "ascii");CHKERRQ(ierr);
185             fmode = FILE_MODE_WRITE;
186             if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */
187               ierr = PetscEnumFind(PetscFileModes,loc3_fmode,(PetscEnum*)&fmode,&flag);CHKERRQ(ierr);
188               if (!flag) SETERRQ1(comm,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown file mode: %s",loc3_fmode);
189             }
190             ierr = PetscViewerFileSetMode(*viewer,flag?fmode:FILE_MODE_WRITE);CHKERRQ(ierr);
191             ierr = PetscViewerFileSetName(*viewer,loc1_fname);CHKERRQ(ierr);
192             ierr = PetscViewerDrawSetDrawType(*viewer,loc1_fname);CHKERRQ(ierr);
193           }
194         }
195       }
196       if (viewer) {
197         ierr = PetscViewerSetUp(*viewer);CHKERRQ(ierr);
198       }
199       if (loc2_fmt && *loc2_fmt) {
200         ierr = PetscEnumFind(PetscViewerFormats,loc2_fmt,(PetscEnum*)format,&flag);CHKERRQ(ierr);
201         if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer format %s",loc2_fmt);CHKERRQ(ierr);
202       }
203       ierr = PetscFree(loc0_vtype);CHKERRQ(ierr);
204     }
205   }
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "PetscViewerCreate"
211 /*@
212    PetscViewerCreate - Creates a viewing context
213 
214    Collective on MPI_Comm
215 
216    Input Parameter:
217 .  comm - MPI communicator
218 
219    Output Parameter:
220 .  inviewer - location to put the PetscViewer context
221 
222    Level: advanced
223 
224    Concepts: graphics^creating PetscViewer
225    Concepts: file input/output^creating PetscViewer
226    Concepts: sockets^creating PetscViewer
227 
228 .seealso: PetscViewerDestroy(), PetscViewerSetType(), PetscViewerType
229 
230 @*/
231 PetscErrorCode  PetscViewerCreate(MPI_Comm comm,PetscViewer *inviewer)
232 {
233   PetscViewer    viewer;
234   PetscErrorCode ierr;
235 
236   PetscFunctionBegin;
237   *inviewer = 0;
238   ierr = PetscViewerInitializePackage();CHKERRQ(ierr);
239   ierr         = PetscHeaderCreate(viewer,PETSC_VIEWER_CLASSID,"PetscViewer","PetscViewer","Viewer",comm,PetscViewerDestroy,NULL);CHKERRQ(ierr);
240   *inviewer    = viewer;
241   viewer->data = 0;
242   PetscFunctionReturn(0);
243 }
244 
245 #undef __FUNCT__
246 #define __FUNCT__ "PetscViewerSetType"
247 /*@C
248    PetscViewerSetType - Builds PetscViewer for a particular implementation.
249 
250    Collective on PetscViewer
251 
252    Input Parameter:
253 +  viewer      - the PetscViewer context
254 -  type        - for example, PETSCVIEWERASCII
255 
256    Options Database Command:
257 .  -draw_type  <type> - Sets the type; use -help for a list
258     of available methods (for instance, ascii)
259 
260    Level: advanced
261 
262    Notes:
263    See "include/petscviewer.h" for available methods (for instance,
264    PETSCVIEWERSOCKET)
265 
266 .seealso: PetscViewerCreate(), PetscViewerGetType(), PetscViewerType, PetscViewerPushFormat()
267 @*/
268 PetscErrorCode  PetscViewerSetType(PetscViewer viewer,PetscViewerType type)
269 {
270   PetscErrorCode ierr,(*r)(PetscViewer);
271   PetscBool      match;
272 
273   PetscFunctionBegin;
274   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
275   PetscValidCharPointer(type,2);
276   ierr = PetscObjectTypeCompare((PetscObject)viewer,type,&match);CHKERRQ(ierr);
277   if (match) PetscFunctionReturn(0);
278 
279   /* cleanup any old type that may be there */
280   if (viewer->data) {
281     ierr         = (*viewer->ops->destroy)(viewer);CHKERRQ(ierr);
282 
283     viewer->ops->destroy = NULL;
284     viewer->data         = 0;
285   }
286   ierr = PetscMemzero(viewer->ops,sizeof(struct _PetscViewerOps));CHKERRQ(ierr);
287 
288   ierr =  PetscFunctionListFind(PetscViewerList,type,&r);CHKERRQ(ierr);
289   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown PetscViewer type given: %s",type);
290 
291   ierr = PetscObjectChangeTypeName((PetscObject)viewer,type);CHKERRQ(ierr);
292   ierr = (*r)(viewer);CHKERRQ(ierr);
293   PetscFunctionReturn(0);
294 }
295 
296 #undef __FUNCT__
297 #define __FUNCT__ "PetscViewerRegister"
298 /*@C
299    PetscViewerRegister - Adds a viewer
300 
301    Not Collective
302 
303    Input Parameters:
304 +  name_solver - name of a new user-defined viewer
305 -  routine_create - routine to create method context
306 
307    Level: developer
308    Notes:
309    PetscViewerRegister() may be called multiple times to add several user-defined viewers.
310 
311    Sample usage:
312 .vb
313    PetscViewerRegister("my_viewer_type",MyViewerCreate);
314 .ve
315 
316    Then, your solver can be chosen with the procedural interface via
317 $     PetscViewerSetType(viewer,"my_viewer_type")
318    or at runtime via the option
319 $     -viewer_type my_viewer_type
320 
321   Concepts: registering^Viewers
322 
323 .seealso: PetscViewerRegisterAll(), PetscViewerRegisterDestroy()
324  @*/
325 PetscErrorCode  PetscViewerRegister(const char *sname,PetscErrorCode (*function)(PetscViewer))
326 {
327   PetscErrorCode ierr;
328 
329   PetscFunctionBegin;
330   ierr = PetscFunctionListAdd(&PetscViewerList,sname,function);CHKERRQ(ierr);
331   PetscFunctionReturn(0);
332 }
333 
334 #undef __FUNCT__
335 #define __FUNCT__ "PetscViewerSetFromOptions"
336 /*@C
337    PetscViewerSetFromOptions - Sets the graphics type from the options database.
338       Defaults to a PETSc X windows graphics.
339 
340    Collective on PetscViewer
341 
342    Input Parameter:
343 .     PetscViewer - the graphics context
344 
345    Level: intermediate
346 
347    Notes:
348     Must be called after PetscViewerCreate() before the PetscViewer is used.
349 
350   Concepts: PetscViewer^setting options
351 
352 .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerType
353 
354 @*/
355 PetscErrorCode  PetscViewerSetFromOptions(PetscViewer viewer)
356 {
357   PetscErrorCode    ierr;
358   char              vtype[256];
359   PetscBool         flg;
360 
361   PetscFunctionBegin;
362   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
363 
364   if (!PetscViewerList) {
365     ierr = PetscViewerRegisterAll();CHKERRQ(ierr);
366   }
367   ierr = PetscObjectOptionsBegin((PetscObject)viewer);CHKERRQ(ierr);
368   ierr = PetscOptionsFList("-viewer_type","Type of PetscViewer","None",PetscViewerList,(char*)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII),vtype,256,&flg);CHKERRQ(ierr);
369   if (flg) {
370     ierr = PetscViewerSetType(viewer,vtype);CHKERRQ(ierr);
371   }
372   /* type has not been set? */
373   if (!((PetscObject)viewer)->type_name) {
374     ierr = PetscViewerSetType(viewer,PETSCVIEWERASCII);CHKERRQ(ierr);
375   }
376   if (viewer->ops->setfromoptions) {
377     ierr = (*viewer->ops->setfromoptions)(PetscOptionsObject,viewer);CHKERRQ(ierr);
378   }
379 
380   /* process any options handlers added with PetscObjectAddOptionsHandler() */
381   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)viewer);CHKERRQ(ierr);
382   ierr = PetscViewerViewFromOptions(viewer,NULL,"-viewer_view");CHKERRQ(ierr);
383   ierr = PetscOptionsEnd();CHKERRQ(ierr);
384   PetscFunctionReturn(0);
385 }
386 
387 #undef __FUNCT__
388 #define __FUNCT__ "PetscViewerFlowControlStart"
389 PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer,PetscInt *mcnt,PetscInt *cnt)
390 {
391   PetscErrorCode ierr;
392   PetscFunctionBegin;
393   ierr = PetscViewerBinaryGetFlowControl(viewer,mcnt);CHKERRQ(ierr);
394   ierr = PetscViewerBinaryGetFlowControl(viewer,cnt);CHKERRQ(ierr);
395   PetscFunctionReturn(0);
396 }
397 
398 #undef __FUNCT__
399 #define __FUNCT__ "PetscViewerFlowControlStepMaster"
400 PetscErrorCode PetscViewerFlowControlStepMaster(PetscViewer viewer,PetscInt i,PetscInt *mcnt,PetscInt cnt)
401 {
402   PetscErrorCode ierr;
403   MPI_Comm       comm;
404 
405   PetscFunctionBegin;
406   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
407   if (i >= *mcnt) {
408     *mcnt += cnt;
409     ierr = MPI_Bcast(mcnt,1,MPIU_INT,0,comm);CHKERRQ(ierr);
410   }
411   PetscFunctionReturn(0);
412 }
413 
414 #undef __FUNCT__
415 #define __FUNCT__ "PetscViewerFlowControlEndMaster"
416 PetscErrorCode PetscViewerFlowControlEndMaster(PetscViewer viewer,PetscInt *mcnt)
417 {
418   PetscErrorCode ierr;
419   MPI_Comm       comm;
420   PetscFunctionBegin;
421   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
422   *mcnt = 0;
423   ierr = MPI_Bcast(mcnt,1,MPIU_INT,0,comm);CHKERRQ(ierr);
424   PetscFunctionReturn(0);
425 }
426 
427 #undef __FUNCT__
428 #define __FUNCT__ "PetscViewerFlowControlStepWorker"
429 PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer,PetscMPIInt rank,PetscInt *mcnt)
430 {
431   PetscErrorCode ierr;
432   MPI_Comm       comm;
433   PetscFunctionBegin;
434   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
435   while (PETSC_TRUE) {
436     if (rank < *mcnt) break;
437     ierr = MPI_Bcast(mcnt,1,MPIU_INT,0,comm);CHKERRQ(ierr);
438   }
439   PetscFunctionReturn(0);
440 }
441 
442 #undef __FUNCT__
443 #define __FUNCT__ "PetscViewerFlowControlEndWorker"
444 PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer,PetscInt *mcnt)
445 {
446   PetscErrorCode ierr;
447   MPI_Comm       comm;
448   PetscFunctionBegin;
449   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
450   while (PETSC_TRUE) {
451     ierr = MPI_Bcast(mcnt,1,MPIU_INT,0,comm);CHKERRQ(ierr);
452     if (!*mcnt) break;
453   }
454   PetscFunctionReturn(0);
455 }
456