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 - control whether 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 Notes: 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 Notes: 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 Notes: 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 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: `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerType` 361 362 @*/ 363 PetscErrorCode PetscViewerCreate(MPI_Comm comm, PetscViewer *inviewer) { 364 PetscViewer viewer; 365 366 PetscFunctionBegin; 367 *inviewer = NULL; 368 PetscCall(PetscViewerInitializePackage()); 369 PetscCall(PetscHeaderCreate(viewer, PETSC_VIEWER_CLASSID, "PetscViewer", "PetscViewer", "Viewer", comm, PetscViewerDestroy, PetscViewerView)); 370 *inviewer = viewer; 371 viewer->data = NULL; 372 PetscFunctionReturn(0); 373 } 374 375 /*@C 376 PetscViewerSetType - Builds PetscViewer for a particular implementation. 377 378 Collective on PetscViewer 379 380 Input Parameters: 381 + viewer - the PetscViewer context 382 - type - for example, PETSCVIEWERASCII 383 384 Options Database Command: 385 . -viewer_type <type> - Sets the type; use -help for a list 386 of available methods (for instance, ascii) 387 388 Level: advanced 389 390 Notes: 391 See "include/petscviewer.h" for available methods (for instance, 392 PETSCVIEWERSOCKET) 393 394 .seealso: `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()` 395 @*/ 396 PetscErrorCode PetscViewerSetType(PetscViewer viewer, PetscViewerType type) { 397 PetscBool match; 398 PetscErrorCode (*r)(PetscViewer); 399 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 402 PetscValidCharPointer(type, 2); 403 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, type, &match)); 404 if (match) PetscFunctionReturn(0); 405 406 /* cleanup any old type that may be there */ 407 PetscTryTypeMethod(viewer, destroy); 408 viewer->ops->destroy = NULL; 409 viewer->data = NULL; 410 411 PetscCall(PetscMemzero(viewer->ops, sizeof(struct _PetscViewerOps))); 412 413 PetscCall(PetscFunctionListFind(PetscViewerList, type, &r)); 414 PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscViewer type given: %s", type); 415 416 PetscCall(PetscObjectChangeTypeName((PetscObject)viewer, type)); 417 PetscCall((*r)(viewer)); 418 PetscFunctionReturn(0); 419 } 420 421 /*@C 422 PetscViewerRegister - Adds a viewer 423 424 Not Collective 425 426 Input Parameters: 427 + name_solver - name of a new user-defined viewer 428 - routine_create - routine to create method context 429 430 Level: developer 431 Notes: 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 the graphics type from the options database. 455 Defaults to a PETSc X windows graphics. 456 457 Collective on PetscViewer 458 459 Input Parameter: 460 . PetscViewer - the graphics context 461 462 Level: intermediate 463 464 Notes: 465 Must be called after PetscViewerCreate() before the PetscViewer is used. 466 467 .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType` 468 469 @*/ 470 PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer) { 471 char vtype[256]; 472 PetscBool flg; 473 474 PetscFunctionBegin; 475 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 476 477 if (!PetscViewerList) PetscCall(PetscViewerRegisterAll()); 478 PetscObjectOptionsBegin((PetscObject)viewer); 479 PetscCall(PetscOptionsFList("-viewer_type", "Type of PetscViewer", "None", PetscViewerList, (char *)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII), vtype, 256, &flg)); 480 if (flg) PetscCall(PetscViewerSetType(viewer, vtype)); 481 /* type has not been set? */ 482 if (!((PetscObject)viewer)->type_name) PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 483 PetscTryTypeMethod(viewer, setfromoptions, PetscOptionsObject); 484 485 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 486 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject)); 487 PetscCall(PetscViewerViewFromOptions(viewer, NULL, "-viewer_view")); 488 PetscOptionsEnd(); 489 PetscFunctionReturn(0); 490 } 491 492 PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt) { 493 PetscFunctionBegin; 494 PetscCall(PetscViewerBinaryGetFlowControl(viewer, mcnt)); 495 PetscCall(PetscViewerBinaryGetFlowControl(viewer, cnt)); 496 PetscFunctionReturn(0); 497 } 498 499 PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt) { 500 MPI_Comm comm; 501 502 PetscFunctionBegin; 503 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 504 if (i >= *mcnt) { 505 *mcnt += cnt; 506 PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm)); 507 } 508 PetscFunctionReturn(0); 509 } 510 511 PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt) { 512 MPI_Comm comm; 513 PetscFunctionBegin; 514 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 515 *mcnt = 0; 516 PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm)); 517 PetscFunctionReturn(0); 518 } 519 520 PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt) { 521 MPI_Comm comm; 522 PetscFunctionBegin; 523 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 524 while (PETSC_TRUE) { 525 if (rank < *mcnt) break; 526 PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm)); 527 } 528 PetscFunctionReturn(0); 529 } 530 531 PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt) { 532 MPI_Comm comm; 533 PetscFunctionBegin; 534 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 535 while (PETSC_TRUE) { 536 PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm)); 537 if (!*mcnt) break; 538 } 539 PetscFunctionReturn(0); 540 } 541