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