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