1 #include <petsc/private/viewerimpl.h> /*I "petscviewer.h" I*/ 2 #include <petsc/private/hashtable.h> 3 #if defined(PETSC_HAVE_SAWS) 4 #include <petscviewersaws.h> 5 #endif 6 7 PetscFunctionList PetscViewerList = NULL; 8 9 PetscOptionsHelpPrinted PetscOptionsHelpPrintedSingleton = NULL; 10 KHASH_SET_INIT_STR(HTPrinted) 11 struct _n_PetscOptionsHelpPrinted { 12 khash_t(HTPrinted) *printed; 13 PetscSegBuffer strings; 14 }; 15 16 PetscErrorCode PetscOptionsHelpPrintedDestroy(PetscOptionsHelpPrinted *hp) 17 { 18 PetscFunctionBegin; 19 if (!*hp) PetscFunctionReturn(PETSC_SUCCESS); 20 kh_destroy(HTPrinted, (*hp)->printed); 21 PetscCall(PetscSegBufferDestroy(&(*hp)->strings)); 22 PetscCall(PetscFree(*hp)); 23 PetscFunctionReturn(PETSC_SUCCESS); 24 } 25 26 /*@C 27 PetscOptionsHelpPrintedCreate - Creates an object used to manage tracking which help messages have 28 been printed so they will not be printed again. 29 30 Output Parameter: 31 . hp - the created object 32 33 Not Collective 34 35 Level: developer 36 37 .seealso: `PetscOptionsHelpPrintedCheck()`, `PetscOptionsHelpPrintChecked()` 38 @*/ 39 PetscErrorCode PetscOptionsHelpPrintedCreate(PetscOptionsHelpPrinted *hp) 40 { 41 PetscFunctionBegin; 42 PetscCall(PetscNew(hp)); 43 (*hp)->printed = kh_init(HTPrinted); 44 PetscCall(PetscSegBufferCreate(sizeof(char), 10000, &(*hp)->strings)); 45 PetscFunctionReturn(PETSC_SUCCESS); 46 } 47 48 /*@C 49 PetscOptionsHelpPrintedCheck - Checks if a particular pre, name pair has previous been entered (meaning the help message was printed) 50 51 Not Collective 52 53 Input Parameters: 54 + hp - the object used to manage tracking what help messages have been printed 55 . pre - the prefix part of the string, many be `NULL` 56 - name - the string to look for (cannot be `NULL`) 57 58 Output Parameter: 59 . found - `PETSC_TRUE` if the string was already set 60 61 Level: intermediate 62 63 .seealso: `PetscOptionsHelpPrintedCreate()` 64 @*/ 65 PetscErrorCode PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrinted hp, const char *pre, const char *name, PetscBool *found) 66 { 67 size_t l1, l2; 68 #if !defined(PETSC_HAVE_THREADSAFETY) 69 char *both; 70 int newitem; 71 #endif 72 73 PetscFunctionBegin; 74 PetscCall(PetscStrlen(pre, &l1)); 75 PetscCall(PetscStrlen(name, &l2)); 76 if (l1 + l2 == 0) { 77 *found = PETSC_FALSE; 78 PetscFunctionReturn(PETSC_SUCCESS); 79 } 80 #if !defined(PETSC_HAVE_THREADSAFETY) 81 size_t lboth = l1 + l2 + 1; 82 PetscCall(PetscSegBufferGet(hp->strings, lboth, &both)); 83 PetscCall(PetscStrncpy(both, pre, lboth)); 84 PetscCall(PetscStrncpy(both + l1, name, l2 + 1)); 85 kh_put(HTPrinted, hp->printed, both, &newitem); 86 if (!newitem) PetscCall(PetscSegBufferUnuse(hp->strings, lboth)); 87 *found = newitem ? PETSC_FALSE : PETSC_TRUE; 88 #else 89 *found = PETSC_FALSE; 90 #endif 91 PetscFunctionReturn(PETSC_SUCCESS); 92 } 93 94 static PetscBool noviewer = PETSC_FALSE; 95 static PetscBool noviewers[PETSCVIEWERCREATEVIEWEROFFPUSHESMAX]; 96 static PetscInt inoviewers = 0; 97 98 /*@ 99 PetscOptionsPushCreateViewerOff - sets if a `PetscOptionsCreateViewer()`, `PetscOptionsViewer(), and `PetscOptionsCreateViewers()` returns viewers. 100 101 Logically Collective 102 103 Input Parameter: 104 . flg - `PETSC_TRUE` to turn off viewer creation, `PETSC_FALSE` to turn it on. 105 106 Level: developer 107 108 Note: 109 Calling `XXXViewFromOptions` in an inner loop can be expensive. This can appear, for example, when using 110 many small subsolves. Call this function to control viewer creation in `PetscOptionsCreateViewer()`, thus removing the expensive `XXXViewFromOptions` calls. 111 112 Developer Notes: 113 Instead of using this approach, the calls to `PetscOptionsCreateViewer()` can be moved into `XXXSetFromOptions()` 114 115 .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPopCreateViewerOff()` 116 @*/ 117 PetscErrorCode PetscOptionsPushCreateViewerOff(PetscBool flg) 118 { 119 PetscFunctionBegin; 120 PetscCheck(inoviewers < PETSCVIEWERCREATEVIEWEROFFPUSHESMAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPushCreateViewerOff(), perhaps you forgot PetscOptionsPopCreateViewerOff()?"); 121 122 noviewers[inoviewers++] = noviewer; 123 noviewer = flg; 124 PetscFunctionReturn(PETSC_SUCCESS); 125 } 126 127 /*@ 128 PetscOptionsPopCreateViewerOff - reset whether `PetscOptionsCreateViewer()` returns a viewer. 129 130 Logically Collective 131 132 Level: developer 133 134 Note: 135 See `PetscOptionsPushCreateViewerOff()` 136 137 .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPushCreateViewerOff()` 138 @*/ 139 PetscErrorCode PetscOptionsPopCreateViewerOff(void) 140 { 141 PetscFunctionBegin; 142 PetscCheck(inoviewers, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPopCreateViewerOff(), perhaps you forgot PetscOptionsPushCreateViewerOff()?"); 143 noviewer = noviewers[--inoviewers]; 144 PetscFunctionReturn(PETSC_SUCCESS); 145 } 146 147 /*@ 148 PetscOptionsGetCreateViewerOff - do `PetscOptionsCreateViewer()`, `PetscOptionsViewer(), and `PetscOptionsCreateViewers()` return viewers 149 150 Logically Collective 151 152 Output Parameter: 153 . flg - whether viewers are returned. 154 155 Level: developer 156 157 .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPushCreateViewerOff()`, `PetscOptionsPopCreateViewerOff()` 158 @*/ 159 PetscErrorCode PetscOptionsGetCreateViewerOff(PetscBool *flg) 160 { 161 PetscFunctionBegin; 162 PetscAssertPointer(flg, 1); 163 *flg = noviewer; 164 PetscFunctionReturn(PETSC_SUCCESS); 165 } 166 167 static PetscErrorCode PetscOptionsCreateViewers_Single(MPI_Comm comm, const char value[], PetscViewer *viewer, PetscViewerFormat *format) 168 { 169 char *loc0_vtype = NULL, *loc1_fname = NULL, *loc2_fmt = NULL, *loc3_fmode = NULL; 170 PetscInt cnt; 171 size_t viewer_string_length; 172 const char *viewers[] = {PETSCVIEWERASCII, PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSOCKET, PETSCVIEWERMATLAB, PETSCVIEWERSAWS, PETSCVIEWERVTK, PETSCVIEWERHDF5, PETSCVIEWERGLVIS, PETSCVIEWEREXODUSII, NULL}; /* list should be automatically generated from PetscViewersList */ 173 174 PetscFunctionBegin; 175 PetscCall(PetscStrlen(value, &viewer_string_length)); 176 if (!viewer_string_length) { 177 if (format) *format = PETSC_VIEWER_DEFAULT; 178 if (viewer) { 179 PetscCall(PetscViewerASCIIGetStdout(comm, viewer)); 180 PetscCall(PetscObjectReference((PetscObject)*viewer)); 181 } 182 PetscFunctionReturn(PETSC_SUCCESS); 183 } 184 185 PetscCall(PetscStrallocpy(value, &loc0_vtype)); 186 PetscCall(PetscStrchr(loc0_vtype, ':', &loc1_fname)); 187 if (loc1_fname) { 188 *loc1_fname++ = 0; 189 PetscCall(PetscStrchr(loc1_fname, ':', &loc2_fmt)); 190 } 191 if (loc2_fmt) { 192 *loc2_fmt++ = 0; 193 PetscCall(PetscStrchr(loc2_fmt, ':', &loc3_fmode)); 194 } 195 if (loc3_fmode) *loc3_fmode++ = 0; 196 PetscCall(PetscStrendswithwhich(*loc0_vtype ? loc0_vtype : "ascii", viewers, &cnt)); 197 PetscCheck(cnt <= (PetscInt)sizeof(viewers) - 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Unknown viewer type: %s", loc0_vtype); 198 if (viewer) { 199 if (!loc1_fname) { 200 switch (cnt) { 201 case 0: 202 PetscCall(PetscViewerASCIIGetStdout(comm, viewer)); 203 PetscCall(PetscObjectReference((PetscObject)*viewer)); 204 break; 205 case 1: 206 if (!(*viewer = PETSC_VIEWER_BINARY_(comm))) PetscCall(PETSC_ERR_PLIB); 207 PetscCall(PetscObjectReference((PetscObject)*viewer)); 208 break; 209 case 2: 210 if (!(*viewer = PETSC_VIEWER_DRAW_(comm))) PetscCall(PETSC_ERR_PLIB); 211 PetscCall(PetscObjectReference((PetscObject)*viewer)); 212 break; 213 #if defined(PETSC_USE_SOCKET_VIEWER) 214 case 3: 215 if (!(*viewer = PETSC_VIEWER_SOCKET_(comm))) PetscCall(PETSC_ERR_PLIB); 216 PetscCall(PetscObjectReference((PetscObject)*viewer)); 217 break; 218 #endif 219 #if defined(PETSC_HAVE_MATLAB) 220 case 4: 221 if (!(*viewer = PETSC_VIEWER_MATLAB_(comm))) PetscCall(PETSC_ERR_PLIB); 222 PetscCall(PetscObjectReference((PetscObject)*viewer)); 223 break; 224 #endif 225 #if defined(PETSC_HAVE_SAWS) 226 case 5: 227 if (!(*viewer = PETSC_VIEWER_SAWS_(comm))) PetscCall(PETSC_ERR_PLIB); 228 PetscCall(PetscObjectReference((PetscObject)*viewer)); 229 break; 230 #endif 231 #if defined(PETSC_HAVE_HDF5) 232 case 7: 233 if (!(*viewer = PETSC_VIEWER_HDF5_(comm))) PetscCall(PETSC_ERR_PLIB); 234 PetscCall(PetscObjectReference((PetscObject)*viewer)); 235 break; 236 #endif 237 case 8: 238 if (!(*viewer = PETSC_VIEWER_GLVIS_(comm))) PetscCall(PETSC_ERR_PLIB); 239 PetscCall(PetscObjectReference((PetscObject)*viewer)); 240 break; 241 #if defined(PETSC_HAVE_EXODUSII) 242 case 9: 243 if (!(*viewer = PETSC_VIEWER_EXODUSII_(comm))) PetscCall(PETSC_ERR_PLIB); 244 PetscCall(PetscObjectReference((PetscObject)*viewer)); 245 break; 246 #endif 247 default: 248 SETERRQ(comm, PETSC_ERR_SUP, "Unsupported viewer %s", loc0_vtype); 249 } 250 } else { 251 if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */ 252 PetscCall(PetscViewerASCIIGetStdout(comm, viewer)); 253 PetscCall(PetscObjectReference((PetscObject)*viewer)); 254 } else { 255 PetscFileMode fmode; 256 PetscBool flag = PETSC_FALSE; 257 258 PetscCall(PetscViewerCreate(comm, viewer)); 259 PetscCall(PetscViewerSetType(*viewer, *loc0_vtype ? loc0_vtype : "ascii")); 260 fmode = FILE_MODE_WRITE; 261 if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */ 262 PetscCall(PetscEnumFind(PetscFileModes, loc3_fmode, (PetscEnum *)&fmode, &flag)); 263 PetscCheck(flag, comm, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown file mode: %s", loc3_fmode); 264 } 265 if (loc2_fmt) { 266 PetscBool tk, im; 267 PetscCall(PetscStrcmp(loc1_fname, "tikz", &tk)); 268 PetscCall(PetscStrcmp(loc1_fname, "image", &im)); 269 if (tk || im) { 270 PetscCall(PetscViewerDrawSetInfo(*viewer, NULL, loc2_fmt, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE)); 271 *loc2_fmt = 0; 272 } 273 } 274 PetscCall(PetscViewerFileSetMode(*viewer, flag ? fmode : FILE_MODE_WRITE)); 275 PetscCall(PetscViewerFileSetName(*viewer, loc1_fname)); 276 if (*loc1_fname) PetscCall(PetscViewerDrawSetDrawType(*viewer, loc1_fname)); 277 PetscCall(PetscViewerSetFromOptions(*viewer)); 278 } 279 } 280 } 281 if (viewer) PetscCall(PetscViewerSetUp(*viewer)); 282 if (loc2_fmt && *loc2_fmt) { 283 PetscViewerFormat tfmt; 284 PetscBool flag; 285 286 PetscCall(PetscEnumFind(PetscViewerFormats, loc2_fmt, (PetscEnum *)&tfmt, &flag)); 287 if (format) *format = tfmt; 288 PetscCheck(flag, comm, PETSC_ERR_SUP, "Unknown viewer format %s", loc2_fmt); 289 } else if (viewer && (cnt == 6) && format) { /* Get format from VTK viewer */ 290 PetscCall(PetscViewerGetFormat(*viewer, format)); 291 } 292 PetscCall(PetscFree(loc0_vtype)); 293 PetscFunctionReturn(PETSC_SUCCESS); 294 } 295 296 static PetscErrorCode PetscOptionsCreateViewers_Internal(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscInt *n_max_p, PetscViewer viewer[], PetscViewerFormat format[], PetscBool *set, const char func_name[], PetscBool allow_multiple) 297 { 298 const char *value; 299 PetscBool flag, hashelp; 300 PetscInt n_max; 301 302 PetscFunctionBegin; 303 PetscAssertPointer(name, 4); 304 PetscAssertPointer(n_max_p, 5); 305 n_max = *n_max_p; 306 PetscCheck(n_max >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid size %" PetscInt_FMT " of passed arrays", *n_max_p); 307 *n_max_p = 0; 308 309 if (set) *set = PETSC_FALSE; 310 PetscCall(PetscOptionsGetCreateViewerOff(&flag)); 311 if (flag) PetscFunctionReturn(PETSC_SUCCESS); 312 313 PetscCall(PetscOptionsHasHelp(NULL, &hashelp)); 314 if (hashelp) { 315 PetscBool found; 316 317 if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton)); 318 PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, pre, name, &found)); 319 if (!found && viewer) { 320 PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\nViewer (-%s%s) options:\n", pre ? pre : "", name + 1)); 321 PetscCall((*PetscHelpPrintf)(comm, " -%s%s ascii[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Prints object to stdout or ASCII file", func_name)); 322 PetscCall((*PetscHelpPrintf)(comm, " -%s%s binary[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Saves object to a binary file", func_name)); 323 PetscCall((*PetscHelpPrintf)(comm, " -%s%s draw[:[drawtype][:filename|format]] %s (%s)\n", pre ? pre : "", name + 1, "Draws object", func_name)); 324 PetscCall((*PetscHelpPrintf)(comm, " -%s%s socket[:port]: %s (%s)\n", pre ? pre : "", name + 1, "Pushes object to a Unix socket", func_name)); 325 PetscCall((*PetscHelpPrintf)(comm, " -%s%s saws[:communicatorname]: %s (%s)\n", pre ? pre : "", name + 1, "Publishes object to SAWs", func_name)); 326 if (allow_multiple) PetscCall((*PetscHelpPrintf)(comm, " -%s%s v1[,v2,...]: %s (%s)\n", pre ? pre : "", name + 1, "Multiple viewers", func_name)); 327 } 328 } 329 330 PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag)); 331 if (flag) { 332 if (set) *set = PETSC_TRUE; 333 if (!value) { 334 PetscCheck(n_max > 0, comm, PETSC_ERR_ARG_SIZ, "More viewers (1) than max available (0)"); 335 if (format) *format = PETSC_VIEWER_DEFAULT; 336 if (viewer) { 337 PetscCall(PetscViewerASCIIGetStdout(comm, viewer)); 338 PetscCall(PetscObjectReference((PetscObject)*viewer)); 339 } 340 *n_max_p = 1; 341 } else { 342 char *loc0_viewer_string = NULL, *this_viewer_string = NULL; 343 size_t viewer_string_length; 344 345 PetscCall(PetscStrallocpy(value, &loc0_viewer_string)); 346 PetscCall(PetscStrlen(loc0_viewer_string, &viewer_string_length)); 347 this_viewer_string = loc0_viewer_string; 348 349 do { 350 PetscViewer *this_viewer; 351 PetscViewerFormat *this_viewer_format; 352 char *next_viewer_string = NULL; 353 char *comma_separator = NULL; 354 PetscInt n = *n_max_p; 355 356 PetscCheck(n < n_max, comm, PETSC_ERR_PLIB, "More viewers than max available (%d)", (int)n_max); 357 358 PetscCall(PetscStrchr(this_viewer_string, ',', &comma_separator)); 359 if (comma_separator) { 360 PetscCheck(allow_multiple, comm, PETSC_ERR_ARG_OUTOFRANGE, "Trying to pass multiple viewers to %s: only one allowed. Use PetscOptionsCreateViewers() instead", func_name); 361 *comma_separator = 0; 362 next_viewer_string = comma_separator + 1; 363 } 364 this_viewer = PetscSafePointerPlusOffset(viewer, n); 365 if (this_viewer) *this_viewer = NULL; 366 this_viewer_format = PetscSafePointerPlusOffset(format, n); 367 if (this_viewer_format) *this_viewer_format = PETSC_VIEWER_DEFAULT; 368 PetscCall(PetscOptionsCreateViewers_Single(comm, this_viewer_string, this_viewer, this_viewer_format)); 369 this_viewer_string = next_viewer_string; 370 (*n_max_p)++; 371 } while (this_viewer_string); 372 PetscCall(PetscFree(loc0_viewer_string)); 373 } 374 } 375 PetscFunctionReturn(PETSC_SUCCESS); 376 } 377 378 /*@C 379 PetscOptionsCreateViewer - Creates a viewer appropriate for the type indicated by the user 380 381 Collective 382 383 Input Parameters: 384 + comm - the communicator to own the viewer 385 . options - options database, use `NULL` for default global database 386 . pre - the string to prepend to the name or `NULL` 387 - name - the options database name that will be checked for 388 389 Output Parameters: 390 + viewer - the viewer, pass `NULL` if not needed 391 . format - the `PetscViewerFormat` requested by the user, pass `NULL` if not needed 392 - set - `PETSC_TRUE` if found, else `PETSC_FALSE` 393 394 Level: intermediate 395 396 Notes: 397 The argument has the following form 398 .vb 399 type:filename:format:filemode 400 .ve 401 where all parts are optional, but you need to include the colon to access the next part. The mode argument must a valid `PetscFileMode`, i.e. read, write, append, update, or append_update. For example, to read from an HDF5 file, use 402 .vb 403 hdf5:sol.h5::read 404 .ve 405 406 If no value is provided ascii:stdout is used 407 + ascii[:[filename][:[format][:append]]] - defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 408 for example ascii::ascii_info prints just the information about the object not all details 409 unless :append is given filename opens in write mode, overwriting what was already there 410 . binary[:[filename][:[format][:append]]] - defaults to the file binaryoutput 411 . draw[:drawtype[:filename]] - for example, draw:tikz, draw:tikz:figure.tex or draw:x 412 . socket[:port] - defaults to the standard output port 413 - saws[:communicatorname] - publishes object to the Scientific Application Webserver (SAWs) 414 415 You can control whether calls to this function create a viewer (or return early with *set of `PETSC_FALSE`) with 416 `PetscOptionsPushCreateViewerOff()`. This is useful if calling many small subsolves, in which case XXXViewFromOptions can take 417 an appreciable fraction of the runtime. 418 419 If PETSc is configured with `--with-viewfromoptions=0` this function always returns with *set of `PETSC_FALSE` 420 421 This routine is thread-safe for accessing predefined `PetscViewer`s like `PETSC_VIEWER_STDOUT_SELF` but not for accessing 422 files by name. 423 424 .seealso: [](sec_viewers), `PetscViewerDestroy()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, 425 `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 426 `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 427 `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 428 `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 429 `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 430 `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsPushCreateViewerOff()`, `PetscOptionsPopCreateViewerOff()`, 431 `PetscOptionsCreateViewerOff()` 432 @*/ 433 PetscErrorCode PetscOptionsCreateViewer(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set) 434 { 435 PetscInt n_max = 1; 436 PetscBool set_internal; 437 438 PetscFunctionBegin; 439 if (viewer) *viewer = NULL; 440 if (format) *format = PETSC_VIEWER_DEFAULT; 441 PetscCall(PetscOptionsCreateViewers_Internal(comm, options, pre, name, &n_max, viewer, format, &set_internal, PETSC_FUNCTION_NAME, PETSC_FALSE)); 442 if (set_internal) PetscAssert(n_max == 1, comm, PETSC_ERR_PLIB, "Unexpected: %d != 1 viewers set", (int)n_max); 443 if (set) *set = set_internal; 444 PetscFunctionReturn(PETSC_SUCCESS); 445 } 446 447 /*@C 448 PetscOptionsCreateViewers - Create multiple viewers from a comma-separated list in the options database 449 450 Collective 451 452 Input Parameters: 453 + comm - the communicator to own the viewers 454 . options - options database, use `NULL` for default global database 455 . pre - the string to prepend to the name or `NULL` 456 . name - the options database name that will be checked for 457 - n_max - on input: the maximum number of viewers; on output: the number of viewers in the comma-separated list 458 459 Output Parameters: 460 + viewers - an array to hold at least `n_max` `PetscViewer`s, or `NULL` if not needed; on output: if not `NULL`, the 461 first `n_max` entries are initialized `PetscViewer`s 462 . formats - an array to hold at least `n_max` `PetscViewerFormat`s, or `NULL` if not needed; on output: if not 463 `NULL`, the first `n_max` entries are valid `PetscViewewFormat`s 464 - set - `PETSC_TRUE` if found, else `PETSC_FALSE` 465 466 Level: intermediate 467 468 Note: 469 See `PetscOptionsCreateViewer()` for how the format strings for the viewers are interpreted. 470 471 Use `PetscViewerDestroy()` on each viewer, otherwise a memory leak will occur. 472 473 If PETSc is configured with `--with-viewfromoptions=0` this function always returns with `n_max` of 0 and `set` of `PETSC_FALSE` 474 475 .seealso: [](sec_viewers), `PetscOptionsCreateViewer()` 476 @*/ 477 PetscErrorCode PetscOptionsCreateViewers(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscInt *n_max, PetscViewer viewers[], PetscViewerFormat formats[], PetscBool *set) 478 { 479 PetscFunctionBegin; 480 PetscCall(PetscOptionsCreateViewers_Internal(comm, options, pre, name, n_max, viewers, formats, set, PETSC_FUNCTION_NAME, PETSC_TRUE)); 481 PetscFunctionReturn(PETSC_SUCCESS); 482 } 483 484 /*@ 485 PetscViewerCreate - Creates a viewing context. A `PetscViewer` represents a file, a graphical window, a Unix socket or a variety of other ways 486 of viewing a PETSc object 487 488 Collective 489 490 Input Parameter: 491 . comm - MPI communicator 492 493 Output Parameter: 494 . inviewer - location to put the `PetscViewer` context 495 496 Level: advanced 497 498 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerType` 499 @*/ 500 PetscErrorCode PetscViewerCreate(MPI_Comm comm, PetscViewer *inviewer) 501 { 502 PetscViewer viewer; 503 504 PetscFunctionBegin; 505 PetscAssertPointer(inviewer, 2); 506 PetscCall(PetscViewerInitializePackage()); 507 PetscCall(PetscHeaderCreate(viewer, PETSC_VIEWER_CLASSID, "PetscViewer", "PetscViewer", "Viewer", comm, PetscViewerDestroy, PetscViewerView)); 508 *inviewer = viewer; 509 viewer->data = NULL; 510 PetscFunctionReturn(PETSC_SUCCESS); 511 } 512 513 /*@ 514 PetscViewerSetType - Builds `PetscViewer` for a particular implementation. 515 516 Collective 517 518 Input Parameters: 519 + viewer - the `PetscViewer` context obtained with `PetscViewerCreate()` 520 - type - for example, `PETSCVIEWERASCII` 521 522 Options Database Key: 523 . -viewer_type <type> - Sets the type; use -help for a list of available methods (for instance, ascii) 524 525 Level: advanced 526 527 Note: 528 See `PetscViewerType` for possible values 529 530 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()` 531 @*/ 532 PetscErrorCode PetscViewerSetType(PetscViewer viewer, PetscViewerType type) 533 { 534 PetscBool match; 535 PetscErrorCode (*r)(PetscViewer); 536 537 PetscFunctionBegin; 538 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 539 PetscAssertPointer(type, 2); 540 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, type, &match)); 541 if (match) PetscFunctionReturn(PETSC_SUCCESS); 542 543 /* cleanup any old type that may be there */ 544 PetscTryTypeMethod(viewer, destroy); 545 viewer->ops->destroy = NULL; 546 viewer->data = NULL; 547 548 PetscCall(PetscMemzero(viewer->ops, sizeof(struct _PetscViewerOps))); 549 550 PetscCall(PetscFunctionListFind(PetscViewerList, type, &r)); 551 PetscCheck(r, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscViewer type given: %s", type); 552 553 PetscCall(PetscObjectChangeTypeName((PetscObject)viewer, type)); 554 PetscCall((*r)(viewer)); 555 PetscFunctionReturn(PETSC_SUCCESS); 556 } 557 558 /*@C 559 PetscViewerRegister - Adds a viewer to those available for use with `PetscViewerSetType()` 560 561 Not Collective, No Fortran Support 562 563 Input Parameters: 564 + sname - name of a new user-defined viewer 565 - function - routine to create method context 566 567 Level: developer 568 569 Note: 570 `PetscViewerRegister()` may be called multiple times to add several user-defined viewers. 571 572 Example Usage: 573 .vb 574 PetscViewerRegister("my_viewer_type", MyViewerCreate); 575 .ve 576 577 Then, your solver can be chosen with the procedural interface via 578 $ PetscViewerSetType(viewer, "my_viewer_type") 579 or at runtime via the option 580 $ -viewer_type my_viewer_type 581 582 .seealso: [](sec_viewers), `PetscViewerRegisterAll()` 583 @*/ 584 PetscErrorCode PetscViewerRegister(const char *sname, PetscErrorCode (*function)(PetscViewer)) 585 { 586 PetscFunctionBegin; 587 PetscCall(PetscViewerInitializePackage()); 588 PetscCall(PetscFunctionListAdd(&PetscViewerList, sname, function)); 589 PetscFunctionReturn(PETSC_SUCCESS); 590 } 591 592 /*@C 593 PetscViewerSetFromOptions - Sets various options for a viewer based on values in the options database. 594 595 Collective 596 597 Input Parameter: 598 . viewer - the viewer context 599 600 Level: intermediate 601 602 Note: 603 Must be called after `PetscViewerCreate()` but before the `PetscViewer` is used. 604 605 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType` 606 @*/ 607 PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer) 608 { 609 char vtype[256]; 610 PetscBool flg; 611 612 PetscFunctionBegin; 613 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 614 615 if (!PetscViewerList) PetscCall(PetscViewerRegisterAll()); 616 PetscObjectOptionsBegin((PetscObject)viewer); 617 PetscCall(PetscOptionsFList("-viewer_type", "Type of PetscViewer", "None", PetscViewerList, (char *)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII), vtype, 256, &flg)); 618 if (flg) PetscCall(PetscViewerSetType(viewer, vtype)); 619 /* type has not been set? */ 620 if (!((PetscObject)viewer)->type_name) PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 621 PetscTryTypeMethod(viewer, setfromoptions, PetscOptionsObject); 622 623 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 624 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject)); 625 PetscCall(PetscViewerViewFromOptions(viewer, NULL, "-viewer_view")); 626 PetscOptionsEnd(); 627 PetscFunctionReturn(PETSC_SUCCESS); 628 } 629 630 PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt) 631 { 632 PetscFunctionBegin; 633 PetscCall(PetscViewerBinaryGetFlowControl(viewer, mcnt)); 634 PetscCall(PetscViewerBinaryGetFlowControl(viewer, cnt)); 635 PetscFunctionReturn(PETSC_SUCCESS); 636 } 637 638 PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt) 639 { 640 MPI_Comm comm; 641 642 PetscFunctionBegin; 643 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 644 if (i >= *mcnt) { 645 *mcnt += cnt; 646 PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm)); 647 } 648 PetscFunctionReturn(PETSC_SUCCESS); 649 } 650 651 PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt) 652 { 653 MPI_Comm comm; 654 655 PetscFunctionBegin; 656 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 657 *mcnt = 0; 658 PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm)); 659 PetscFunctionReturn(PETSC_SUCCESS); 660 } 661 662 PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt) 663 { 664 MPI_Comm comm; 665 666 PetscFunctionBegin; 667 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 668 while (PETSC_TRUE) { 669 if (rank < *mcnt) break; 670 PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm)); 671 } 672 PetscFunctionReturn(PETSC_SUCCESS); 673 } 674 675 PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt) 676 { 677 MPI_Comm comm; 678 679 PetscFunctionBegin; 680 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 681 while (PETSC_TRUE) { 682 PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm)); 683 if (!*mcnt) break; 684 } 685 PetscFunctionReturn(PETSC_SUCCESS); 686 } 687