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