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