1 | /***************************************
2 | $Header: /cvsroot/petscgraphics/tsview.c,v 1.31 2003/11/19 00:48:34 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 | ### Jump to timestep ###\n\
23 | t Toggle Geomview transparency (3-D only)\n\
24 | v Change field displayed (3-D only)\n\
25 | p [v1 v2 ...] Set contour values for plotting or \"auto\" (3-D only)\n\
26 | s size Set maximum dimension of PETSc viewer windows (2-D only)\n\
27 | h/? Print this information\n\
28 | q/x Quit tsview\n"
29 |
30 | #include "illuminator.h"
31 | #include <sys/dir.h> /* For scandir(), alphasort, struct dirent */
32 | #include <libgen.h> /* For dirname(), basename() */
33 | #include <string.h> /* For strdup() */
34 |
35 | /* Build with -DDEBUG for debugging output */
36 | #undef DPRINTF
37 | #ifdef DEBUG
38 | #define DPRINTF(fmt, args...) PetscPrintf (PETSC_COMM_WORLD, "%s: " fmt, __FUNCT__, args)
39 | #else
40 | #define DPRINTF(fmt, args...)
41 | #endif
42 |
43 | char *basefilename;
44 |
45 |
46 | #undef __FUNCT__
47 | #define __FUNCT__ "myfilter"
48 |
49 | /*++++++++++++++++++++++++++++++++++++++
50 | This function returns non-zero for "qualifying" file names which start with
51 | the stored files' basename and end with
52 | +latex+{\tt .cpu0000.meta}.
53 | +html+ <tt>.cpu0000.meta</tt>.
54 | It is used as the
55 | +latex+{\tt select()} function for {\tt scandir()} in {\tt main()}.
56 | +html+ <tt>select()</tt> function for <tt>scandir()</tt> in <tt>main()</tt>.
57 |
58 | int myfilter Returns non-zero for qualifying filenames.
59 |
60 | const struct dirent *direntry Directory entry with filename to test.
61 | ++++++++++++++++++++++++++++++++++++++*/
62 |
63 | int myfilter (const struct dirent *direntry)
64 | {
65 | if ((!strncmp (direntry->d_name, basefilename, strlen(basefilename))))
66 | return (!strncmp (direntry->d_name + strlen(direntry->d_name) - 13,
67 | ".cpu0000.meta", 13));
68 | return 0;
69 | }
70 |
71 |
72 | #undef __FUNCT__
73 | #define __FUNCT__ "main"
74 |
75 | /*++++++++++++++++++++++++++++++++++++++
76 | This is
77 | +latex+{\tt main()}.
78 | +html+ <tt>main()</tt>.
79 |
80 | int main It returns an int to the OS.
81 |
82 | int argc Argument count.
83 |
84 | char *argv[] Arguments.
85 | ++++++++++++++++++++++++++++++++++++++*/
86 |
87 | int main (int argc, char *argv[])
88 | {
89 | int total_entries, current_entry, dims, i, ierr, windowsize=300, plots=0;
90 | struct dirent **namelist;
91 | char **files, *thefilename, *filec, *dirc, *basedirname;
92 | PetscViewer theviewer;
93 | PetscTruth loaded = PETSC_FALSE, transp=PETSC_TRUE;
94 |
95 | if (argc<2)
96 | {
97 | ierr = PetscPrintf (PETSC_COMM_WORLD, "Usage: tsview basename\n");
98 | CHKERRQ (ierr);
99 | return 1;
100 | }
101 |
102 | /*+ After
103 | +latex+{\tt PETSc}
104 | +html+ <tt>PETSc</tt>
105 | initialization, it gets the list of files matching the basename. +*/
106 | ierr = PetscInitialize (&argc, &argv, (char *)0, help); CHKERRQ (ierr);
107 |
108 | DPRINTF ("Command line:",0); CHKERRQ (ierr);
109 | #ifdef DEBUG
110 | for (i=0; i<argc; i++)
111 | {
112 | ierr = PetscPrintf (PETSC_COMM_WORLD, " %s", argv[i]); CHKERRQ (ierr);
113 | }
114 | ierr = PetscPrintf (PETSC_COMM_WORLD, "\n"); CHKERRQ (ierr);
115 | #endif
116 |
117 | filec = strdup (argv[1]);
118 | dirc = strdup (argv[1]);
119 | basefilename = basename (filec);
120 | basedirname = dirname (dirc);
121 |
122 | ierr = PetscOptionsHasName (PETSC_NULL, "-no_transparency", &transp);
123 | CHKERRQ (ierr);
124 | transp = !transp;
125 |
126 | total_entries = scandir (basedirname, &namelist, myfilter, alphasort);
127 | if (!total_entries)
128 | {
129 | ierr = PetscPrintf (PETSC_COMM_WORLD, "No such files, exiting\n");
130 | CHKERRQ (ierr);
131 | exit (1);
132 | }
133 | if (total_entries < 0)
134 | {
135 | ierr = PetscPrintf (PETSC_COMM_WORLD, "Error scanning directory %s\n",
136 | basedirname); CHKERRQ (ierr);
137 | ierr = PetscFinalize (); CHKERRQ(ierr);
138 | return 1;
139 | }
140 | ierr = PetscPrintf (PETSC_COMM_WORLD, "%d eligible files:\n", total_entries);
141 | CHKERRQ (ierr);
142 |
143 | if (!(files = (char **) malloc (total_entries * sizeof (char *))))
144 | {
145 | ierr = PetscPrintf (PETSC_COMM_WORLD, "Error allocating memory\n");
146 | CHKERRQ (ierr);
147 | ierr = PetscFinalize (); CHKERRQ(ierr);
148 | return 1;
149 | }
150 | for (i=0; i<total_entries; i++)
151 | {
152 | int filength = strlen(namelist[i]->d_name);
153 |
154 | files [i] = (char *) malloc ((filength-12)*sizeof(char));
155 | strncpy (files [i], namelist[i]->d_name, filength-13);
156 | files [i] [filength-13] = '\0';
157 | free (namelist[i]);
158 | ierr = PetscPrintf (PETSC_COMM_WORLD, "[%d] %s\n", i, files [i]);
159 | CHKERRQ (ierr);
160 | }
161 | free (namelist);
162 |
163 | /*+In the main loop, the various timesteps are displayed, with options:
164 | +latex+\begin{itemize} \item
165 | +html+ <ul><li>
166 | A number jumps to that entry in the files table.
167 | +latex+\item {\stt <return>}
168 | +html+ <li><tt><return></tt>
169 | loads the next file.
170 | +latex+\item {\tt b}
171 | +html+ <li><tt>b</tt>
172 | goes back one file.
173 | +latex+\item {\tt q}
174 | +html+ <li><tt>q</tt>
175 | quits the program.
176 | +latex+\end{itemize}
177 | +html+ </ul>
178 | +*/
179 | current_entry=0;
180 | while (1)
181 | {
182 | DA theda;
183 | Vec global;
184 | int usermetacount=0, fields, display_field;
185 | char basis [strlen(argv[1]) + 20], **usermetanames, **usermetadata,
186 | instring [100];
187 | PetscScalar minmax[6], plot_vals[6], plot_colors[24] =
188 | { 1.,0.,0.,.5, 1.,1.,0.,.5, 0.,1.,0.,.5, 0.,1.,1.,.5, 0.,0.,1.,.5,
189 | 1.,0.,1.,.5 };
190 | field_plot_type *fieldtypes;
191 |
192 | /* Load the vector */
193 | strcpy (basis, basedirname);
194 | strcat (basis, "/");
195 | strcat (basis, files[current_entry]);
196 | ierr = PetscPrintf (PETSC_COMM_WORLD, "Loading entry %d, basename %s\n",
197 | current_entry, basis);
198 | if (loaded)
199 | {
200 | ierr = IlluMultiRead (theda, global, basis, &usermetacount,
201 | &usermetanames, &usermetadata);
202 | CHKERRQ (ierr);
203 | }
204 | else
205 | {
206 | DPRINTF ("Loading first timestep, creating distributed array\n",0);
207 | display_field = 0;
208 | minmax [0] = minmax [2] = minmax [4] = 0.;
209 | minmax [1] = minmax [3] = minmax [5] = 1.;
210 | ierr = IlluMultiLoad (basis, &theda, minmax+1, minmax+3, minmax+5,
211 | &fieldtypes, &usermetacount, &usermetanames,
212 | &usermetadata); CHKERRQ (ierr);
213 | ierr = DAGetGlobalVector (theda, &global); CHKERRQ (ierr);
214 | loaded = PETSC_TRUE;
215 |
216 | ierr = DAGetInfo (theda, &dims, PETSC_NULL,PETSC_NULL,PETSC_NULL,
217 | PETSC_NULL,PETSC_NULL,PETSC_NULL, &fields,
218 | PETSC_NULL,PETSC_NULL,PETSC_NULL); CHKERRQ (ierr);
219 |
220 | /* Usermetadata xwidth, ywidth, zwidth override minmax in case
221 | version is 0.1. */
222 | for (i=0; i<usermetacount; i++)
223 | {
224 | if (!strncmp (usermetanames [i], "xwidth", 6))
225 | sscanf (usermetadata [i], "%lf", minmax+1);
226 | else if (!strncmp (usermetanames [i], "ywidth", 6))
227 | sscanf (usermetadata [i], "%lf", minmax+3);
228 | else if (!strncmp (usermetanames [i], "zwidth", 6))
229 | sscanf (usermetadata [i], "%lf", minmax+5);
230 | }
231 |
232 | if (dims<3)
233 | {
234 | int width=windowsize, height=windowsize;
235 |
236 | if (minmax[1]<minmax[3])
237 | width *= minmax[1]/minmax[3];
238 | else
239 | height *= minmax[3]/minmax[1];
240 |
241 | ierr = PetscViewerDrawOpen
242 | (PETSC_COMM_WORLD, 0, "", PETSC_DECIDE, PETSC_DECIDE,
243 | width, height, &theviewer); CHKERRQ (ierr);
244 | }
245 | else
246 | {
247 | ierr = GeomviewBegin (PETSC_COMM_WORLD);
248 | }
249 | }
250 |
251 | /* Print user data */
252 | ierr = PetscPrintf (PETSC_COMM_WORLD, "User data:\n"); CHKERRQ (ierr);
253 | for (i=0; i<usermetacount; i++)
254 | {
255 | ierr = PetscPrintf (PETSC_COMM_WORLD, "%s = %s\n", usermetanames [i],
256 | usermetadata [i]); CHKERRQ (ierr);
257 | }
258 |
259 | /* View the vector */
260 | if (dims<3)
261 | {
262 | ierr = VecView (global, theviewer); CHKERRQ (ierr);
263 | }
264 | else
265 | {
266 | /*+ The Illuminator-based 3-D viewer can only display one field at a
267 | time. At the beginning, that is field 0, and is cycled using the
268 | +latex+{\tt v}
269 | +html+ <tt>v</tt>
270 | command. +*/
271 | PetscScalar minval, maxval;
272 | char *fieldname;
273 |
274 | ierr = VecStrideMin (global, display_field, PETSC_NULL, &minval);
275 | CHKERRQ (ierr);
276 | ierr = VecStrideMax (global, display_field, PETSC_NULL, &maxval);
277 | CHKERRQ (ierr);
278 | ierr = DAGetFieldName (theda, display_field, &fieldname);
279 | CHKERRQ (ierr);
280 | ierr = PetscPrintf (PETSC_COMM_WORLD,
281 | "Displaying field %d [%g-%g]: %s\n",
282 | display_field, minval, maxval, fieldname);
283 | CHKERRQ (ierr);
284 |
285 | DPRINTF ("Calculating triangle locations\n",0);
286 | if (plots)
287 | {
288 | ierr = DATriangulate (theda, global, display_field, minmax,
289 | plots, plot_vals, plot_colors);
290 | }
291 | else
292 | {
293 | ierr = DATriangulate (theda, global, display_field, minmax,
294 | PETSC_DECIDE, PETSC_NULL, PETSC_NULL);
295 | CHKERRQ (ierr);
296 | }
297 | DPRINTF ("Consolidating triangles on head node and visualizing\n",0);
298 | ierr = GeomviewDisplayTriangulation
299 | (PETSC_COMM_WORLD, minmax, fieldname, transp);
300 | CHKERRQ (ierr);
301 | }
302 |
303 | /* Free user data */
304 | for (i=0; i<usermetacount; i++)
305 | {
306 | free (usermetanames [i]);
307 | free (usermetadata [i]);
308 | }
309 | free (usermetanames);
310 | free (usermetadata);
311 |
312 | /* Get user input */
313 | ierr = PetscPrintf (PETSC_COMM_WORLD, "What to do? (h for options) ");
314 | CHKERRQ (ierr);
315 | ierr = PetscSynchronizedFGets (PETSC_COMM_WORLD, stdin, 99, instring);
316 | CHKERRQ (ierr);
317 |
318 | switch (instring [0])
319 | {
320 | case 'q':
321 | case 'Q':
322 | case 'x':
323 | case 'X':
324 | {
325 | if (dims < 3)
326 | {
327 | ierr = PetscViewerDestroy (theviewer); CHKERRQ (ierr);
328 | }
329 | else
330 | {
331 | ierr = GeomviewEnd (PETSC_COMM_WORLD); CHKERRQ (ierr);
332 | }
333 | ierr = PetscFinalize(); CHKERRQ (ierr);
334 | return 0;
335 | }
336 | case 't':
337 | case 'T':
338 | {
339 | transp=!transp;
340 | break;
341 | }
342 | case 'h':
343 | case 'H':
344 | case '?':
345 | {
346 | ierr = PetscPrintf (PETSC_COMM_WORLD, HELP_STRING);
347 | break;
348 | }
349 | case '0':
350 | case '1':
351 | case '2':
352 | case '3':
353 | case '4':
354 | case '5':
355 | case '6':
356 | case '7':
357 | case '8':
358 | case '9':
359 | {
360 | current_entry = atoi (instring);
361 | break;
362 | }
363 | case 'b':
364 | case 'B':
365 | {
366 | current_entry--;
367 | break;
368 | }
369 | case 'v':
370 | case 'V':
371 | {
372 | if (dims == 3)
373 | display_field = (display_field+1) % fields;
374 | break;
375 | }
376 | case 's':
377 | case 'S':
378 | {
379 | printf ("instring=\"%s\"\n",instring);
380 | if (instring[1] && instring[2] && dims<3)
381 | {
382 | sscanf (instring+2, "%d", &windowsize);
383 |
384 | if (windowsize)
385 | {
386 | int width=windowsize, height=windowsize;
387 |
388 | ierr = PetscViewerDestroy (theviewer); CHKERRQ (ierr);
389 |
390 | if (minmax[1]<minmax[3])
391 | width *= minmax[1]/minmax[3];
392 | else
393 | height *= minmax[3]/minmax[1];
394 |
395 | ierr = PetscViewerDrawOpen
396 | (PETSC_COMM_WORLD, 0, "", PETSC_DECIDE, PETSC_DECIDE,
397 | width, height, &theviewer); CHKERRQ (ierr);
398 | }
399 | else
400 | {
401 | ierr=PetscPrintf (PETSC_COMM_WORLD,
402 | "Usage: \"s ###\" (2-D only)\n");
403 | CHKERRQ (ierr);
404 | }
405 | }
406 | else
407 | {
408 | ierr=PetscPrintf (PETSC_COMM_WORLD,
409 | "Usage: \"s ###\" (2-D only)\n");
410 | CHKERRQ (ierr);
411 | }
412 | break;
413 | }
414 | case 'p':
415 | case 'P':
416 | {
417 | int count=0, newplots=0;
418 |
419 | if (dims<3)
420 | {
421 | ierr=PetscPrintf (PETSC_COMM_WORLD,
422 | "The 'p' command is for 2-D only.\n");
423 | CHKERRQ (ierr);
424 | break;
425 | }
426 |
427 | if (instring[1]=='\0' || instring[2]=='\0')
428 | {
429 | ierr = PetscPrintf (PETSC_COMM_WORLD,
430 | "Current plot contour isoquants:");
431 | CHKERRQ (ierr);
432 | if (plots == 0)
433 | {
434 | ierr = PetscPrintf (PETSC_COMM_WORLD,
435 | " auto (20%%, 40%%, 60%%, 80%%)");
436 | CHKERRQ (ierr);
437 | }
438 | for (count=0; count<plots; count++)
439 | {
440 | ierr = PetscPrintf (PETSC_COMM_WORLD, " %g",
441 | plot_vals[count]); CHKERRQ (ierr);
442 | }
443 | ierr = PetscPrintf (PETSC_COMM_WORLD, "\n"); CHKERRQ (ierr);
444 | break;
445 | }
446 |
447 | while (newplots<6 && instring[count] != '\0')
448 | {
449 | while ((instring[count] < '0' || instring[count] > '9') &&
450 | instring[count] != '-' && instring[count] != '.' &&
451 | instring[count] != '\0')
452 | count++;
453 |
454 | if (instring[count])
455 | {
456 | #if defined(PETSC_USE_SINGLE)
457 | sscanf (instring+count, "%f", plot_vals+newplots);
458 | #else
459 | sscanf (instring+count, "%lf", plot_vals+newplots);
460 | #endif
461 | newplots++;
462 | while ((instring[count] >= '0' && instring[count] <= '9')||
463 | instring[count] == '-' || instring[count] == '.')
464 | count++;
465 | }
466 | }
467 | plots = newplots;
468 | break;
469 | }
470 | default:
471 | current_entry++;
472 | }
473 | if (current_entry < 0)
474 | current_entry = total_entries-1;
475 | if (current_entry >= total_entries)
476 | current_entry = 0;
477 | }
478 |
479 | free (filec);
480 | free (dirc);
481 | }