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 PetscFunctionBegin; 19 if (!*hp) PetscFunctionReturn(0); 20 kh_destroy(HTPrinted, (*hp)->printed); 21 PetscCall(PetscSegBufferDestroy(&(*hp)->strings)); 22 PetscCall(PetscFree(*hp)); 23 PetscFunctionReturn(0); 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 Not collective 31 32 Level: developer 33 34 .seealso: `PetscOptionsHelpPrintedCheck()`, `PetscOptionsHelpPrintChecked()` 35 @*/ 36 PetscErrorCode PetscOptionsHelpPrintedCreate(PetscOptionsHelpPrinted *hp) { 37 PetscFunctionBegin; 38 PetscCall(PetscNew(hp)); 39 (*hp)->printed = kh_init(HTPrinted); 40 PetscCall(PetscSegBufferCreate(sizeof(char), 10000, &(*hp)->strings)); 41 PetscFunctionReturn(0); 42 } 43 44 /*@C 45 PetscOptionsHelpPrintedCheck - Checks if a particular pre, name pair has previous been entered (meaning the help message was printed) 46 47 Not collective 48 49 Input Parameters: 50 + hp - the object used to manage tracking what help messages have been printed 51 . pre - the prefix part of the string, many be NULL 52 - name - the string to look for (cannot be NULL) 53 54 Output Parameter: 55 . found - PETSC_TRUE if the string was already set 56 57 Level: intermediate 58 59 .seealso: `PetscOptionsHelpPrintedCreate()` 60 @*/ 61 PetscErrorCode PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrinted hp, const char *pre, const char *name, PetscBool *found) { 62 size_t l1, l2; 63 #if !defined(PETSC_HAVE_THREADSAFETY) 64 char *both; 65 int newitem; 66 #endif 67 68 PetscFunctionBegin; 69 PetscCall(PetscStrlen(pre, &l1)); 70 PetscCall(PetscStrlen(name, &l2)); 71 if (l1 + l2 == 0) { 72 *found = PETSC_FALSE; 73 PetscFunctionReturn(0); 74 } 75 #if !defined(PETSC_HAVE_THREADSAFETY) 76 PetscCall(PetscSegBufferGet(hp->strings, l1 + l2 + 1, &both)); 77 PetscCall(PetscStrcpy(both, pre)); 78 PetscCall(PetscStrcat(both, name)); 79 kh_put(HTPrinted, hp->printed, both, &newitem); 80 if (!newitem) PetscCall(PetscSegBufferUnuse(hp->strings, l1 + l2 + 1)); 81 *found = newitem ? PETSC_FALSE : PETSC_TRUE; 82 #else 83 *found = PETSC_FALSE; 84 #endif 85 PetscFunctionReturn(0); 86 } 87 88 static PetscBool noviewer = PETSC_FALSE; 89 static PetscBool noviewers[PETSCVIEWERGETVIEWEROFFPUSHESMAX]; 90 static PetscInt inoviewers = 0; 91 92 /*@ 93 PetscOptionsPushGetViewerOff - sets if a `PetscOptionsGetViewer()` returns a viewer. 94 95 Logically Collective 96 97 Input Parameter: 98 . flg - `PETSC_TRUE` to turn off viewer creation, `PETSC_FALSE` to turn it on. 99 100 Level: developer 101 102 Note: 103 Calling XXXViewFromOptions in an inner loop can be very expensive. This can appear, for example, when using 104 many small subsolves. Call this function to control viewer creation in `PetscOptionsGetViewer()`, thus removing the expensive XXXViewFromOptions calls. 105 106 .seealso: `PetscOptionsGetViewer()`, `PetscOptionsPopGetViewerOff()` 107 @*/ 108 PetscErrorCode PetscOptionsPushGetViewerOff(PetscBool flg) { 109 PetscFunctionBegin; 110 PetscCheck(inoviewers < PETSCVIEWERGETVIEWEROFFPUSHESMAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPushGetViewerOff(), perhaps you forgot PetscOptionsPopGetViewerOff()?"); 111 112 noviewers[inoviewers++] = noviewer; 113 noviewer = flg; 114 PetscFunctionReturn(0); 115 } 116 117 /*@ 118 PetscOptionsPopGetViewerOff - reset whether `PetscOptionsGetViewer()` returns a viewer. 119 120 Logically Collective 121 122 Level: developer 123 124 Note: 125 Calling XXXViewFromOptions in an inner loop can be very expensive. This can appear, for example, when using 126 many small subsolves. Call this function to control viewer creation in `PetscOptionsGetViewer()`, thus removing the expensive XXXViewFromOptions calls. 127 128 .seealso: `PetscOptionsGetViewer()`, `PetscOptionsPushGetViewerOff()` 129 @*/ 130 PetscErrorCode PetscOptionsPopGetViewerOff(void) { 131 PetscFunctionBegin; 132 PetscCheck(inoviewers, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPopGetViewerOff(), perhaps you forgot PetscOptionsPushGetViewerOff()?"); 133 noviewer = noviewers[--inoviewers]; 134 PetscFunctionReturn(0); 135 } 136 137 /*@ 138 PetscOptionsGetViewerOff - does `PetscOptionsGetViewer()` return a viewer? 139 140 Logically Collective 141 142 Output Parameter: 143 . flg - whether viewers are returned. 144 145 Level: developer 146 147 Note: 148 Calling XXXViewFromOptions in an inner loop can be very expensive. This can appear, for example, when using 149 many small subsolves. 150 151 .seealso: `PetscOptionsGetViewer()`, `PetscOptionsPushGetViewerOff()`, `PetscOptionsPopGetViewerOff()` 152 @*/ 153 PetscErrorCode PetscOptionsGetViewerOff(PetscBool *flg) { 154 PetscFunctionBegin; 155 PetscValidBoolPointer(flg, 1); 156 *flg = noviewer; 157 PetscFunctionReturn(0); 158 } 159 160 /*@C 161 PetscOptionsGetViewer - Gets a viewer appropriate for the type indicated by the user 162 163 Collective 164 165 Input Parameters: 166 + comm - the communicator to own the viewer 167 . options - options database, use NULL for default global database 168 . pre - the string to prepend to the name or NULL 169 - name - the option one is seeking 170 171 Output Parameters: 172 + viewer - the viewer, pass NULL if not needed 173 . format - the `PetscViewerFormat` requested by the user, pass NULL if not needed 174 - set - `PETSC_TRUE` if found, else `PETSC_FALSE` 175 176 Level: intermediate 177 178 Notes: 179 If no value is provided ascii:stdout is used 180 + ascii[:[filename][:[format][:append]]] - defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 181 for example ascii::ascii_info prints just the information about the object not all details 182 unless :append is given filename opens in write mode, overwriting what was already there 183 . binary[:[filename][:[format][:append]]] - defaults to the file binaryoutput 184 . draw[:drawtype[:filename]] - for example, draw:tikz, draw:tikz:figure.tex or draw:x 185 . socket[:port] - defaults to the standard output port 186 - saws[:communicatorname] - publishes object to the Scientific Application Webserver (SAWs) 187 188 Use `PetscViewerDestroy()` after using the viewer, otherwise a memory leak will occur 189 190 You can control whether calls to this function create a viewer (or return early with *set of `PETSC_FALSE`) with 191 `PetscOptionsPushGetViewerOff()`. This is useful if calling many small subsolves, in which case XXXViewFromOptions can take 192 an appreciable fraction of the runtime. 193 194 If PETSc is configured with --with-viewfromoptions=0 this function always returns with *set of `PETSC_FALSE` 195 196 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, 197 `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 198 `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`, 199 `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 200 `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 201 `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 202 `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsPushGetViewerOff()`, `PetscOptionsPopGetViewerOff()`, 203 `PetscOptionsGetViewerOff()` 204 @*/ 205 PetscErrorCode PetscOptionsGetViewer(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set) { 206 const char *value; 207 PetscBool flag, hashelp; 208 209 PetscFunctionBegin; 210 PetscValidCharPointer(name, 4); 211 212 if (viewer) *viewer = NULL; 213 if (format) *format = PETSC_VIEWER_DEFAULT; 214 if (set) *set = PETSC_FALSE; 215 PetscCall(PetscOptionsGetViewerOff(&flag)); 216 if (flag) PetscFunctionReturn(0); 217 218 PetscCall(PetscOptionsHasHelp(NULL, &hashelp)); 219 if (hashelp) { 220 PetscBool found; 221 222 if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton)); 223 PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, pre, name, &found)); 224 if (!found && viewer) { 225 PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\nViewer (-%s%s) options:\n", pre ? pre : "", name + 1)); 226 PetscCall((*PetscHelpPrintf)(comm, " -%s%s ascii[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Prints object to stdout or ASCII file", "PetscOptionsGetViewer")); 227 PetscCall((*PetscHelpPrintf)(comm, " -%s%s binary[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Saves object to a binary file", "PetscOptionsGetViewer")); 228 PetscCall((*PetscHelpPrintf)(comm, " -%s%s draw[:[drawtype][:filename|format]] %s (%s)\n", pre ? pre : "", name + 1, "Draws object", "PetscOptionsGetViewer")); 229 PetscCall((*PetscHelpPrintf)(comm, " -%s%s socket[:port]: %s (%s)\n", pre ? pre : "", name + 1, "Pushes object to a Unix socket", "PetscOptionsGetViewer")); 230 PetscCall((*PetscHelpPrintf)(comm, " -%s%s saws[:communicatorname]: %s (%s)\n", pre ? pre : "", name + 1, "Publishes object to SAWs", "PetscOptionsGetViewer")); 231 } 232 } 233 234 if (format) *format = PETSC_VIEWER_DEFAULT; 235 PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag)); 236 if (flag) { 237 if (set) *set = PETSC_TRUE; 238 if (!value) { 239 if (viewer) { 240 PetscCall(PetscViewerASCIIGetStdout(comm, viewer)); 241 PetscCall(PetscObjectReference((PetscObject)*viewer)); 242 } 243 } else { 244 char *loc0_vtype, *loc1_fname, *loc2_fmt = NULL, *loc3_fmode = NULL; 245 PetscInt cnt; 246 const char *viewers[] = {PETSCVIEWERASCII, PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSOCKET, PETSCVIEWERMATLAB, PETSCVIEWERSAWS, PETSCVIEWERVTK, PETSCVIEWERHDF5, PETSCVIEWERGLVIS, PETSCVIEWEREXODUSII, NULL}; 247 248 PetscCall(PetscStrallocpy(value, &loc0_vtype)); 249 PetscCall(PetscStrchr(loc0_vtype, ':', &loc1_fname)); 250 if (loc1_fname) { 251 *loc1_fname++ = 0; 252 PetscCall(PetscStrchr(loc1_fname, ':', &loc2_fmt)); 253 } 254 if (loc2_fmt) { 255 *loc2_fmt++ = 0; 256 PetscCall(PetscStrchr(loc2_fmt, ':', &loc3_fmode)); 257 } 258 if (loc3_fmode) *loc3_fmode++ = 0; 259 PetscCall(PetscStrendswithwhich(*loc0_vtype ? loc0_vtype : "ascii", viewers, &cnt)); 260 PetscCheck(cnt <= (PetscInt)sizeof(viewers) - 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Unknown viewer type: %s", loc0_vtype); 261 if (viewer) { 262 if (!loc1_fname) { 263 switch (cnt) { 264 case 0: PetscCall(PetscViewerASCIIGetStdout(comm, viewer)); break; 265 case 1: 266 if (!(*viewer = PETSC_VIEWER_BINARY_(comm))) PetscCall(PETSC_ERR_PLIB); 267 break; 268 case 2: 269 if (!(*viewer = PETSC_VIEWER_DRAW_(comm))) PetscCall(PETSC_ERR_PLIB); 270 break; 271 #if defined(PETSC_USE_SOCKET_VIEWER) 272 case 3: 273 if (!(*viewer = PETSC_VIEWER_SOCKET_(comm))) PetscCall(PETSC_ERR_PLIB); 274 break; 275 #endif 276 #if defined(PETSC_HAVE_MATLAB_ENGINE) 277 case 4: 278 if (!(*viewer = PETSC_VIEWER_MATLAB_(comm))) PetscCall(PETSC_ERR_PLIB); 279 break; 280 #endif 281 #if defined(PETSC_HAVE_SAWS) 282 case 5: 283 if (!(*viewer = PETSC_VIEWER_SAWS_(comm))) PetscCall(PETSC_ERR_PLIB); 284 break; 285 #endif 286 #if defined(PETSC_HAVE_HDF5) 287 case 7: 288 if (!(*viewer = PETSC_VIEWER_HDF5_(comm))) PetscCall(PETSC_ERR_PLIB); 289 break; 290 #endif 291 case 8: 292 if (!(*viewer = PETSC_VIEWER_GLVIS_(comm))) PetscCall(PETSC_ERR_PLIB); 293 break; 294 #if defined(PETSC_HAVE_EXODUSII) 295 case 9: 296 if (!(*viewer = PETSC_VIEWER_EXODUSII_(comm))) PetscCall(PETSC_ERR_PLIB); 297 break; 298 #endif 299 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported viewer %s", loc0_vtype); 300 } 301 PetscCall(PetscObjectReference((PetscObject)*viewer)); 302 } else { 303 if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */ 304 PetscCall(PetscViewerASCIIGetStdout(comm, viewer)); 305 PetscCall(PetscObjectReference((PetscObject)*viewer)); 306 } else { 307 PetscFileMode fmode; 308 PetscCall(PetscViewerCreate(comm, viewer)); 309 PetscCall(PetscViewerSetType(*viewer, *loc0_vtype ? loc0_vtype : "ascii")); 310 fmode = FILE_MODE_WRITE; 311 if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */ 312 PetscCall(PetscEnumFind(PetscFileModes, loc3_fmode, (PetscEnum *)&fmode, &flag)); 313 PetscCheck(flag, comm, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown file mode: %s", loc3_fmode); 314 } 315 if (loc2_fmt) { 316 PetscBool tk, im; 317 PetscCall(PetscStrcmp(loc1_fname, "tikz", &tk)); 318 PetscCall(PetscStrcmp(loc1_fname, "image", &im)); 319 if (tk || im) { 320 PetscCall(PetscViewerDrawSetInfo(*viewer, NULL, loc2_fmt, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE)); 321 *loc2_fmt = 0; 322 } 323 } 324 PetscCall(PetscViewerFileSetMode(*viewer, flag ? fmode : FILE_MODE_WRITE)); 325 PetscCall(PetscViewerFileSetName(*viewer, loc1_fname)); 326 if (*loc1_fname) PetscCall(PetscViewerDrawSetDrawType(*viewer, loc1_fname)); 327 PetscCall(PetscViewerSetFromOptions(*viewer)); 328 } 329 } 330 } 331 if (viewer) PetscCall(PetscViewerSetUp(*viewer)); 332 if (loc2_fmt && *loc2_fmt) { 333 PetscViewerFormat tfmt; 334 335 PetscCall(PetscEnumFind(PetscViewerFormats, loc2_fmt, (PetscEnum *)&tfmt, &flag)); 336 if (format) *format = tfmt; 337 PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unknown viewer format %s", loc2_fmt); 338 } else if (viewer && (cnt == 6) && format) { /* Get format from VTK viewer */ 339 PetscCall(PetscViewerGetFormat(*viewer, format)); 340 } 341 PetscCall(PetscFree(loc0_vtype)); 342 } 343 } 344 PetscFunctionReturn(0); 345 } 346 347 /*@ 348 PetscViewerCreate - Creates a viewing context. A `PetscViewer` represents a file, a graphical window, a Unix socket or a variety of other ways of viewing a PETSc object 349 350 Collective 351 352 Input Parameter: 353 . comm - MPI communicator 354 355 Output Parameter: 356 . inviewer - location to put the `PetscViewer` context 357 358 Level: advanced 359 360 .seealso: `PetscViewer`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerType` 361 @*/ 362 PetscErrorCode PetscViewerCreate(MPI_Comm comm, PetscViewer *inviewer) { 363 PetscViewer viewer; 364 365 PetscFunctionBegin; 366 *inviewer = NULL; 367 PetscCall(PetscViewerInitializePackage()); 368 PetscCall(PetscHeaderCreate(viewer, PETSC_VIEWER_CLASSID, "PetscViewer", "PetscViewer", "Viewer", comm, PetscViewerDestroy, PetscViewerView)); 369 *inviewer = viewer; 370 viewer->data = NULL; 371 PetscFunctionReturn(0); 372 } 373 374 /*@C 375 PetscViewerSetType - Builds `PetscViewer` for a particular implementation. 376 377 Collective on viewer 378 379 Input Parameters: 380 + viewer - the `PetscViewer` context obtained with `PetscViewerCreate()` 381 - type - for example, `PETSCVIEWERASCII` 382 383 Options Database Command: 384 . -viewer_type <type> - Sets the type; use -help for a list 385 of available methods (for instance, ascii) 386 387 Level: advanced 388 389 Note: 390 See "include/petscviewer.h" for available methods (for instance, 391 `PETSCVIEWERSOCKET`) 392 393 .seealso: `PetscViewer`, `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()` 394 @*/ 395 PetscErrorCode PetscViewerSetType(PetscViewer viewer, PetscViewerType type) { 396 PetscBool match; 397 PetscErrorCode (*r)(PetscViewer); 398 399 PetscFunctionBegin; 400 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 401 PetscValidCharPointer(type, 2); 402 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, type, &match)); 403 if (match) PetscFunctionReturn(0); 404 405 /* cleanup any old type that may be there */ 406 PetscTryTypeMethod(viewer, destroy); 407 viewer->ops->destroy = NULL; 408 viewer->data = NULL; 409 410 PetscCall(PetscMemzero(viewer->ops, sizeof(struct _PetscViewerOps))); 411 412 PetscCall(PetscFunctionListFind(PetscViewerList, type, &r)); 413 PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscViewer type given: %s", type); 414 415 PetscCall(PetscObjectChangeTypeName((PetscObject)viewer, type)); 416 PetscCall((*r)(viewer)); 417 PetscFunctionReturn(0); 418 } 419 420 /*@C 421 PetscViewerRegister - Adds a viewer to those available for use 422 423 Not Collective 424 425 Input Parameters: 426 + name_solver - name of a new user-defined viewer 427 - routine_create - routine to create method context 428 429 Level: developer 430 431 Note: 432 `PetscViewerRegister()` may be called multiple times to add several user-defined viewers. 433 434 Sample usage: 435 .vb 436 PetscViewerRegister("my_viewer_type",MyViewerCreate); 437 .ve 438 439 Then, your solver can be chosen with the procedural interface via 440 $ PetscViewerSetType(viewer,"my_viewer_type") 441 or at runtime via the option 442 $ -viewer_type my_viewer_type 443 444 .seealso: `PetscViewerRegisterAll()` 445 @*/ 446 PetscErrorCode PetscViewerRegister(const char *sname, PetscErrorCode (*function)(PetscViewer)) { 447 PetscFunctionBegin; 448 PetscCall(PetscViewerInitializePackage()); 449 PetscCall(PetscFunctionListAdd(&PetscViewerList, sname, function)); 450 PetscFunctionReturn(0); 451 } 452 453 /*@C 454 PetscViewerSetFromOptions - Sets various options for a viewer from the options database. 455 456 Collective on viewer 457 458 Input Parameter: 459 . viewer - the viewer context 460 461 Level: intermediate 462 463 Note: 464 Must be called after PetscViewerCreate() before the PetscViewer is used. 465 466 .seealso: `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType` 467 @*/ 468 PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer) { 469 char vtype[256]; 470 PetscBool flg; 471 472 PetscFunctionBegin; 473 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 474 475 if (!PetscViewerList) PetscCall(PetscViewerRegisterAll()); 476 PetscObjectOptionsBegin((PetscObject)viewer); 477 PetscCall(PetscOptionsFList("-viewer_type", "Type of PetscViewer", "None", PetscViewerList, (char *)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII), vtype, 256, &flg)); 478 if (flg) PetscCall(PetscViewerSetType(viewer, vtype)); 479 /* type has not been set? */ 480 if (!((PetscObject)viewer)->type_name) PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 481 PetscTryTypeMethod(viewer, setfromoptions, PetscOptionsObject); 482 483 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 484 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject)); 485 PetscCall(PetscViewerViewFromOptions(viewer, NULL, "-viewer_view")); 486 PetscOptionsEnd(); 487 PetscFunctionReturn(0); 488 } 489 490 PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt) { 491 PetscFunctionBegin; 492 PetscCall(PetscViewerBinaryGetFlowControl(viewer, mcnt)); 493 PetscCall(PetscViewerBinaryGetFlowControl(viewer, cnt)); 494 PetscFunctionReturn(0); 495 } 496 497 PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt) { 498 MPI_Comm comm; 499 500 PetscFunctionBegin; 501 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 502 if (i >= *mcnt) { 503 *mcnt += cnt; 504 PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm)); 505 } 506 PetscFunctionReturn(0); 507 } 508 509 PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt) { 510 MPI_Comm comm; 511 PetscFunctionBegin; 512 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 513 *mcnt = 0; 514 PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm)); 515 PetscFunctionReturn(0); 516 } 517 518 PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt) { 519 MPI_Comm comm; 520 PetscFunctionBegin; 521 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 522 while (PETSC_TRUE) { 523 if (rank < *mcnt) break; 524 PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm)); 525 } 526 PetscFunctionReturn(0); 527 } 528 529 PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt) { 530 MPI_Comm comm; 531 PetscFunctionBegin; 532 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 533 while (PETSC_TRUE) { 534 PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm)); 535 if (!*mcnt) break; 536 } 537 PetscFunctionReturn(0); 538 } 539