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