1    | /***************************************
2    |   $Header: /cvsroot/petscgraphics/tsview.c,v 1.43 2006/01/30 04:53:58 hazelsct Exp $
3    | 
4    |   This program views the output of a time series saved using
5    |   +latex+{\tt IlluMultiSave()}.
6    |   +html+ <tt>IlluMultiSave()</tt>.
7    |   It basically just switches between timesteps; future versions may be more
8    |   interesting.  The neat part of it is that it loads multiprocessor data and
9    |   displays it on a single CPU.
10   |   ***************************************/
11   | 
12   | static char help[] = "Displays the output of of a timestep series saved using IlluMultiSave().\n\
13   | Usage:\n\
14   | \n\
15   |   tsview <basename> [-no_transparency]\n\
16   | \n\
17   | Then interactively flip through the timesteps (h or ? lists commands).\n";
18   | 
19   | #define HELP_STRING "tsview commands:\n\
20   |   <enter>       Display next timestep\n\
21   |   b             Display previous timestep\n\
22   |   i increment   Set the next timestep increment\n\
23   |   ###           Jump to timestep ###\n\
24   |   t             Toggle Geomview transparency (3-D only)\n\
25   |   v             Change field displayed (3-D only)\n\
26   |   d             Dump geomview to picture (3-D only), creates basename-f%d.ppm\n\
27   |   a             Dump all timesteps to pictures (3-D only)\n\
28   |   p [v1 v2 ...] Set contour values for plotting or \"auto\" (3-D only)\n\
29   |   r             Reloads entries in a directory\n\
30   |   s size        Set maximum dimension of PETSc viewer windows (2-D only)\n\
31   |   cx, cy, cz    Toggle xcut, ycut, zcut (cut last row/plane of periodic DA)\n\
32   |   gx30-90, y,z  Set plot x range to 30-90, same for y and z\n\
33   |   h/?           Print this information\n\
34   |   q/x           Quit tsview\n"
35   | 
36   | #include "illuminator.h"
37   | #include <sys/dir.h> /* For scandir(), alphasort, struct dirent */
38   | #include <libgen.h>  /* For dirname(), basename() */
39   | #include <string.h>  /* For strdup() */
40   | #include <stdlib.h>            /* Needed for readline stuff below */
41   | #include <term.h>              /* ncurses header for readline */
42   | #include <readline/readline.h> /* For command line editing */
43   | #include <readline/history.h>  /* For command line history */
44   | 
45   | /* Build with -DDEBUG for debugging output */
46   | #undef DPRINTF
47   | #ifdef DEBUG
48   | #define DPRINTF(fmt, args...) PetscPrintf (PETSC_COMM_WORLD, "%s: " fmt, __FUNCT__, args)
49   | #else
50   | #define DPRINTF(fmt, args...)
51   | #endif
52   | 
53   | char *basefilename;
54   | 
55   | 
56   | #undef __FUNCT__
57   | #define __FUNCT__ "myfilter"
58   | 
59   | /*++++++++++++++++++++++++++++++++++++++
60   |   This function returns non-zero for "qualifying" file names which start with
61   |   the stored files' basename and end with
62   |   +latex+{\tt .cpu0000.meta}.
63   |   +html+ <tt>.cpu0000.meta</tt>.
64   |   It is used as the
65   |   +latex+{\tt select()} function for {\tt scandir()} in {\tt main()}.
66   |   +html+ <tt>select()</tt> function for <tt>scandir()</tt> in <tt>main()</tt>.
67   | 
68   |   int myfilter Returns non-zero for qualifying filenames.
69   | 
70   |   const struct dirent *direntry Directory entry with filename to test.
71   |   ++++++++++++++++++++++++++++++++++++++*/
72   | 
73   | int myfilter (const struct dirent *direntry)
74   | {
75   |   if ((!strncmp (direntry->d_name, basefilename, strlen(basefilename))))
76   |     return (!strncmp (direntry->d_name + strlen(direntry->d_name) - 13,
77   | 		      ".cpu0000.meta", 13));
78   |   return 0;
79   | }
80   | 
81   | 
82   | /*+++++++++++++++++++++++++++++++++++++
83   | 
84   | Functions for reading the command line
85   | and avoiding reading empty lines
86   | 
87   | Probably this function is not Petsc
88   | safe, but we'll see.
89   | 
90   | +++++++++++++++++++++++++++++++++++++*/
91   | 
92   | /* A static variable for holding the line. */
93   | static char *line_read = (char *)NULL;
94   | 
95   | /* Read a string, and return a pointer to it.
96   |    Returns NULL on EOF. */
97   | 
98   | 
99   | 
100  | char* rl_gets (char* message)
101  | {
102  |   /* If the buffer has already been allocated,
103  |      return the memory to the free pool. */
104  |   if (line_read)
105  |     {
106  |       free (line_read);
107  |       line_read = (char *)NULL;
108  |     }
109  | 
110  |   /* Get a line from the user. */
111  |   line_read = readline (message);
112  | 
113  |   /* If the line has any text in it,
114  |      save it on the history. */
115  |   if (line_read && *line_read)
116  |     add_history (line_read);
117  | 
118  |   return (line_read);
119  | }
120  | 
121  | 
122  | /*
123  |   Failed attempt to make a Petsc safe readline
124  |   Lefted here for reference
125  | 
126  |   It is based on PetscSynchronizedFGets, but instead of using
127  |   fgets() it uses rl_gets()
128  | 
129  | */
130  | 
131  | int PetscSynchronizedFReadline(MPI_Comm comm,char* message,char* string)
132  | {
133  |   int ierr,rank, len;
134  |   PetscFunctionBegin;
135  |   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
136  | 
137  |   /* First processor prints immediately to stdin*/
138  |   if (!rank) {
139  |     string = rl_gets(message);
140  |   }
141  |   
142  |   len = strlen(string);
143  | 
144  |   ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr);
145  |   PetscFunctionReturn(0);
146  | }
147  | 
148  | 
149  | #undef __FUNCT__
150  | #define __FUNCT__ "main"
151  | 
152  | /*++++++++++++++++++++++++++++++++++++++
153  |   This is
154  |   +latex+{\tt main()}.
155  |   +html+ <tt>main()</tt>.
156  | 
157  |   int main It returns an int to the OS.
158  | 
159  |   int argc Argument count.
160  | 
161  |   char *argv[] Arguments.
162  |   ++++++++++++++++++++++++++++++++++++++*/
163  | 
164  | int main (int argc, char *argv[])
165  | {
166  |   int total_entries, current_entry, dims, i, ierr, windowsize=300, plots=0,
167  |     increment=1, xmin=0,xmax=-1, ymin=0,ymax=-1, zmin=0,zmax=-1;
168  |   struct dirent **namelist;
169  |   char **files, *thefilename, *filec, *dirc, *basedirname;
170  |   PetscViewer theviewer;
171  |   PetscTruth loaded = PETSC_FALSE, transp=PETSC_TRUE;
172  | 
173  |   if (argc<2)
174  |     {
175  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "Usage: tsview basename\n");
176  |       CHKERRQ (ierr);
177  |       return 1;
178  |     }
179  | 
180  |   /*+ After
181  |     +latex+{\tt PETSc}
182  |     +html+ <tt>PETSc</tt>
183  |     initialization, it gets the list of files matching the basename. +*/
184  |   ierr = PetscInitialize (&argc, &argv, (char *)0, help); CHKERRQ (ierr);
185  | 
186  |   DPRINTF ("Command line:",0); CHKERRQ (ierr);
187  | #ifdef DEBUG
188  |   for (i=0; i<argc; i++)
189  |     {
190  |       ierr = PetscPrintf (PETSC_COMM_WORLD, " %s", argv[i]); CHKERRQ (ierr);
191  |     }
192  |   ierr = PetscPrintf (PETSC_COMM_WORLD, "\n"); CHKERRQ (ierr);
193  | #endif
194  | 
195  |   filec = strdup (argv[1]);
196  |   dirc = strdup (argv[1]);
197  |   basefilename = basename (filec);
198  |   basedirname = dirname (dirc);
199  | 
200  |   ierr = PetscOptionsHasName (PETSC_NULL, "-no_transparency", &transp);
201  |   CHKERRQ (ierr);
202  |   transp = !transp;
203  | 
204  |   total_entries = scandir (basedirname, &namelist, myfilter, alphasort);
205  |   if (!total_entries)
206  |     {
207  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "No such files, exiting\n");
208  |       CHKERRQ (ierr);
209  |       exit (1);
210  |     }
211  |   if (total_entries < 0)
212  |     {
213  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "Error scanning directory %s\n",
214  | 			  basedirname); CHKERRQ (ierr);
215  |       ierr = PetscFinalize (); CHKERRQ(ierr);
216  |       return 1;
217  |     }
218  |   ierr = PetscPrintf (PETSC_COMM_WORLD, "%d eligible files:\n", total_entries);
219  |   CHKERRQ (ierr);
220  | 
221  |   if (!(files = (char **) malloc (total_entries * sizeof (char *))))
222  |     {
223  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "Error allocating memory\n");
224  |       CHKERRQ (ierr);
225  |       ierr = PetscFinalize (); CHKERRQ(ierr);
226  |       return 1;
227  |     }
228  |   for (i=0; i<total_entries; i++)
229  |     {
230  |       int filength = strlen(namelist[i]->d_name);
231  | 
232  |       files [i] = (char *) malloc ((filength-12)*sizeof(char));
233  |       strncpy (files [i], namelist[i]->d_name, filength-13);
234  |       files [i] [filength-13] = '\0';
235  |       free (namelist[i]);
236  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "[%d] %s\n", i, files [i]);
237  |       CHKERRQ (ierr);
238  |     }
239  |   free (namelist);
240  | 
241  |   /*+In the main loop, the various timesteps are displayed, with options:
242  |     +latex+\begin{itemize} \item
243  |     +html+ <ul><li>
244  |     A number jumps to that entry in the files table.
245  |     +latex+\item {\stt <return>}
246  |     +html+ <li><tt>&lt;return&gt;</tt>
247  |     loads the next file.
248  |     +latex+\item {\tt b}
249  |     +html+ <li><tt>b</tt>
250  |     goes back one file.
251  |     +latex+\item {\tt q}
252  |     +html+ <li><tt>q</tt>
253  |     quits the program.
254  |     +latex+\end{itemize}
255  |     +html+ </ul>
256  |     +*/
257  |   current_entry=0;
258  |   while (1)
259  |     {
260  |       DA theda;
261  |       Vec global;
262  |       int usermetacount=0, fields, display_field;
263  |       char basis [strlen(argv[1]) + 20], **usermetanames, **usermetadata,
264  | 	*instring;
265  |       PetscScalar minmax[6], plot_vals[6], plot_colors[24] =
266  | 	{ 1.,0.,0.,.5, 1.,1.,0.,.5, 0.,1.,0.,.5, 0.,1.,1.,.5, 0.,0.,1.,.5,
267  | 	  1.,0.,1.,.5 };
268  |       field_plot_type *fieldtypes;
269  |       ISurface Surf;
270  |       IDisplay Disp;
271  | 
272  |       /* Load the vector */
273  |       strcpy (basis, basedirname);
274  |       strcat (basis, "/");
275  |       strcat (basis, files[current_entry]);
276  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "Loading entry %d, basename %s\n",
277  | 			  current_entry, basis);
278  |       if (loaded)
279  | 	{
280  | 	  ierr = IlluMultiRead (PETSC_COMM_WORLD, theda, global, basis,
281  | 				&usermetacount, &usermetanames, &usermetadata);
282  | 	  CHKERRQ (ierr);
283  | 	}
284  |       else
285  | 	{
286  | 	  DPRINTF ("Loading first timestep, creating distributed array\n",0);
287  | 	  display_field = 0;
288  | 	  minmax [0] = minmax [2] = minmax [4] = 0.;
289  | 	  minmax [1] = minmax [3] = minmax [5] = 1.;
290  | 	  ierr = IlluMultiLoad
291  | 	    (PETSC_COMM_WORLD, basis, &theda, minmax+1, minmax+3, minmax+5,
292  | 	     &fieldtypes, &usermetacount, &usermetanames, &usermetadata);
293  | 	  CHKERRQ (ierr);
294  | 	  ierr = DAGetGlobalVector (theda, &global); CHKERRQ (ierr);
295  | 	  loaded = PETSC_TRUE;
296  | 
297  | 	  ierr = DAGetInfo (theda, &dims, PETSC_NULL,PETSC_NULL,PETSC_NULL,
298  | 			    PETSC_NULL,PETSC_NULL,PETSC_NULL, &fields,
299  | 			    PETSC_NULL,PETSC_NULL,PETSC_NULL); CHKERRQ (ierr);
300  | 
301  | 	  /* Usermetadata xwidth, ywidth, zwidth override minmax in case
302  | 	     version is 0.1. */
303  | 	  for (i=0; i<usermetacount; i++)
304  | 	    {
305  | 	      if (!strncmp (usermetanames [i], "xwidth", 6))
306  | 		sscanf (usermetadata [i], "%lf", minmax+1);
307  | 	      else if (!strncmp (usermetanames [i], "ywidth", 6))
308  | 		sscanf (usermetadata [i], "%lf", minmax+3);
309  | 	      else if (!strncmp (usermetanames [i], "zwidth", 6))
310  | 		sscanf (usermetadata [i], "%lf", minmax+5);
311  | 	    }
312  | 
313  | 	  if (dims<3)
314  | 	    {
315  | 	      int width=windowsize, height=windowsize;
316  | 
317  | 	      ierr = PetscPrintf (PETSC_COMM_WORLD,
318  | 				  "For viewing 2-D data, try tsview-ng!\n");
319  | 	      CHKERRQ (ierr);
320  | 
321  | 	      if (minmax[1]<minmax[3])
322  | 		width  *= minmax[1]/minmax[3];
323  | 	      else
324  | 		height *= minmax[3]/minmax[1];
325  | 
326  | 	      ierr = PetscViewerDrawOpen
327  | 		(PETSC_COMM_WORLD, 0, "", PETSC_DECIDE, PETSC_DECIDE,
328  | 		 width, height, &theviewer); CHKERRQ (ierr);
329  | 	    }
330  | 	  else
331  | 	    {
332  | #ifdef GEOMVIEW
333  | 	      ierr = SurfCreate (&Surf); CHKERRQ (ierr);
334  | 	      ierr = GeomviewBegin (PETSC_COMM_WORLD, &Disp); CHKERRQ (ierr);
335  | #else
336  | 	      SETERRQ (PETSC_ERR_SUP,
337  | 		       "Built without Geomview, which is needed for 3-D");
338  | #endif
339  | 	    }
340  | 	}
341  | 
342  |       /* Print user data */
343  |       ierr = PetscPrintf (PETSC_COMM_WORLD, "User data:\n"); CHKERRQ (ierr);
344  |       for (i=0; i<usermetacount; i++)
345  | 	{
346  | 	  ierr = PetscPrintf (PETSC_COMM_WORLD, "%s = %s\n", usermetanames [i],
347  | 			      usermetadata [i]); CHKERRQ (ierr);
348  | 	}
349  | 
350  |       /* View the vector */
351  |       if (dims<3)
352  | 	{
353  | 	  ierr = VecView (global, theviewer); CHKERRQ (ierr);
354  | 	}
355  |       else
356  | 	{
357  | 	  /*+ The Illuminator-based 3-D viewer can only display one field at a
358  | 	    time.  At the beginning, that is field 0, and is cycled using the
359  | 	    +latex+{\tt v}
360  | 	    +html+ <tt>v</tt>
361  | 	    command. +*/
362  | 	  PetscScalar minval, maxval;
363  | 	  char *fieldname;
364  | 
365  | 	  ierr = VecStrideMin (global, display_field, PETSC_NULL, &minval);
366  | 	  CHKERRQ (ierr);
367  | 	  ierr = VecStrideMax (global, display_field, PETSC_NULL, &maxval);
368  | 	  CHKERRQ (ierr);
369  | 	  ierr = DAGetFieldName (theda, display_field, &fieldname);
370  | 	  CHKERRQ (ierr);
371  | 	  ierr = PetscPrintf (PETSC_COMM_WORLD,
372  | 			      "Displaying field %d [%g-%g]: %s\n",
373  | 			      display_field, minval, maxval, fieldname);
374  | 	  CHKERRQ (ierr);
375  | 
376  | 	  DPRINTF ("Calculating triangle locations\n",0);
377  | 	  if (plots)
378  | 	    {
379  | 	      ierr = DATriangulateRange (Surf, theda, global, display_field,
380  | 					 minmax, plots, plot_vals, plot_colors,
381  | 					 xmin,xmax, ymin,ymax, zmin,zmax);
382  | 	      CHKERRQ (ierr);
383  | 	    }
384  | 	  else
385  | 	    {
386  | 	      ierr = DATriangulateRange (Surf, theda, global, display_field,
387  | 					 minmax, PETSC_DECIDE, PETSC_NULL,
388  | 					 PETSC_NULL, xmin,xmax, ymin,ymax,
389  | 					 zmin,zmax);
390  | 	      CHKERRQ (ierr);
391  | 	    }
392  | #ifdef GEOMVIEW
393  | 	  DPRINTF ("Consolidating triangles on head node and visualizing\n",0);
394  | 	  ierr = GeomviewDisplayTriangulation
395  | 	    (PETSC_COMM_WORLD, Surf, Disp, minmax, fieldname, transp);
396  | 	  CHKERRQ (ierr);
397  | #endif
398  | 	  ierr = SurfClear (Surf); CHKERRQ (ierr);
399  | 	}
400  | 
401  |       /* Free user data */
402  |       for (i=0; i<usermetacount; i++)
403  | 	{
404  | 	  free (usermetanames [i]);
405  | 	  free (usermetadata [i]);
406  | 	}
407  |       free (usermetanames);
408  |       free (usermetadata);
409  | 
410  |       /* Get user input */
411  |       /* ierr = PetscPrintf (PETSC_COMM_WORLD, "What to do? (h for options) ");
412  |       CHKERRQ (ierr);
413  |       ierr = PetscSynchronizedFGets (PETSC_COMM_WORLD, stdin, 99, instring);
414  |       CHKERRQ (ierr); */
415  |       /* This is probably not PETSc-safe */
416  |       instring = rl_gets("What to do? (h for options)> ");
417  | 
418  |       switch (instring [0])
419  | 	{
420  | 	case 'q':
421  | 	case 'Q':
422  | 	case 'x':
423  | 	case 'X':
424  | 	  {
425  | 	    if (dims < 3)
426  | 	      {
427  | 		ierr = PetscViewerDestroy (theviewer); CHKERRQ (ierr);
428  | 	      }
429  | 	    else
430  | 	      {
431  | #ifdef GEOMVIEW
432  | 		ierr = GeomviewEnd (PETSC_COMM_WORLD, Disp); CHKERRQ (ierr);
433  | #endif
434  | 		ierr = ISurfDestroy (Surf); CHKERRQ (ierr);
435  | 	      }
436  | 	    ierr = PetscFinalize(); CHKERRQ (ierr);
437  | 	    return 0;
438  | 	  }
439  | 	case 't':
440  | 	case 'T':
441  | 	  {
442  | 	    transp=!transp;
443  | 	    break;
444  | 	  }
445  | 	case 'h':
446  | 	case 'H':
447  | 	case '?':
448  | 	  {
449  | 	    ierr = PetscPrintf (PETSC_COMM_WORLD, HELP_STRING);
450  | 	    break;
451  | 	  }
452  | 	case '0':
453  | 	case '1':
454  | 	case '2':
455  | 	case '3':
456  | 	case '4':
457  | 	case '5':
458  | 	case '6':
459  | 	case '7':
460  | 	case '8':
461  | 	case '9':
462  | 	  {
463  | 	    current_entry = atoi (instring);
464  | 	    break;
465  | 	  }
466  | 	case 'b':
467  | 	case 'B':
468  | 	  {
469  | 	    current_entry--;
470  | 	    break;
471  | 	  }
472  | 	case 'i':
473  | 	case 'I':
474  | 	  {
475  | 	    /* printf ("instring=\"%s\"\n",instring); */
476  | 	    if (instring[1] && instring[2])
477  | 	      {
478  | 		sscanf (instring, "i %d", &increment);
479  | 	      }
480  | 	    else
481  | 	      {
482  | 		ierr=PetscPrintf (PETSC_COMM_WORLD,
483  | 				  "Increment: %d\n",increment);
484  | 		CHKERRQ (ierr);
485  | 	      }
486  | 	    break;
487  | 	  }
488  | 	case 'v':
489  | 	case 'V':
490  | 	  {
491  | 	    if (dims == 3)
492  | 	      display_field = (display_field+1) % fields;
493  | 	    break;
494  | 	  }
495  | #ifdef GEOMVIEW
496  | 	case 'd':
497  | 	case 'D':
498  | 	  {
499  | 	    char filename [200], number[10];
500  | 
501  | 	    if (dims<3)
502  | 	      {
503  | 		ierr=PetscPrintf (PETSC_COMM_WORLD,
504  | 				  "The 'd' command is for 3-D only.\n");
505  | 		CHKERRQ (ierr);
506  | 		break;
507  | 	      }
508  | 
509  | 	    strncpy (filename, basedirname, 198);
510  | 	    strcat (filename, "/");
511  | 	    strncat (filename, files [current_entry], 198 - strlen (filename));
512  | 	    snprintf (number, 9, "-f%d", display_field);
513  | 	    strncat (filename, number, 198 - strlen (filename));
514  | 	    strncat (filename, ".ppm", 198 - strlen (filename));
515  | 
516  | 	    DPRINTF ("Saving image with filename %s\n", filename);
517  | 	    IDispWritePPM (Disp, filename);
518  | 	    break;
519  | 	  }
520  | 	case 'a':
521  | 	case 'A':
522  | 	  {
523  | 	    char filename [200], number[10], *fieldname;
524  | 	    int entry;
525  | 
526  | 	    if (dims<3)
527  | 	      {
528  | 		ierr=PetscPrintf (PETSC_COMM_WORLD,
529  | 				  "The 'a' command is for 3-D only.\n");
530  | 		CHKERRQ (ierr);
531  | 		break;
532  | 	      }
533  | 
534  | 	    for (entry=0; entry<total_entries; entry++)
535  | 	      {
536  | 		DPRINTF ("Loading   file %d/%d\r", entry, total_entries);
537  | 		strcpy (basis, basedirname);
538  | 		strcat (basis, "/");
539  | 		strcat (basis, files[entry]);
540  | 		ierr = IlluMultiRead (PETSC_COMM_WORLD, theda, global, basis,
541  | 				      &usermetacount, &usermetanames,
542  | 				      &usermetadata); CHKERRQ (ierr);
543  | 
544  | 		DPRINTF ("Rendering file %d/%d\r", entry, total_entries);
545  | 		ierr = DATriangulateRange
546  | 		  (Surf, theda, global, display_field, minmax,
547  | 		   plots?plots:PETSC_DECIDE, plots?plot_vals:PETSC_NULL,
548  | 		   plots?plot_colors:PETSC_NULL, xmin,xmax, ymin,ymax,
549  | 		   zmin,zmax); CHKERRQ (ierr);
550  | 		ierr = DAGetFieldName (theda, display_field, &fieldname);
551  | 		CHKERRQ (ierr);
552  | 		ierr = GeomviewDisplayTriangulation
553  | 		  (PETSC_COMM_WORLD, Surf, Disp, minmax, fieldname, transp);
554  | 		CHKERRQ (ierr);
555  | 		ierr = SurfClear (Surf); CHKERRQ (ierr);
556  | 
557  | 		DPRINTF ("Dumping   file %d/%d\r", entry, total_entries);
558  | 		strncpy (filename, basedirname, 198);
559  | 		strcat (filename, "/");
560  | 		strncat (filename, files [entry], 198 - strlen (filename));
561  | 		snprintf (number, 9, "-f%d", display_field);
562  | 		strncat (filename, number, 198 - strlen (filename));
563  | 		strncat (filename, ".ppm", 198 - strlen (filename));
564  | 		IDispWritePPM (Disp, filename);
565  | 	      }
566  | 	    DPRINTF ("\n");
567  | 	    break;
568  | 	  }
569  | #endif
570  | 	case 'r':
571  | 	case 'R':
572  | 	  {
573  | 	    total_entries = scandir (basedirname, &namelist, myfilter,
574  | 				     alphasort);
575  | 
576  | 	    if (!(files = (char **) realloc (files,total_entries * sizeof (char *))))
577  | 	      {
578  | 		ierr = PetscPrintf (PETSC_COMM_WORLD, "Error allocating memory\n");
579  | 		CHKERRQ (ierr);
580  | 		ierr = PetscFinalize (); CHKERRQ(ierr);
581  | 		return 1;
582  | 	      }
583  | 	    for (i=0; i<total_entries; i++)
584  | 	      {
585  | 		int filength = strlen(namelist[i]->d_name);
586  | 	
587  | 		files [i] = (char *) malloc ((filength-12)*sizeof(char));
588  | 		strncpy (files [i], namelist[i]->d_name, filength-13);
589  | 		files [i] [filength-13] = '\0';
590  | 		free (namelist[i]);
591  | 		ierr = PetscPrintf (PETSC_COMM_WORLD, "[%d] %s\n", i, files [i]);
592  | 		CHKERRQ (ierr);
593  | 	      }
594  | 	    free (namelist);
595  | 	    
596  | 	    ierr = PetscPrintf (PETSC_COMM_WORLD, "Total Entries: %d\n",
597  | 				total_entries);
598  | 	    CHKERRQ (ierr);
599  | 	    break;
600  | 	  }
601  | 	case 's':
602  | 	case 'S':
603  | 	  {
604  | 	    if (instring[1] && instring[2] && dims<3)
605  | 	      {
606  | 		sscanf (instring+2, "%d", &windowsize);
607  | 
608  | 		if (windowsize)
609  | 		  {
610  | 		    int width=windowsize, height=windowsize;
611  | 
612  | 		    ierr = PetscViewerDestroy (theviewer); CHKERRQ (ierr);
613  | 
614  | 		    if (minmax[1]<minmax[3])
615  | 		      width  *= minmax[1]/minmax[3];
616  | 		    else
617  | 		      height *= minmax[3]/minmax[1];
618  | 
619  | 		    ierr = PetscViewerDrawOpen
620  | 		      (PETSC_COMM_WORLD, 0, "", PETSC_DECIDE, PETSC_DECIDE,
621  | 		       width, height, &theviewer); CHKERRQ (ierr);
622  | 		  }
623  | 		else
624  | 		  {
625  | 		    ierr=PetscPrintf (PETSC_COMM_WORLD,
626  | 				      "Usage: \"s ###\" (2-D only)\n");
627  | 		    CHKERRQ (ierr);
628  | 		  }
629  | 	      }
630  | 	    else
631  | 	      {
632  | 		ierr=PetscPrintf (PETSC_COMM_WORLD,
633  | 				  "Usage: \"s ###\" (2-D only)\n");
634  | 		CHKERRQ (ierr);
635  | 	      }
636  | 	    break;
637  | 	  }
638  | 	case 'p':
639  | 	case 'P':
640  | 	  {
641  | 	    int count=0, newplots=0;
642  | 
643  | 	    if (dims<3)
644  | 	      {
645  | 		ierr=PetscPrintf (PETSC_COMM_WORLD,
646  | 				  "The 'p' command is for 3-D only.\n");
647  | 		CHKERRQ (ierr);
648  | 		break;
649  | 	      }
650  | 
651  | 	    if (instring[1]=='\0' || instring[2]=='\0')
652  | 	      {
653  | 		ierr = PetscPrintf (PETSC_COMM_WORLD,
654  | 				    "Current plot contour isoquants:");
655  | 		CHKERRQ (ierr);
656  | 		if (plots == 0)
657  | 		  {
658  | 		    ierr = PetscPrintf (PETSC_COMM_WORLD,
659  | 					" auto (20%%, 40%%, 60%%, 80%%)");
660  | 		    CHKERRQ (ierr);
661  | 		  }
662  | 		for (count=0; count<plots; count++)
663  | 		  {
664  | 		    ierr = PetscPrintf (PETSC_COMM_WORLD, " %g",
665  | 					plot_vals[count]); CHKERRQ (ierr);
666  | 		  }
667  | 		ierr = PetscPrintf (PETSC_COMM_WORLD, "\n"); CHKERRQ (ierr);
668  | 		break;
669  | 	      }
670  | 
671  | 	    while (newplots<6 && instring[count] != '\0')
672  | 	      {
673  | 		while ((instring[count] < '0' || instring[count] > '9') &&
674  | 		       instring[count] != '-' && instring[count] != '.' &&
675  | 		       instring[count] != '\0')
676  | 		  count++;
677  | 
678  | 		if (instring[count])
679  | 		  {
680  | #if defined(PETSC_USE_SINGLE)
681  | 		    sscanf (instring+count, "%f", plot_vals+newplots);
682  | #else
683  | 		    sscanf (instring+count, "%lf", plot_vals+newplots);
684  | #endif
685  | 		    newplots++;
686  | 		    while ((instring[count] >= '0' && instring[count] <= '9')||
687  | 			   instring[count] == '-' || instring[count] == '.')
688  | 		      count++;
689  | 		  }
690  | 	      }
691  | 	    plots = newplots;
692  | 	    break;
693  | 	  }
694  | 	case 'c':
695  | 	case 'C':
696  | 	  {
697  | 	    if (instring[1] == 'x' || instring[1] == 'X')
698  | 	      xmax = (xmax == -2) ? -1 : -2;
699  | 	    if (instring[1] == 'y' || instring[1] == 'Y')
700  | 	      ymax = (ymax == -2) ? -1 : -2;
701  | 	    if (instring[1] == 'z' || instring[1] == 'Z')
702  | 	      zmax = (zmax == -2) ? -1 : -2;
703  | 	    DPRINTF ("x %d-%d, y %d-%d, z %d-%d\n", xmin, xmax, ymin, ymax,
704  | 		     zmin, zmax);
705  | 	    break;
706  | 	  }
707  | 	case 'g':
708  | 	case 'G':
709  | 	  {
710  | 	    int mingrid, maxgrid;
711  | 	    sscanf (instring+2, "%d-%d", &mingrid, &maxgrid);
712  | 	    if (instring[1] == 'x' || instring[1] == 'X')
713  | 	      {
714  | 		xmin = mingrid;
715  | 		xmax = maxgrid;
716  | 	      }
717  | 	    if (instring[1] == 'y' || instring[1] == 'Y')
718  | 	      {
719  | 		ymin = mingrid;
720  | 		ymax = maxgrid;
721  | 	      }
722  | 	    if (instring[1] == 'z' || instring[1] == 'Z')
723  | 	      {
724  | 		zmin = mingrid;
725  | 		zmax = maxgrid;
726  | 	      }
727  | 	    DPRINTF ("x %d-%d, y %d-%d, z %d-%d\n", xmin, xmax, ymin, ymax,
728  | 		     zmin, zmax);
729  | 	    break;
730  | 	  }
731  | 	default:
732  | 	  current_entry+=increment;
733  | 	}
734  |       if (current_entry < 0)
735  | 	current_entry = total_entries-1;
736  |       if (current_entry >= total_entries)
737  | 	current_entry = 0;
738  |     }
739  | 
740  |   free (filec);
741  |   free (dirc);
742  | }