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 | }