1 2 #include <petsc/private/viewerimpl.h> /*I "petscviewer.h" I*/ 3 #include <petscdraw.h> 4 5 PetscClassId PETSC_VIEWER_CLASSID; 6 7 static PetscBool PetscViewerPackageInitialized = PETSC_FALSE; 8 /*@C 9 PetscViewerFinalizePackage - This function destroys any global objects created in the Petsc viewers. It is 10 called from PetscFinalize(). 11 12 Level: developer 13 14 .seealso: `PetscFinalize()` 15 @*/ 16 PetscErrorCode PetscViewerFinalizePackage(void) { 17 PetscFunctionBegin; 18 if (Petsc_Viewer_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_keyval)); 19 if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Stdout_keyval)); 20 if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Stderr_keyval)); 21 if (Petsc_Viewer_Binary_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Binary_keyval)); 22 if (Petsc_Viewer_Draw_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Draw_keyval)); 23 #if defined(PETSC_HAVE_HDF5) 24 if (Petsc_Viewer_HDF5_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_HDF5_keyval)); 25 #endif 26 #if defined(PETSC_USE_SOCKETVIEWER) 27 if (Petsc_Viewer_Socket_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Socket_keyval)); 28 #endif 29 PetscCall(PetscFunctionListDestroy(&PetscViewerList)); 30 PetscViewerPackageInitialized = PETSC_FALSE; 31 PetscViewerRegisterAllCalled = PETSC_FALSE; 32 PetscFunctionReturn(0); 33 } 34 35 /*@C 36 PetscViewerInitializePackage - This function initializes everything in the main PetscViewer package. 37 38 Level: developer 39 40 .seealso: `PetscInitialize()` 41 @*/ 42 PetscErrorCode PetscViewerInitializePackage(void) { 43 char logList[256]; 44 PetscBool opt, pkg; 45 46 PetscFunctionBegin; 47 if (PetscViewerPackageInitialized) PetscFunctionReturn(0); 48 PetscViewerPackageInitialized = PETSC_TRUE; 49 /* Register Classes */ 50 PetscCall(PetscClassIdRegister("Viewer", &PETSC_VIEWER_CLASSID)); 51 /* Register Constructors */ 52 PetscCall(PetscViewerRegisterAll()); 53 /* Process Info */ 54 { 55 PetscClassId classids[1]; 56 57 classids[0] = PETSC_VIEWER_CLASSID; 58 PetscCall(PetscInfoProcessClass("viewer", 1, classids)); 59 } 60 /* Process summary exclusions */ 61 PetscCall(PetscOptionsGetString(NULL, NULL, "-log_exclude", logList, sizeof(logList), &opt)); 62 if (opt) { 63 PetscCall(PetscStrInList("viewer", logList, ',', &pkg)); 64 if (pkg) PetscCall(PetscLogEventExcludeClass(PETSC_VIEWER_CLASSID)); 65 } 66 #if defined(PETSC_HAVE_MATHEMATICA) 67 PetscCall(PetscViewerMathematicaInitializePackage()); 68 #endif 69 /* Register package finalizer */ 70 PetscCall(PetscRegisterFinalize(PetscViewerFinalizePackage)); 71 PetscFunctionReturn(0); 72 } 73 74 /*@ 75 PetscViewerDestroy - Destroys a PetscViewer. 76 77 Collective on PetscViewer 78 79 Input Parameters: 80 . viewer - the PetscViewer to be destroyed. 81 82 Level: beginner 83 84 .seealso: `PetscViewerSocketOpen()`, `PetscViewerASCIIOpen()`, `PetscViewerCreate()`, `PetscViewerDrawOpen()` 85 86 @*/ 87 PetscErrorCode PetscViewerDestroy(PetscViewer *viewer) { 88 PetscFunctionBegin; 89 if (!*viewer) PetscFunctionReturn(0); 90 PetscValidHeaderSpecific(*viewer, PETSC_VIEWER_CLASSID, 1); 91 92 PetscCall(PetscViewerFlush(*viewer)); 93 if (--((PetscObject)(*viewer))->refct > 0) { 94 *viewer = NULL; 95 PetscFunctionReturn(0); 96 } 97 98 PetscCall(PetscObjectSAWsViewOff((PetscObject)*viewer)); 99 if ((*viewer)->ops->destroy) PetscCall((*(*viewer)->ops->destroy)(*viewer)); 100 PetscCall(PetscHeaderDestroy(viewer)); 101 PetscFunctionReturn(0); 102 } 103 104 /*@C 105 PetscViewerAndFormatCreate - Creates a PetscViewerAndFormat struct. 106 107 Collective on PetscViewer 108 109 Input Parameters: 110 + viewer - the viewer 111 - format - the format 112 113 Output Parameter: 114 . vf - viewer and format object 115 116 Notes: 117 This increases the reference count of the viewer so you can destroy the viewer object after this call 118 Level: developer 119 120 This is used as the context variable for many of the TS, SNES, and KSP monitor functions 121 122 .seealso: `PetscViewerSocketOpen()`, `PetscViewerASCIIOpen()`, `PetscViewerCreate()`, `PetscViewerDrawOpen()`, `PetscViewerAndFormatDestroy()` 123 124 @*/ 125 PetscErrorCode PetscViewerAndFormatCreate(PetscViewer viewer, PetscViewerFormat format, PetscViewerAndFormat **vf) { 126 PetscFunctionBegin; 127 PetscCall(PetscObjectReference((PetscObject)viewer)); 128 PetscCall(PetscNew(vf)); 129 (*vf)->viewer = viewer; 130 (*vf)->format = format; 131 (*vf)->lg = NULL; 132 (*vf)->data = NULL; 133 PetscFunctionReturn(0); 134 } 135 136 /*@C 137 PetscViewerAndFormatDestroy - Destroys a PetscViewerAndFormat struct. 138 139 Collective on PetscViewer 140 141 Input Parameters: 142 . vf - the PetscViewerAndFormat to be destroyed. 143 144 Level: developer 145 146 .seealso: `PetscViewerSocketOpen()`, `PetscViewerASCIIOpen()`, `PetscViewerCreate()`, `PetscViewerDrawOpen()`, `PetscViewerAndFormatCreate()` 147 @*/ 148 PetscErrorCode PetscViewerAndFormatDestroy(PetscViewerAndFormat **vf) { 149 PetscFunctionBegin; 150 PetscCall(PetscViewerDestroy(&(*vf)->viewer)); 151 PetscCall(PetscDrawLGDestroy(&(*vf)->lg)); 152 PetscCall(PetscFree(*vf)); 153 PetscFunctionReturn(0); 154 } 155 156 /*@C 157 PetscViewerGetType - Returns the type of a PetscViewer. 158 159 Not Collective 160 161 Input Parameter: 162 . viewer - the PetscViewer 163 164 Output Parameter: 165 . type - PetscViewer type (see below) 166 167 Available Types Include: 168 + PETSCVIEWERSOCKET - Socket PetscViewer 169 . PETSCVIEWERASCII - ASCII PetscViewer 170 . PETSCVIEWERBINARY - binary file PetscViewer 171 . PETSCVIEWERSTRING - string PetscViewer 172 - PETSCVIEWERDRAW - drawing PetscViewer 173 174 Level: intermediate 175 176 Note: 177 See include/petscviewer.h for a complete list of PetscViewers. 178 179 PetscViewerType is actually a string 180 181 .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType` 182 183 @*/ 184 PetscErrorCode PetscViewerGetType(PetscViewer viewer, PetscViewerType *type) { 185 PetscFunctionBegin; 186 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 187 PetscValidPointer(type, 2); 188 *type = ((PetscObject)viewer)->type_name; 189 PetscFunctionReturn(0); 190 } 191 192 /*@C 193 PetscViewerSetOptionsPrefix - Sets the prefix used for searching for all 194 PetscViewer options in the database. 195 196 Logically Collective on PetscViewer 197 198 Input Parameters: 199 + viewer - the PetscViewer context 200 - prefix - the prefix to prepend to all option names 201 202 Notes: 203 A hyphen (-) must NOT be given at the beginning of the prefix name. 204 The first character of all runtime options is AUTOMATICALLY the hyphen. 205 206 Level: advanced 207 208 .seealso: `PetscViewerSetFromOptions()` 209 @*/ 210 PetscErrorCode PetscViewerSetOptionsPrefix(PetscViewer viewer, const char prefix[]) { 211 PetscFunctionBegin; 212 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 213 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)viewer, prefix)); 214 PetscFunctionReturn(0); 215 } 216 217 /*@C 218 PetscViewerAppendOptionsPrefix - Appends to the prefix used for searching for all 219 PetscViewer options in the database. 220 221 Logically Collective on PetscViewer 222 223 Input Parameters: 224 + viewer - the PetscViewer context 225 - prefix - the prefix to prepend to all option names 226 227 Notes: 228 A hyphen (-) must NOT be given at the beginning of the prefix name. 229 The first character of all runtime options is AUTOMATICALLY the hyphen. 230 231 Level: advanced 232 233 .seealso: `PetscViewerGetOptionsPrefix()` 234 @*/ 235 PetscErrorCode PetscViewerAppendOptionsPrefix(PetscViewer viewer, const char prefix[]) { 236 PetscFunctionBegin; 237 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 238 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)viewer, prefix)); 239 PetscFunctionReturn(0); 240 } 241 242 /*@C 243 PetscViewerGetOptionsPrefix - Sets the prefix used for searching for all 244 PetscViewer options in the database. 245 246 Not Collective 247 248 Input Parameter: 249 . viewer - the PetscViewer context 250 251 Output Parameter: 252 . prefix - pointer to the prefix string used 253 254 Notes: 255 On the fortran side, the user should pass in a string 'prefix' of 256 sufficient length to hold the prefix. 257 258 Level: advanced 259 260 .seealso: `PetscViewerAppendOptionsPrefix()` 261 @*/ 262 PetscErrorCode PetscViewerGetOptionsPrefix(PetscViewer viewer, const char *prefix[]) { 263 PetscFunctionBegin; 264 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 265 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)viewer, prefix)); 266 PetscFunctionReturn(0); 267 } 268 269 /*@ 270 PetscViewerSetUp - Sets up the internal viewer data structures for the later use. 271 272 Collective on PetscViewer 273 274 Input Parameters: 275 . viewer - the PetscViewer context 276 277 Notes: 278 For basic use of the PetscViewer classes the user need not explicitly call 279 PetscViewerSetUp(), since these actions will happen automatically. 280 281 Level: advanced 282 283 .seealso: `PetscViewerCreate()`, `PetscViewerDestroy()` 284 @*/ 285 PetscErrorCode PetscViewerSetUp(PetscViewer viewer) { 286 PetscFunctionBegin; 287 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 288 if (viewer->setupcalled) PetscFunctionReturn(0); 289 PetscTryTypeMethod(viewer, setup); 290 viewer->setupcalled = PETSC_TRUE; 291 PetscFunctionReturn(0); 292 } 293 294 /*@C 295 PetscViewerViewFromOptions - View from Options 296 297 Collective on PetscViewer 298 299 Input Parameters: 300 + A - the PetscViewer context 301 . obj - Optional object 302 - name - command line option 303 304 Level: intermediate 305 .seealso: `PetscViewer`, `PetscViewerView`, `PetscObjectViewFromOptions()`, `PetscViewerCreate()` 306 @*/ 307 PetscErrorCode PetscViewerViewFromOptions(PetscViewer A, PetscObject obj, const char name[]) { 308 PetscFunctionBegin; 309 PetscValidHeaderSpecific(A, PETSC_VIEWER_CLASSID, 1); 310 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 311 PetscFunctionReturn(0); 312 } 313 314 /*@C 315 PetscViewerView - Visualizes a viewer object. 316 317 Collective on PetscViewer 318 319 Input Parameters: 320 + v - the viewer to be viewed 321 - viewer - visualization context 322 323 Notes: 324 The available visualization contexts include 325 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 326 . PETSC_VIEWER_STDOUT_WORLD - synchronized standard 327 output where only the first processor opens 328 the file. All other processors send their 329 data to the first processor to print. 330 - PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure 331 332 Level: beginner 333 334 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, 335 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerLoad()` 336 @*/ 337 PetscErrorCode PetscViewerView(PetscViewer v, PetscViewer viewer) { 338 PetscBool iascii; 339 PetscViewerFormat format; 340 #if defined(PETSC_HAVE_SAWS) 341 PetscBool issaws; 342 #endif 343 344 PetscFunctionBegin; 345 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1); 346 PetscValidType(v, 1); 347 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)v), &viewer)); 348 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 349 PetscCheckSameComm(v, 1, viewer, 2); 350 351 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 352 #if defined(PETSC_HAVE_SAWS) 353 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 354 #endif 355 if (iascii) { 356 PetscCall(PetscViewerGetFormat(viewer, &format)); 357 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)v, viewer)); 358 if (format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 359 if (v->format) PetscCall(PetscViewerASCIIPrintf(viewer, " Viewer format = %s\n", PetscViewerFormats[v->format])); 360 PetscCall(PetscViewerASCIIPushTab(viewer)); 361 PetscTryTypeMethod(v, view, viewer); 362 PetscCall(PetscViewerASCIIPopTab(viewer)); 363 } 364 #if defined(PETSC_HAVE_SAWS) 365 } else if (issaws) { 366 if (!((PetscObject)v)->amsmem) { 367 PetscCall(PetscObjectViewSAWs((PetscObject)v, viewer)); 368 PetscTryTypeMethod(v, view, viewer); 369 } 370 #endif 371 } 372 PetscFunctionReturn(0); 373 } 374 375 /*@C 376 PetscViewerRead - Reads data from a PetscViewer 377 378 Collective 379 380 Input Parameters: 381 + viewer - The viewer 382 . data - Location to write the data 383 . num - Number of items of data to read 384 - datatype - Type of data to read 385 386 Output Parameters: 387 . count - number of items of data actually read, or NULL 388 389 Notes: 390 If datatype is PETSC_STRING and num is negative, reads until a newline character is found, 391 until a maximum of (-num - 1) chars. 392 393 Level: beginner 394 395 .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, 396 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 397 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer` 398 @*/ 399 PetscErrorCode PetscViewerRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype) { 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 402 if (dtype == PETSC_STRING) { 403 PetscInt c, i = 0, cnt; 404 char *s = (char *)data; 405 if (num >= 0) { 406 for (c = 0; c < num; c++) { 407 /* Skip leading whitespaces */ 408 do { 409 PetscCall((*viewer->ops->read)(viewer, &(s[i]), 1, &cnt, PETSC_CHAR)); 410 if (!cnt) break; 411 } while (s[i] == '\n' || s[i] == '\t' || s[i] == ' ' || s[i] == '\0' || s[i] == '\v' || s[i] == '\f' || s[i] == '\r'); 412 i++; 413 /* Read strings one char at a time */ 414 do { 415 PetscCall((*viewer->ops->read)(viewer, &(s[i++]), 1, &cnt, PETSC_CHAR)); 416 if (!cnt) break; 417 } while (s[i - 1] != '\n' && s[i - 1] != '\t' && s[i - 1] != ' ' && s[i - 1] != '\0' && s[i - 1] != '\v' && s[i - 1] != '\f' && s[i - 1] != '\r'); 418 /* Terminate final string */ 419 if (c == num - 1) s[i - 1] = '\0'; 420 } 421 } else { 422 /* Read until a \n is encountered (-num is the max size allowed) */ 423 do { 424 PetscCall((*viewer->ops->read)(viewer, &(s[i++]), 1, &cnt, PETSC_CHAR)); 425 if (i == -num || !cnt) break; 426 } while (s[i - 1] != '\n'); 427 /* Terminate final string */ 428 s[i - 1] = '\0'; 429 c = i; 430 } 431 if (count) *count = c; 432 else PetscCheck(c >= num, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_READ, "Insufficient data, only read %" PetscInt_FMT " < %" PetscInt_FMT " strings", c, num); 433 } else PetscUseTypeMethod(viewer, read, data, num, count, dtype); 434 PetscFunctionReturn(0); 435 } 436 437 /*@ 438 PetscViewerReadable - Return a flag whether the viewer can be read from 439 440 Not Collective 441 442 Input Parameters: 443 . viewer - the PetscViewer context 444 445 Output Parameters: 446 . flg - PETSC_TRUE if the viewer is readable, PETSC_FALSE otherwise 447 448 Notes: 449 PETSC_TRUE means that viewer's PetscViewerType supports reading (this holds e.g. for PETSCVIEWERBINARY) 450 and viewer is in a mode allowing reading, i.e. PetscViewerFileGetMode() 451 returns one of FILE_MODE_READ, FILE_MODE_UPDATE, FILE_MODE_APPEND_UPDATE. 452 453 Level: intermediate 454 455 .seealso: `PetscViewerWritable()`, `PetscViewerCheckReadable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()` 456 @*/ 457 PetscErrorCode PetscViewerReadable(PetscViewer viewer, PetscBool *flg) { 458 PetscFileMode mode; 459 PetscErrorCode (*f)(PetscViewer, PetscFileMode *) = NULL; 460 461 PetscFunctionBegin; 462 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 463 PetscValidBoolPointer(flg, 2); 464 PetscCall(PetscObjectQueryFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", &f)); 465 *flg = PETSC_FALSE; 466 if (!f) PetscFunctionReturn(0); 467 PetscCall((*f)(viewer, &mode)); 468 switch (mode) { 469 case FILE_MODE_READ: 470 case FILE_MODE_UPDATE: 471 case FILE_MODE_APPEND_UPDATE: *flg = PETSC_TRUE; 472 default: break; 473 } 474 PetscFunctionReturn(0); 475 } 476 477 /*@ 478 PetscViewerWritable - Return a flag whether the viewer can be written to 479 480 Not Collective 481 482 Input Parameters: 483 . viewer - the PetscViewer context 484 485 Output Parameters: 486 . flg - PETSC_TRUE if the viewer is writable, PETSC_FALSE otherwise 487 488 Notes: 489 PETSC_TRUE means viewer is in a mode allowing writing, i.e. PetscViewerFileGetMode() 490 returns one of FILE_MODE_WRITE, FILE_MODE_APPEND, FILE_MODE_UPDATE, FILE_MODE_APPEND_UPDATE. 491 492 Level: intermediate 493 494 .seealso: `PetscViewerReadable()`, `PetscViewerCheckWritable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()` 495 @*/ 496 PetscErrorCode PetscViewerWritable(PetscViewer viewer, PetscBool *flg) { 497 PetscFileMode mode; 498 PetscErrorCode (*f)(PetscViewer, PetscFileMode *) = NULL; 499 500 PetscFunctionBegin; 501 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 502 PetscValidBoolPointer(flg, 2); 503 PetscCall(PetscObjectQueryFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", &f)); 504 *flg = PETSC_TRUE; 505 if (!f) PetscFunctionReturn(0); 506 PetscCall((*f)(viewer, &mode)); 507 if (mode == FILE_MODE_READ) *flg = PETSC_FALSE; 508 PetscFunctionReturn(0); 509 } 510 511 /*@ 512 PetscViewerCheckReadable - Check whether the viewer can be read from 513 514 Collective 515 516 Input Parameters: 517 . viewer - the PetscViewer context 518 519 Level: intermediate 520 521 .seealso: `PetscViewerReadable()`, `PetscViewerCheckWritable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()` 522 @*/ 523 PetscErrorCode PetscViewerCheckReadable(PetscViewer viewer) { 524 PetscBool flg; 525 526 PetscFunctionBegin; 527 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 528 PetscCall(PetscViewerReadable(viewer, &flg)); 529 PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Viewer doesn't support reading, or is not in reading mode (FILE_MODE_READ, FILE_MODE_UPDATE, FILE_MODE_APPEND_UPDATE)"); 530 PetscFunctionReturn(0); 531 } 532 533 /*@ 534 PetscViewerCheckWritable - Check whether the viewer can be written to 535 536 Collective 537 538 Input Parameters: 539 . viewer - the PetscViewer context 540 541 Level: intermediate 542 543 .seealso: `PetscViewerWritable()`, `PetscViewerCheckReadable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()` 544 @*/ 545 PetscErrorCode PetscViewerCheckWritable(PetscViewer viewer) { 546 PetscBool flg; 547 548 PetscFunctionBegin; 549 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 550 PetscCall(PetscViewerWritable(viewer, &flg)); 551 PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Viewer doesn't support writing, or is in FILE_MODE_READ mode"); 552 PetscFunctionReturn(0); 553 } 554