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