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