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