1 | /***************************************
2 | $Header: /cvsroot/petscgraphics/tsview-ng.c,v 1.10 2004/05/21 22:08:44 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 | #include "illuminator.h"
20 | #include <glade/glade.h>
21 | #include <gnome.h>
22 | #include <libgnomeui/libgnomeui.h>
23 | #include <sys/dir.h> /* For scandir(), alphasort, struct dirent */
24 | #include <libgen.h> /* For dirname(), basename() */
25 | #include <string.h> /* For strdup() */
26 |
27 | /* Build with -DDEBUG for debugging output */
28 | #undef DPRINTF
29 | #ifdef DEBUG
30 | #define DPRINTF(fmt, args...) PetscPrintf (PETSC_COMM_WORLD, "%s: " fmt, __FUNCT__, args)
31 | #else
32 | #define DPRINTF(fmt, args...)
33 | #endif
34 |
35 | GladeXML *xml;
36 | /* Filename list */
37 | int entrynum=0, total_entries=0, current_timestep;
38 | char *the_basename, *basedirname, **stepnames=NULL;
39 | double current_time;
40 |
41 | /* Window parameters and drawables */
42 | int width=0, height=0, nx, ny, dataview_count=1;
43 | GtkWidget *dataviews [1];
44 | guchar *rgbbuf [1] = { NULL };
45 | double sizemag;
46 | PetscTruth transp;
47 |
48 | /* Maximum intensity for hueintense plots */
49 | PetscScalar vecmax=-1.;
50 |
51 | /* PETSc structures etc. */
52 | DA theda;
53 | Vec global;
54 | PetscScalar minmax[6] = { 0.,1., 0.,1., 0.,1. };
55 | field_plot_type *fieldtypes;
56 | int dimensions, num_fields, num_variables[1], **variable_indices;
57 |
58 | /* First some main functions which do stuff, then callbacks, then main(). */
59 | static inline void pseudocolor (PetscScalar val, PetscScalar min,
60 | PetscScalar max, guchar *pixel)
61 | {
62 | PetscScalar shade = (val - min) / (max - min);
63 | /* Old stuff *
64 | if (shade < 0.2) { /* red -> yellow *
65 | *pixel++ = 255;
66 | *pixel++ = 1275*shade;
67 | *pixel++ = 0; }
68 | else if (shade < 0.4) { /* yellow -> green *
69 | *pixel++ = 510-1275*shade;
70 | *pixel++ = 255;
71 | *pixel++ = 0; }
72 | else if (shade < 0.6) { /* green -> cyan *
73 | *pixel++ = 0;
74 | *pixel++ = 255;
75 | *pixel++ = 1275*shade-510; }
76 | else if (shade < 0.8) { /* cyan -> blue *
77 | *pixel++ = 0;
78 | *pixel++ = 1020-1275*shade;
79 | *pixel++ = 255; }
80 | else { /* blue -> magenta *
81 | *pixel++ = 1275*shade-1020;
82 | *pixel++ = 0;
83 | *pixel++ = 255; }
84 | /* New stuff */
85 | if (shade < 0.25) { /* red -> yellow */
86 | *pixel++ = 255;
87 | *pixel++ = 1020*shade;
88 | *pixel++ = 0; }
89 | else if (shade < 0.5) { /* yellow -> green */
90 | *pixel++ = 510-1020*shade;
91 | *pixel++ = 255;
92 | *pixel++ = 0; }
93 | else if (shade < 0.75) { /* green -> cyan */
94 | *pixel++ = 0;
95 | *pixel++ = 255;
96 | *pixel++ = 1020*shade-510; }
97 | else { /* cyan -> blue */
98 | *pixel++ = 0;
99 | *pixel++ = 1020-1020*shade;
100 | *pixel++ = 255; }
101 | }
102 |
103 | static inline void pseudohueintcolor
104 | (PetscScalar vx, PetscScalar vy, PetscScalar refmag, guchar *pixel)
105 | {
106 | PetscScalar mag=sqrt(vx*vx+vy*vy), theta=atan2(vy,vx), red, green, blue;
107 | if (refmag <= 0.)
108 | {
109 | *pixel = *(pixel+1) = *(pixel+2) = 0;
110 | return;
111 | }
112 | mag = (mag > refmag) ? 1.0 : mag/refmag;
113 | /* Old pseudocolor */
114 | /* red = (theta<-M_PI*5./6.)? 1.5/M_PI*(-M_PI*5./6.-theta):
115 | ((theta<-M_PI/6.)? 0.:
116 | ((theta<M_PI/2.)? 1.5/M_PI*(theta+M_PI/6.): 1.5/M_PI*(M_PI*7./6.-theta)));
117 | green = (theta<-M_PI*5./6.)? 1.5/M_PI*(theta+M_PI*3./2.):
118 | ((theta<-M_PI/6.)? 1.5/M_PI*(-M_PI/6.-theta):
119 | ((theta<M_PI/2.)? 0.: 1.5/M_PI*(theta-M_PI/2.)));
120 | blue = (theta<-M_PI*5./6.)? 0.:
121 | ((theta<-M_PI/6.)? 1.5/M_PI*(theta+M_PI*5./6.):
122 | ((theta<M_PI/2.)? 1.5/M_PI*(M_PI/2.-theta): 0.)); */
123 |
124 | /* New pseudocolor: green, yellow, red, blue at 0, 90, 180, 270 degrees */
125 | red = 2./M_PI * ((theta<-M_PI/2.) ? -M_PI/2.-theta :
126 | ((theta<0.) ? 0. : ((theta<M_PI/2.) ? theta : M_PI/2.)));
127 | green = 2./M_PI * ((theta<-M_PI/2.) ? 0. :
128 | ((theta<0.) ? theta+M_PI/2. :
129 | ((theta<M_PI/2.) ? M_PI/2. : M_PI-theta)));
130 | blue = 2./M_PI * ((theta<-M_PI/2.) ? theta+M_PI :
131 | ((theta<0.) ? -theta : 0.));
132 |
133 | *pixel++ = 255*mag*red;
134 | *pixel++ = 255*mag*green;
135 | *pixel++ = 255*mag*blue;
136 | }
137 |
138 | static inline void pseudoternarycolor
139 | (PetscScalar A, PetscScalar B, PetscScalar Corner1A, PetscScalar Corner1B,
140 | PetscScalar Corner2A, PetscScalar Corner2B, PetscScalar Corner3A,
141 | PetscScalar Corner3B, guchar *pixel)
142 | {
143 | PetscScalar x1, x2, inverse_det;
144 |
145 | /* Transform A,B into x1,x2 based on corners */
146 | A -= Corner3A;
147 | Corner1A -= Corner3A;
148 | Corner2A -= Corner3A;
149 | B -= Corner3B;
150 | Corner1B -= Corner3B;
151 | Corner2B -= Corner3B;
152 | inverse_det = 1./(Corner1A*Corner2B - Corner2A*Corner1B);
153 | x1 = (A*Corner2B - B*Corner2A) * inverse_det;
154 | x2 = (B*Corner1A - A*Corner1B) * inverse_det;
155 |
156 | /* Now colorize */
157 | *pixel++ = 255*(1.-x1);
158 | *pixel++ = 255*(x1+x2);
159 | *pixel++ = 255*(1.-x2);
160 | }
161 |
162 | /* Find the maximum magnitude of a 2-D vector field in an array */
163 | PetscScalar ArrayMaxMag (PetscScalar *global, int points, int fields,int field)
164 | {
165 | int i;
166 | PetscScalar retval;
167 |
168 | retval = global[field]*global[field] + global[field+1]*global[field+1];
169 |
170 | for (i=1; i<points; i++)
171 | retval = PetscMax (retval, global[i*fields+field]*global[i*fields+field] +
172 | global[i*fields+field+1]*global[i*fields+field+1]);
173 | return sqrt (retval);
174 | }
175 |
176 | void paint_rgb (guchar *rgb, int rwidth, int rheight, DA rgbda, Vec rgbglobal,
177 | int display_field)
178 | {
179 | int nx,ny,nz, ix,iy, ierr;
180 | PetscScalar *global_array, minval, maxval, refmag;
181 |
182 | ierr = DAGetInfo (rgbda, PETSC_NULL, &nx,&ny,&nz,
183 | PETSC_NULL,PETSC_NULL,PETSC_NULL, PETSC_NULL,
184 | PETSC_NULL,PETSC_NULL,PETSC_NULL); CHKERRQ (ierr);
185 |
186 | ierr = VecStrideMin (rgbglobal, display_field, PETSC_NULL, &minval);
187 | CHKERRQ (ierr);
188 | ierr = VecStrideMax (rgbglobal, display_field, PETSC_NULL, &maxval);
189 | CHKERRQ (ierr);
190 |
191 | ierr = VecGetArray (rgbglobal, &global_array);
192 |
193 | /* If a vector field, then find max magnitude in fields 0-1 */
194 | if (fieldtypes[display_field] == FIELD_VECTOR_HUEINTENSE ||
195 | fieldtypes[display_field] == FIELD_VECTOR_ARROWS)
196 | {
197 | if (vecmax > 0)
198 | refmag = vecmax;
199 | else
200 | refmag = ArrayMaxMag (global_array, nx*ny, num_fields, display_field);
201 | printf ("Reference vector magnitude = %g\n", refmag);
202 | }
203 |
204 | for (iy=0; iy<rheight; iy++)
205 | for (ix=0; ix<rwidth; ix++)
206 | {
207 | int vecindex;
208 | guchar *pixel;
209 | vecindex = (((rheight-iy-1)*ny/rheight)*nx+ ix*nx/rwidth)*num_fields+
210 | display_field;
211 | pixel = rgb + 3*(iy*rwidth + ix);
212 |
213 | if (fieldtypes[display_field] == FIELD_TERNARY_RGB)
214 | pseudoternarycolor
215 | (global_array [vecindex], global_array [vecindex+1],
216 | 0.,0., 1.,0., 0.,1., pixel);
217 | else if (fieldtypes[display_field] == FIELD_VECTOR_HUEINTENSE ||
218 | fieldtypes[display_field] == FIELD_VECTOR_ARROWS)
219 | pseudohueintcolor
220 | (global_array [vecindex], global_array [vecindex+1], refmag,
221 | pixel);
222 | else
223 | pseudocolor (global_array [vecindex], minval, maxval, pixel);
224 | }
225 | ierr = VecRestoreArray (rgbglobal, &global_array);
226 | }
227 |
228 | void render_dataviews ()
229 | {
230 | int viewnum, nx,ny,nz, ierr;
231 | GtkWidget *thebar = glade_xml_get_widget(xml, "appbar1");
232 |
233 | if (dataview_count != 1)
234 | {
235 | printf ("dataview_count != 1 is not yet supported\n");
236 | exit(0);
237 | }
238 | for (viewnum=0; viewnum<dataview_count; viewnum++)
239 | {
240 | int ix,iy, display_field=0;
241 | PetscScalar minval, maxval, refmag, *global_array;
242 | GtkType type;
243 | char thestatus [100];
244 |
245 | /* (Re)allocate buffer */
246 | if (!(rgbbuf [viewnum] =
247 | (guchar *) realloc (rgbbuf [viewnum],
248 | 3*width*height*sizeof(guchar)))) {
249 | printf ("ERROR: can't reallocate RGB buffer\n");
250 | exit (1); }
251 |
252 | sprintf (thestatus, "Rendering view %d...", viewnum);
253 | gnome_appbar_set_default (GNOME_APPBAR (thebar), thestatus);
254 |
255 | /* Render into rgbbuf */
256 | paint_rgb (rgbbuf [viewnum], width,height, theda, global, display_field);
257 |
258 | /* Draw buffer onto window */
259 | if (!dataviews [viewnum])
260 | dataviews [viewnum] = glade_xml_get_widget (xml, "plot_area");
261 | gtk_drawing_area_size (GTK_DRAWING_AREA (dataviews [viewnum]),
262 | width, height);
263 | gdk_draw_rgb_image (dataviews [viewnum]->window,
264 | dataviews [viewnum]->style->fg_gc[GTK_STATE_NORMAL],
265 | 0, 0, width, height, GDK_RGB_DITHER_MAX,
266 | rgbbuf [viewnum], width * 3);
267 | }
268 | gnome_appbar_set_default (GNOME_APPBAR (thebar), "Done.");
269 | }
270 |
271 |
272 | #undef __FUNCT__
273 | #define __FUNCT__ "myfilter"
274 |
275 | /*+ Little variable for myfilter() and refresh_stepnames(). +*/
276 | static char *basefilename;
277 |
278 | /*++++++++++++++++++++++++++++++++++++++
279 | This function returns non-zero for "qualifying" file names which start with
280 | the stored files' basename.time and end with
281 | +latex+{\tt .cpu0000.meta}.
282 | +html+ <tt>.cpu0000.meta</tt>.
283 | It is used as the
284 | +latex+{\tt select()} function for {\tt scandir()} in {\tt main()}.
285 | +html+ <tt>select()</tt> function for <tt>scandir()</tt> in <tt>main()</tt>.
286 |
287 | int myfilter Returns non-zero for qualifying filenames.
288 |
289 | const struct dirent *direntry Directory entry with filename to test.
290 | ++++++++++++++++++++++++++++++++++++++*/
291 |
292 | int myfilter (const struct dirent *direntry)
293 | {
294 | if ((!strncmp (direntry->d_name, basefilename, strlen(basefilename))) &&
295 | (!strncmp (direntry->d_name + strlen(basefilename), ".time", 5)))
296 | return (!strncmp (direntry->d_name + strlen(direntry->d_name) - 13,
297 | ".cpu0000.meta", 13));
298 | return 0;
299 | }
300 |
301 |
302 | void on_plot_area_expose_event (GtkWidget *widget, GdkEventExpose *event,
303 | gpointer user_data)
304 | {
305 | gdk_draw_rgb_image (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL],
306 | 0, 0, width, height, GDK_RGB_DITHER_MAX, rgbbuf [0],
307 | width * 3);
308 | }
309 |
310 | /*++++++++++++++++++++++++++++++++++++++
311 | This loads the names of the files into a long list.
312 | ++++++++++++++++++++++++++++++++++++++*/
313 |
314 | int refresh_stepnames ()
315 | {
316 | struct dirent **namelist;
317 | char *filec, *dirc;
318 | int i, ierr;
319 |
320 | filec = strdup (the_basename);
321 | dirc = strdup (the_basename);
322 | basefilename = basename (filec);
323 | basedirname = dirname (dirc);
324 |
325 | total_entries = scandir (basedirname, &namelist, myfilter, alphasort);
326 | if (!total_entries)
327 | {
328 | ierr = PetscPrintf (PETSC_COMM_WORLD, "No such files\n");
329 | CHKERRQ (ierr);
330 | return 1;
331 | }
332 | if (total_entries < 0)
333 | {
334 | ierr = PetscPrintf (PETSC_COMM_WORLD, "Error scanning directory %s\n",
335 | basedirname); CHKERRQ (ierr);
336 | ierr = PetscFinalize (); CHKERRQ(ierr);
337 | return 1;
338 | }
339 | ierr = PetscPrintf (PETSC_COMM_WORLD, "%d eligible files:\n", total_entries);
340 | CHKERRQ (ierr);
341 |
342 | if (!(stepnames = (char **) realloc
343 | (stepnames, total_entries*sizeof (char *))))
344 | {
345 | ierr = PetscPrintf (PETSC_COMM_WORLD, "Error allocating memory\n");
346 | CHKERRQ (ierr);
347 | return 1;
348 | }
349 | for (i=0; i<total_entries; i++)
350 | {
351 | int filength = strlen(namelist[i]->d_name);
352 |
353 | stepnames [i] = (char *) malloc ((filength-12)*sizeof(char));
354 | strncpy (stepnames [i], namelist[i]->d_name, filength-13);
355 | stepnames [i] [filength-13] = '\0';
356 | free (namelist[i]);
357 | ierr = PetscPrintf (PETSC_COMM_WORLD, "[%d] %s\n", i, stepnames [i]);
358 | CHKERRQ (ierr);
359 | }
360 |
361 | free (namelist);
362 | return 0;
363 | }
364 |
365 |
366 | void on_mag_spin_value_changed (GtkWidget *mag_spin, gpointer user_data) {
367 | G_CONST_RETURN gchar *entrytext;
368 | entrytext = gtk_entry_get_text (GTK_ENTRY (mag_spin));
369 | sscanf (entrytext, "%lf", &sizemag);
370 | width = (int) (minmax [1] * sizemag);
371 | height = (int) (minmax [3] * sizemag);
372 |
373 | render_dataviews(dataviews, dataview_count);
374 | }
375 |
376 |
377 | void display_timestep (int usermetacount, char **usermetanames,
378 | char **usermetadata)
379 | {
380 | int i;
381 | static char step_buffer [20], time_buffer [20];
382 |
383 | for (i=0; i<usermetacount; i++)
384 | {
385 | if (!strncmp (usermetanames [i], "timestep", 8))
386 | sscanf (usermetadata [i], "%d", ¤t_timestep);
387 | else if (!strncmp (usermetanames [i], "time", 4))
388 | sscanf (usermetadata [i], "%lf", ¤t_time);
389 | }
390 | snprintf (step_buffer, 19, "Timestep: %d", current_timestep);
391 | gtk_label_set_text (GTK_LABEL (glade_xml_get_widget (xml, "timestep_label")),
392 | step_buffer);
393 | snprintf (time_buffer, 19, "Time: %g", current_time);
394 | gtk_label_set_text (GTK_LABEL (glade_xml_get_widget (xml, "time_label")),
395 | time_buffer);
396 |
397 | on_mag_spin_value_changed (glade_xml_get_widget (xml, "mag_spin"), NULL);
398 | }
399 |
400 |
401 | void on_save_activate (GtkWidget *widget, gpointer user_data)
402 | {
403 | int i, ierr;
404 | char **usermetanames, **usermetadata, filename [200], thestatus [200];
405 | GtkWidget *thebar = glade_xml_get_widget(xml, "appbar1");
406 | FILE *outppm;
407 |
408 | strncpy (filename, basedirname, 198);
409 | strcat (filename, "/");
410 | strncat (filename, stepnames [entrynum], 198 - strlen (filename));
411 | strncat (filename, ".ppm", 198 - strlen (filename));
412 |
413 | sprintf (thestatus, "Saving entry %d in filename %s", entrynum, filename);
414 | gnome_appbar_set_default (GNOME_APPBAR (thebar), thestatus);
415 |
416 | if (!(outppm = fopen (filename, "w")))
417 | printf ("Error opening file %s\n", filename);
418 | fprintf (outppm, "P6\n%d %d\n255\n", width, height);
419 | fwrite (rgbbuf [0], sizeof (guchar), 3*width*height, outppm);
420 | fclose (outppm);
421 |
422 | sprintf (thestatus, "Saved entry %d in filename %s", entrynum, filename);
423 | gnome_appbar_set_default (GNOME_APPBAR (thebar), thestatus);
424 | }
425 |
426 |
427 | void on_timestep_spin_value_changed (GtkWidget *timestep_spin, gpointer user_data) {
428 | int usermetacount, ierr;
429 | G_CONST_RETURN gchar *entrytext;
430 | char **usermetanames, **usermetadata, filename [200], thestatus [200];
431 | GtkWidget *thebar = glade_xml_get_widget(xml, "appbar1");
432 |
433 | entrytext = gtk_entry_get_text (GTK_ENTRY (timestep_spin));
434 | sscanf (entrytext, "%d", &entrynum);
435 |
436 | /* Bound the entrynum between 0 and total_entries-1; -11 is the minimum of
437 | the widget (from jump), 1000001 is the maximum. */
438 | if ((entrynum < 0 && entrynum != -11) || entrynum == 1000001)
439 | entrynum = total_entries-1;
440 | if ((entrynum >= total_entries && entrynum != 1000001) || entrynum == -11)
441 | entrynum = 0;
442 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (timestep_spin),
443 | (gfloat) entrynum);
444 |
445 | strncpy (filename, basedirname, 198);
446 | strcat (filename, "/");
447 | strncat (filename, stepnames [entrynum], 198 - strlen (filename));
448 |
449 | sprintf (thestatus, "Loading entry %d, basename %s\n", entrynum, filename);
450 | gnome_appbar_set_default (GNOME_APPBAR (thebar), thestatus);
451 |
452 | ierr = IlluMultiRead (theda, global, filename, &usermetacount,&usermetanames,
453 | &usermetadata); CHKERRQ (ierr);
454 |
455 | display_timestep (usermetacount, usermetanames, usermetadata);
456 | }
457 |
458 |
459 | void on_refresh_activate (GtkWidget *none, gpointer user_data) {
460 | if (refresh_stepnames ()) exit (1); }
461 |
462 |
463 | void on_about_activate (GtkWidget *none, gpointer user_data) {
464 | gtk_widget_show (glade_xml_get_widget (xml, "about")); }
465 |
466 |
467 | /*
468 | #define HELP_STRING "tsview commands:\n\
469 | <enter> Display next timestep\n\
470 | b Display previous timestep\n\
471 | ### Jump to timestep ###\n\
472 | t Toggle Geomview transparency (3-D only)\n\
473 | v Change field displayed (3-D only)\n\
474 | h/? Print this information\n\
475 | q/x Quit tsview\n"
476 |
477 | int start (int argc, char *argv[])
478 | {
479 | int total_entries, current_entry, dims, i, ierr;
480 | PetscViewer theviewer;
481 | PetscTruth loaded = PETSC_FALSE, transp=PETSC_TRUE; */
482 |
483 | /*+In the main loop, the various timesteps are displayed, with options:
484 | +latex+\begin{itemize} \item
485 | +html+ <ul><li>
486 | A number jumps to that entry in the files table.
487 | +latex+\item {\stt <return>}
488 | +html+ <li><tt><return></tt>
489 | loads the next file.
490 | +latex+\item {\tt b}
491 | +html+ <li><tt>b</tt>
492 | goes back one file.
493 | +latex+\item {\tt q}
494 | +html+ <li><tt>q</tt>
495 | quits the program.
496 | +latex+\end{itemize}
497 | +html+ </ul>
498 | +*/
499 | /* current_entry=0;
500 | while (1)
501 | {
502 |
503 | else
504 | {
505 |
506 | if (dims<3)
507 | {
508 | int width=300, height=300;
509 |
510 | if (minmax[1]<minmax[3])
511 | width *= minmax[1]/minmax[3];
512 | else
513 | height *= minmax[3]/minmax[1];
514 |
515 | ierr = PetscViewerDrawOpen
516 | (PETSC_COMM_WORLD, 0, "", PETSC_DECIDE, PETSC_DECIDE,
517 | width, height, &theviewer); CHKERRQ (ierr);
518 | }
519 | else
520 | {
521 | ierr = GeomviewBegin (PETSC_COMM_WORLD);
522 | }
523 | }
524 |
525 | ierr = PetscPrintf (PETSC_COMM_WORLD, "User data:\n"); CHKERRQ (ierr);
526 | for (i=0; i<usermetacount; i++)
527 | {
528 | ierr = PetscPrintf (PETSC_COMM_WORLD, "%s = %s\n", usermetanames [i],
529 | usermetadata [i]); CHKERRQ (ierr);
530 | }
531 |
532 | if (dims<3)
533 | {
534 | ierr = VecView (global, theviewer); CHKERRQ (ierr);
535 | }
536 | else
537 | { */
538 | /*+ The Illuminator-based 3-D viewer can only display one field at a
539 | time. At the beginning, that is field 0, and is cycled using the
540 | +latex+{\tt v}
541 | +html+ <tt>v</tt>
542 | command. +*/
543 | /* PetscScalar minval, maxval;
544 | char *fieldname;
545 |
546 | ierr = VecStrideMin (global, display_field, PETSC_NULL, &minval);
547 | CHKERRQ (ierr);
548 | ierr = VecStrideMax (global, display_field, PETSC_NULL, &maxval);
549 | CHKERRQ (ierr);
550 | ierr = PetscPrintf (PETSC_COMM_WORLD,
551 | "Displaying field %d [%g-%g]: %s\n",
552 | display_field, minval, maxval, fieldname);
553 | CHKERRQ (ierr);
554 |
555 | DPRINTF ("Calculating triangle locations\n",0);
556 | ierr = DATriangulate (theda, global, display_field, minmax,
557 | PETSC_DECIDE, PETSC_NULL, PETSC_NULL);
558 | CHKERRQ (ierr);
559 | ierr = DAGetFieldName (theda, display_field, &fieldname);
560 | CHKERRQ (ierr);
561 | DPRINTF ("Consolidating triangles on head node and visualizing\n",0);
562 | ierr = GeomviewDisplayTriangulation
563 | (PETSC_COMM_WORLD, minmax, fieldname, transp);
564 | CHKERRQ (ierr);
565 | }
566 |
567 | for (i=0; i<usermetacount; i++)
568 | {
569 | free (usermetanames [i]);
570 | free (usermetadata [i]);
571 | }
572 | free (usermetanames);
573 | free (usermetadata);
574 |
575 | ierr = PetscPrintf (PETSC_COMM_WORLD, "What to do? (h for options) ");
576 | CHKERRQ (ierr);
577 | ierr = PetscSynchronizedFGets (PETSC_COMM_WORLD, stdin, 99, instring);
578 | CHKERRQ (ierr);
579 |
580 | switch (instring [0])
581 | {
582 | case 'q':
583 | case 'Q':
584 | case 'x':
585 | case 'X':
586 | {
587 | if (dims < 3)
588 | {
589 | ierr = PetscViewerDestroy (theviewer); CHKERRQ (ierr);
590 | }
591 | else
592 | {
593 | ierr = GeomviewEnd (PETSC_COMM_WORLD); CHKERRQ (ierr);
594 | }
595 | ierr = PetscFinalize(); CHKERRQ (ierr);
596 | return 0;
597 | }
598 | case 't':
599 | case 'T':
600 | {
601 | transp=!transp;
602 | break;
603 | }
604 | case 'h':
605 | case 'H':
606 | case '?':
607 | {
608 | ierr = PetscPrintf (PETSC_COMM_WORLD, HELP_STRING);
609 | break;
610 | }
611 | case '0':
612 | case '1':
613 | case '2':
614 | case '3':
615 | case '4':
616 | case '5':
617 | case '6':
618 | case '7':
619 | case '8':
620 | case '9':
621 | {
622 | current_entry = atoi (instring);
623 | break;
624 | }
625 | case 'b':
626 | case 'B':
627 | {
628 | current_entry--;
629 | break;
630 | }
631 | case 'v':
632 | case 'V':
633 | {
634 | if (dims == 3)
635 | display_field = (display_field+1) % fields;
636 | }
637 | default:
638 | current_entry++;
639 | }
640 | if (current_entry < 0)
641 | current_entry = total_entries-1;
642 | if (current_entry >= total_entries)
643 | current_entry = 0;
644 | }
645 |
646 | } */
647 |
648 | #undef __FUNCT__
649 | #define __FUNCT__ "main"
650 |
651 | /*++++++++++++++++++++++++++++++++++++++
652 | This is
653 | +latex+{\tt main()}.
654 | +html+ <tt>main()</tt>.
655 |
656 | int main It returns an int to the OS.
657 |
658 | int argc Argument count.
659 |
660 | char *argv[] Arguments.
661 | ++++++++++++++++++++++++++++++++++++++*/
662 |
663 | int main (int argc, char *argv[])
664 | {
665 | /* GnomeProgram *app; */
666 | /* struct poptOption options [] = {
667 | { "vector_max", 'vm', POPT_ARG_FLOAT, &vecmax, 0, "Reference vector length", "VECMAX" },
668 | { NULL, '\0', 0, NULL, 0, NULL, NULL }}; */
669 | int usermetacount=0, i, ierr;
670 | char **usermetanames, **usermetadata, filename [200];
671 |
672 | /*+ After
673 | +latex+{\tt PETSc}
674 | +html+ <tt>PETSc</tt>
675 | and glade/GNOME initialization, it gets the list of files matching the
676 | basename. +*/
677 | ierr = PetscInitialize (&argc, &argv, (char *)0, help); CHKERRQ (ierr);
678 |
679 | if (argc<2)
680 | {
681 | ierr = PetscPrintf (PETSC_COMM_WORLD, "Usage: tsview basename\n");
682 | CHKERRQ (ierr);
683 | return 1;
684 | }
685 |
686 | #ifdef DEBUG
687 | ierr = PetscPrintf (PETSC_COMM_WORLD, "Command line:"); CHKERRQ (ierr);
688 | for (i=0; i<argc; i++)
689 | {
690 | ierr = PetscPrintf (PETSC_COMM_WORLD, " %s", argv[i]); CHKERRQ (ierr);
691 | }
692 | ierr = PetscPrintf (PETSC_COMM_WORLD, "\n"); CHKERRQ (ierr);
693 | #endif
694 |
695 | vecmax = -1.0;
696 | ierr = PetscOptionsGetScalar (PETSC_NULL, "-vector_max", &vecmax,PETSC_NULL);
697 | CHKERRQ (ierr);
698 | ierr = PetscOptionsHasName (PETSC_NULL, "-no_transparency", &transp);
699 | CHKERRQ (ierr);
700 | transp = !transp;
701 |
702 | /* Kludge alert! Setting argc to avoid gnome_program_init errors;
703 | fix: use GNOME arguments instead of PETSc. */
704 | argc=2;
705 |
706 | gnome_program_init ("TSView", VERSION, LIBGNOMEUI_MODULE, argc, argv, NULL);
707 |
708 | strncpy (filename, GLADE_DIRECTORY, 187);
709 | strcat (filename, "/tsview.glade");
710 | xml = glade_xml_new (filename, NULL, NULL);
711 | glade_xml_signal_autoconnect (xml);
712 |
713 | if (argc>1)
714 | the_basename = argv[1];
715 | else
716 | {
717 | /* Put in filter for .time0000000.cpu0000.meta */
718 | gtk_widget_show (glade_xml_get_widget (xml, "open_fileselect"));
719 | }
720 |
721 | if (refresh_stepnames ())
722 | exit (1);
723 |
724 | DPRINTF ("Loading first timestep, creating distributed array\n",0);
725 | strncpy (filename, basedirname, 198);
726 | strcat (filename, "/");
727 | strncat (filename, stepnames [0], 198 - strlen (stepnames [0]));
728 | ierr = IlluMultiLoad (filename, &theda, minmax+1,minmax+3,minmax+5,
729 | &fieldtypes, &usermetacount, &usermetanames,
730 | &usermetadata);
731 | CHKERRQ (ierr);
732 |
733 | /* Usermetadata xwidth, ywidth, zwidth override minmax in case IlluMulti
734 | version of saved data is 0.1. */
735 | for (i=0; i<usermetacount; i++)
736 | {
737 | if (!strncmp (usermetanames [i], "xwidth", 6))
738 | sscanf (usermetadata [i], "%lf", minmax+1);
739 | else if (!strncmp (usermetanames [i], "ywidth", 6))
740 | sscanf (usermetadata [i], "%lf", minmax+3);
741 | else if (!strncmp (usermetanames [i], "zwidth", 6))
742 | sscanf (usermetadata [i], "%lf", minmax+5);
743 | }
744 |
745 | ierr = DAGetGlobalVector (theda, &global); CHKERRQ (ierr);
746 | ierr = DAGetInfo (theda, &dimensions, PETSC_NULL,PETSC_NULL,PETSC_NULL,
747 | PETSC_NULL,PETSC_NULL,PETSC_NULL, &num_fields,
748 | PETSC_NULL,PETSC_NULL,PETSC_NULL); CHKERRQ (ierr);
749 |
750 | /* Main window title */
751 | {
752 | char main_window_title[100] = "TSView: ";
753 | strncat (main_window_title, basename (the_basename), 90);
754 | gtk_window_set_title
755 | (GTK_WINDOW (glade_xml_get_widget (xml, "main_window")),
756 | main_window_title);
757 | }
758 | gtk_widget_set_sensitive (glade_xml_get_widget (xml, "toolbar"), TRUE);
759 | gtk_widget_show (glade_xml_get_widget (xml, "vbox1"));
760 |
761 | display_timestep (usermetacount, usermetanames, usermetadata);
762 |
763 | gtk_main();
764 |
765 | DPRINTF ("Finalizing and exitting.\n",0);
766 | ierr = PetscFinalize (); CHKERRQ(ierr);
767 | return 0;
768 | }