1 2 #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h> /*I "petscviewer.h" I*/ 3 4 #define QUEUESTRINGSIZE 8192 5 6 static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer) { 7 PetscMPIInt rank; 8 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 9 int err; 10 11 PetscFunctionBegin; 12 PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 13 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 14 if (rank == 0 && vascii->fd != stderr && vascii->fd != PETSC_STDOUT) { 15 if (vascii->fd && vascii->closefile) { 16 err = fclose(vascii->fd); 17 PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 18 } 19 if (vascii->storecompressed) { 20 char par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN]; 21 FILE *fp; 22 PetscCall(PetscStrncpy(par, "gzip ", sizeof(par))); 23 PetscCall(PetscStrlcat(par, vascii->filename, sizeof(par))); 24 #if defined(PETSC_HAVE_POPEN) 25 PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp)); 26 PetscCheck(!fgets(buf, 1024, fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from compression command %s\n%s", par, buf); 27 PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 28 #else 29 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 30 #endif 31 } 32 } 33 PetscCall(PetscFree(vascii->filename)); 34 PetscFunctionReturn(0); 35 } 36 37 /* ----------------------------------------------------------------------*/ 38 PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer) { 39 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 40 PetscViewerLink *vlink; 41 PetscBool flg; 42 43 PetscFunctionBegin; 44 PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 45 PetscCall(PetscViewerFileClose_ASCII(viewer)); 46 PetscCall(PetscFree(vascii)); 47 48 /* remove the viewer from the list in the MPI Communicator */ 49 if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0)); 50 51 PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg)); 52 if (flg) { 53 if (vlink && vlink->viewer == viewer) { 54 if (vlink->next) { 55 PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next)); 56 } else { 57 PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval)); 58 } 59 PetscCall(PetscFree(vlink)); 60 } else { 61 while (vlink && vlink->next) { 62 if (vlink->next->viewer == viewer) { 63 PetscViewerLink *nv = vlink->next; 64 vlink->next = vlink->next->next; 65 PetscCall(PetscFree(nv)); 66 } 67 vlink = vlink->next; 68 } 69 } 70 } 71 72 if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) { 73 PetscViewer aviewer; 74 PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, (PetscMPIInt *)&flg)); 75 if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval)); 76 } 77 if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) { 78 PetscViewer aviewer; 79 PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, (PetscMPIInt *)&flg)); 80 if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval)); 81 } 82 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL)); 83 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL)); 84 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL)); 85 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL)); 86 PetscFunctionReturn(0); 87 } 88 89 PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer) { 90 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 91 92 PetscFunctionBegin; 93 PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer)); 94 PetscFunctionReturn(0); 95 } 96 97 PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer) { 98 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 99 int err; 100 MPI_Comm comm; 101 PetscMPIInt rank, size; 102 FILE *fd = vascii->fd; 103 104 PetscFunctionBegin; 105 PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 106 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 107 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 108 PetscCallMPI(MPI_Comm_size(comm, &size)); 109 110 if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) { 111 err = fflush(vascii->fd); 112 PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() call failed"); 113 } 114 115 if (vascii->allowsynchronized) { 116 PetscMPIInt tag, i, j, n = 0, dummy = 0; 117 char *message; 118 MPI_Status status; 119 120 PetscCall(PetscCommDuplicate(comm, &comm, &tag)); 121 122 /* First processor waits for messages from all other processors */ 123 if (rank == 0) { 124 /* flush my own messages that I may have queued up */ 125 PrintfQueue next = vascii->petsc_printfqueuebase, previous; 126 for (i = 0; i < vascii->petsc_printfqueuelength; i++) { 127 if (!vascii->bviewer) { 128 PetscCall(PetscFPrintf(comm, fd, "%s", next->string)); 129 } else { 130 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string)); 131 } 132 previous = next; 133 next = next->next; 134 PetscCall(PetscFree(previous->string)); 135 PetscCall(PetscFree(previous)); 136 } 137 vascii->petsc_printfqueue = NULL; 138 vascii->petsc_printfqueuelength = 0; 139 for (i = 1; i < size; i++) { 140 /* to prevent a flood of messages to process zero, request each message separately */ 141 PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm)); 142 PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status)); 143 for (j = 0; j < n; j++) { 144 PetscMPIInt size = 0; 145 146 PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status)); 147 PetscCall(PetscMalloc1(size, &message)); 148 PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status)); 149 if (!vascii->bviewer) { 150 PetscCall(PetscFPrintf(comm, fd, "%s", message)); 151 } else { 152 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message)); 153 } 154 PetscCall(PetscFree(message)); 155 } 156 } 157 } else { /* other processors send queue to processor 0 */ 158 PrintfQueue next = vascii->petsc_printfqueuebase, previous; 159 160 PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status)); 161 PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm)); 162 for (i = 0; i < vascii->petsc_printfqueuelength; i++) { 163 PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm)); 164 PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm)); 165 previous = next; 166 next = next->next; 167 PetscCall(PetscFree(previous->string)); 168 PetscCall(PetscFree(previous)); 169 } 170 vascii->petsc_printfqueue = NULL; 171 vascii->petsc_printfqueuelength = 0; 172 } 173 PetscCall(PetscCommDestroy(&comm)); 174 } 175 PetscFunctionReturn(0); 176 } 177 178 /*@C 179 PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`. 180 181 Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer 182 183 Input Parameter: 184 . viewer - PetscViewer context, obtained from `PetscViewerASCIIOpen()` 185 186 Output Parameter: 187 . fd - file pointer 188 189 Level: intermediate 190 191 Note: 192 For the standard `PETSCVIEWERASCII` the value is valid only on process 0 of the viewer 193 194 Fortran Note: 195 This routine is not supported in Fortran. 196 197 .seealso: `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, 198 `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()` 199 @*/ 200 PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd) { 201 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 202 203 PetscFunctionBegin; 204 *fd = vascii->fd; 205 PetscFunctionReturn(0); 206 } 207 208 PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode) { 209 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 210 211 PetscFunctionBegin; 212 *mode = vascii->mode; 213 PetscFunctionReturn(0); 214 } 215 216 PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode) { 217 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 218 219 PetscFunctionBegin; 220 vascii->mode = mode; 221 PetscFunctionReturn(0); 222 } 223 224 /* 225 If petsc_history is on, then all Petsc*Printf() results are saved 226 if the appropriate (usually .petschistory) file. 227 */ 228 PETSC_INTERN FILE *petsc_history; 229 230 /*@ 231 PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times 232 233 Not Collective, but only first processor in set has any effect 234 235 Input Parameters: 236 + viewer - obtained with `PetscViewerASCIIOpen()` 237 - tabs - number of tabs 238 239 Level: developer 240 241 Fortran Note: 242 This routine is not supported in Fortran. 243 244 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIGetTab()`, 245 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 246 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()` 247 @*/ 248 PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs) { 249 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 250 PetscBool iascii; 251 252 PetscFunctionBegin; 253 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 254 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 255 if (iascii) ascii->tab = tabs; 256 PetscFunctionReturn(0); 257 } 258 259 /*@ 260 PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`. 261 262 Not Collective, meaningful on first processor only. 263 264 Input Parameters: 265 . viewer - obtained with `PetscViewerASCIIOpen()` 266 267 Output Parameters: 268 . tabs - number of tabs 269 270 Level: developer 271 272 Fortran Note: 273 This routine is not supported in Fortran. 274 275 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISetTab()`, 276 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 277 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()` 278 @*/ 279 PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs) { 280 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 281 PetscBool iascii; 282 283 PetscFunctionBegin; 284 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 285 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 286 if (iascii && tabs) *tabs = ascii->tab; 287 PetscFunctionReturn(0); 288 } 289 290 /*@ 291 PetscViewerASCIIAddTab - Add to the number of times an ASCII viewer tabs before printing 292 293 Not Collective, but only first processor in set has any effect 294 295 Input Parameters: 296 + viewer - obtained with `PetscViewerASCIIOpen()` 297 - tabs - number of tabs 298 299 Level: developer 300 301 Fortran Note: 302 This routine is not supported in Fortran. 303 304 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 305 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 306 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()` 307 @*/ 308 PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs) { 309 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 310 PetscBool iascii; 311 312 PetscFunctionBegin; 313 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 314 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 315 if (iascii) ascii->tab += tabs; 316 PetscFunctionReturn(0); 317 } 318 319 /*@ 320 PetscViewerASCIISubtractTab - Subtracts from the number of times an ASCII viewer tabs before printing 321 322 Not Collective, but only first processor in set has any effect 323 324 Input Parameters: 325 + viewer - obtained with `PetscViewerASCIIOpen()` 326 - tabs - number of tabs 327 328 Level: developer 329 330 Fortran Note: 331 This routine is not supported in Fortran. 332 333 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 334 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 335 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()` 336 @*/ 337 PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs) { 338 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 339 PetscBool iascii; 340 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 343 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 344 if (iascii) ascii->tab -= tabs; 345 PetscFunctionReturn(0); 346 } 347 348 /*@C 349 PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer 350 351 Collective on viewer 352 353 Input Parameters: 354 . viewer - obtained with `PetscViewerASCIIOpen()` 355 356 Level: intermediate 357 358 Note: 359 See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly. 360 361 .seealso: `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 362 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 363 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 364 @*/ 365 PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer) { 366 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 367 PetscBool iascii; 368 369 PetscFunctionBegin; 370 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 371 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 372 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 373 if (iascii) ascii->allowsynchronized++; 374 PetscFunctionReturn(0); 375 } 376 377 /*@C 378 PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer 379 380 Collective on viewer 381 382 Input Parameters: 383 . viewer - obtained with `PetscViewerASCIIOpen()` 384 385 Level: intermediate 386 387 Note: 388 See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly. 389 390 .seealso: `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, 391 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 392 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 393 @*/ 394 PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer) { 395 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 396 PetscBool iascii; 397 398 PetscFunctionBegin; 399 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 400 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 401 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 402 if (iascii) { 403 ascii->allowsynchronized--; 404 PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()"); 405 } 406 PetscFunctionReturn(0); 407 } 408 409 /*@C 410 PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()` 411 lines are tabbed. 412 413 Not Collective, but only first processor in set has any effect 414 415 Input Parameters: 416 . viewer - obtained with `PetscViewerASCIIOpen()` 417 418 Level: developer 419 420 Fortran Note: 421 This routine is not supported in Fortran. 422 423 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 424 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 425 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()` 426 @*/ 427 PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer) { 428 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 429 PetscBool iascii; 430 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 433 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 434 if (iascii) ascii->tab++; 435 PetscFunctionReturn(0); 436 } 437 438 /*@C 439 PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by `PetscViewerASCIIPushTab()` 440 441 Not Collective, but only first processor in set has any effect 442 443 Input Parameters: 444 . viewer - obtained with `PetscViewerASCIIOpen()` 445 446 Level: developer 447 448 Fortran Note: 449 This routine is not supported in Fortran. 450 451 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 452 `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 453 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()` 454 @*/ 455 PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer) { 456 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 457 PetscBool iascii; 458 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 461 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 462 if (iascii) { 463 PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed"); 464 ascii->tab--; 465 } 466 PetscFunctionReturn(0); 467 } 468 469 /*@ 470 PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the ASCII `PetscViewer` 471 472 Not Collective, but only first processor in set has any effect 473 474 Input Parameters: 475 + viewer - obtained with `PetscViewerASCIIOpen()` 476 - flg - `PETSC_TRUE` or `PETSC_FALSE` 477 478 Level: developer 479 480 Fortran Note: 481 This routine is not supported in Fortran. 482 483 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 484 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`, 485 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()` 486 @*/ 487 PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg) { 488 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 489 PetscBool iascii; 490 491 PetscFunctionBegin; 492 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 493 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 494 if (iascii) { 495 if (flg) ascii->tab = ascii->tab_store; 496 else { 497 ascii->tab_store = ascii->tab; 498 ascii->tab = 0; 499 } 500 } 501 PetscFunctionReturn(0); 502 } 503 504 /* ----------------------------------------------------------------------- */ 505 506 /*@C 507 PetscViewerASCIIPrintf - Prints to a file, only from the first 508 processor in the PetscViewer 509 510 Not Collective, but only first processor in set has any effect 511 512 Input Parameters: 513 + viewer - obtained with `PetscViewerASCIIOpen()` 514 - format - the usual printf() format string 515 516 Level: developer 517 518 Fortran Note: 519 The call sequence is `PetscViewerASCIIPrintf`(PetscViewer, character(*), int ierr) from Fortran. 520 That is, you can only pass a single character string from Fortran. 521 522 .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 523 `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, 524 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()` 525 @*/ 526 PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...) { 527 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 528 PetscMPIInt rank; 529 PetscInt tab, intab = ascii->tab; 530 FILE *fd = ascii->fd; 531 PetscBool iascii; 532 int err; 533 534 PetscFunctionBegin; 535 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 536 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 537 PetscValidCharPointer(format, 2); 538 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 539 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 540 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 541 if (rank) PetscFunctionReturn(0); 542 543 if (ascii->bviewer) { /* pass string up to parent viewer */ 544 char *string; 545 va_list Argp; 546 size_t fullLength; 547 548 PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string)); 549 va_start(Argp, format); 550 PetscCall(PetscVSNPrintf(string, QUEUESTRINGSIZE, format, &fullLength, Argp)); 551 va_end(Argp); 552 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%s", string)); 553 PetscCall(PetscFree(string)); 554 } else { /* write directly to file */ 555 va_list Argp; 556 /* flush my own messages that I may have queued up */ 557 PrintfQueue next = ascii->petsc_printfqueuebase, previous; 558 PetscInt i; 559 for (i = 0; i < ascii->petsc_printfqueuelength; i++) { 560 PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "%s", next->string)); 561 previous = next; 562 next = next->next; 563 PetscCall(PetscFree(previous->string)); 564 PetscCall(PetscFree(previous)); 565 } 566 ascii->petsc_printfqueue = NULL; 567 ascii->petsc_printfqueuelength = 0; 568 tab = intab; 569 while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, " ")); 570 571 va_start(Argp, format); 572 PetscCall((*PetscVFPrintf)(fd, format, Argp)); 573 err = fflush(fd); 574 PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file"); 575 if (petsc_history) { 576 va_start(Argp, format); 577 tab = intab; 578 while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, petsc_history, " ")); 579 PetscCall((*PetscVFPrintf)(petsc_history, format, Argp)); 580 err = fflush(petsc_history); 581 PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file"); 582 } 583 va_end(Argp); 584 } 585 PetscFunctionReturn(0); 586 } 587 588 /*@C 589 PetscViewerFileSetName - Sets the name of the file the `PetscViewer` uses. 590 591 Collective on viewer 592 593 Input Parameters: 594 + viewer - the PetscViewer; either `PETSCVIEWERASCII` or `PETSCVIEWERBINARY` 595 - name - the name of the file it should use 596 597 Level: advanced 598 599 .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`, 600 `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()` 601 @*/ 602 PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[]) { 603 char filename[PETSC_MAX_PATH_LEN]; 604 605 PetscFunctionBegin; 606 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 607 PetscValidCharPointer(name, 2); 608 PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename))); 609 PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename)); 610 PetscFunctionReturn(0); 611 } 612 613 /*@C 614 PetscViewerFileGetName - Gets the name of the file the `PetscViewer` uses. 615 616 Not Collective 617 618 Input Parameter: 619 . viewer - the `PetscViewer`; either `PETSCVIEWERASCII` or `PETSCVIEWERBINARY` 620 621 Output Parameter: 622 . name - the name of the file it is using 623 624 Level: advanced 625 626 .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()` 627 @*/ 628 PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name) { 629 PetscFunctionBegin; 630 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 631 PetscValidPointer(name, 2); 632 PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name)); 633 PetscFunctionReturn(0); 634 } 635 636 PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name) { 637 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 638 639 PetscFunctionBegin; 640 *name = vascii->filename; 641 PetscFunctionReturn(0); 642 } 643 644 PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[]) { 645 size_t len; 646 char fname[PETSC_MAX_PATH_LEN], *gz; 647 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 648 PetscBool isstderr, isstdout; 649 PetscMPIInt rank; 650 651 PetscFunctionBegin; 652 PetscCall(PetscViewerFileClose_ASCII(viewer)); 653 if (!name) PetscFunctionReturn(0); 654 PetscCall(PetscStrallocpy(name, &vascii->filename)); 655 656 /* Is this file to be compressed */ 657 vascii->storecompressed = PETSC_FALSE; 658 659 PetscCall(PetscStrstr(vascii->filename, ".gz", &gz)); 660 if (gz) { 661 PetscCall(PetscStrlen(gz, &len)); 662 if (len == 3) { 663 PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first"); 664 *gz = 0; 665 vascii->storecompressed = PETSC_TRUE; 666 } 667 } 668 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 669 if (rank == 0) { 670 PetscCall(PetscStrcmp(name, "stderr", &isstderr)); 671 PetscCall(PetscStrcmp(name, "stdout", &isstdout)); 672 /* empty filename means stdout */ 673 if (name[0] == 0) isstdout = PETSC_TRUE; 674 if (isstderr) vascii->fd = PETSC_STDERR; 675 else if (isstdout) vascii->fd = PETSC_STDOUT; 676 else { 677 PetscCall(PetscFixFilename(name, fname)); 678 switch (vascii->mode) { 679 case FILE_MODE_READ: vascii->fd = fopen(fname, "r"); break; 680 case FILE_MODE_WRITE: vascii->fd = fopen(fname, "w"); break; 681 case FILE_MODE_APPEND: vascii->fd = fopen(fname, "a"); break; 682 case FILE_MODE_UPDATE: 683 vascii->fd = fopen(fname, "r+"); 684 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 685 break; 686 case FILE_MODE_APPEND_UPDATE: 687 /* I really want a file which is opened at the end for updating, 688 not a+, which opens at the beginning, but makes writes at the end. 689 */ 690 vascii->fd = fopen(fname, "r+"); 691 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 692 else PetscCall(fseek(vascii->fd, 0, SEEK_END)); 693 break; 694 default: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]); 695 } 696 PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname); 697 } 698 } 699 #if defined(PETSC_USE_LOG) 700 PetscLogObjectState((PetscObject)viewer, "File: %s", name); 701 #endif 702 PetscFunctionReturn(0); 703 } 704 705 PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer) { 706 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii; 707 708 PetscFunctionBegin; 709 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 710 PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored"); 711 /* 712 The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work 713 because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed 714 (since the count never gets to zero) in some examples this displays information that otherwise would be lost 715 716 This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example, 717 PCView_GASM(). 718 */ 719 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 720 PetscCall(PetscViewerCreate(subcomm, outviewer)); 721 PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII)); 722 PetscCall(PetscViewerASCIIPushSynchronized(*outviewer)); 723 ovascii = (PetscViewer_ASCII *)(*outviewer)->data; 724 ovascii->fd = vascii->fd; 725 ovascii->tab = vascii->tab; 726 ovascii->closefile = PETSC_FALSE; 727 728 vascii->sviewer = *outviewer; 729 (*outviewer)->format = viewer->format; 730 ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer; 731 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer; 732 PetscFunctionReturn(0); 733 } 734 735 PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer) { 736 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 737 738 PetscFunctionBegin; 739 PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer"); 740 PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer"); 741 742 PetscCall(PetscViewerASCIIPopSynchronized(*outviewer)); 743 ascii->sviewer = NULL; 744 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII; 745 PetscCall(PetscViewerDestroy(outviewer)); 746 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 747 PetscFunctionReturn(0); 748 } 749 750 PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer) { 751 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data; 752 753 PetscFunctionBegin; 754 if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename)); 755 PetscFunctionReturn(0); 756 } 757 758 /*MC 759 PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file 760 761 Level: beginner 762 763 .seealso: `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, 764 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, 765 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 766 M*/ 767 PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer) { 768 PetscViewer_ASCII *vascii; 769 770 PetscFunctionBegin; 771 PetscCall(PetscNewLog(viewer, &vascii)); 772 viewer->data = (void *)vascii; 773 774 viewer->ops->destroy = PetscViewerDestroy_ASCII; 775 viewer->ops->flush = PetscViewerFlush_ASCII; 776 viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII; 777 viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII; 778 viewer->ops->view = PetscViewerView_ASCII; 779 viewer->ops->read = PetscViewerASCIIRead; 780 781 /* defaults to stdout unless set with PetscViewerFileSetName() */ 782 vascii->fd = PETSC_STDOUT; 783 vascii->mode = FILE_MODE_WRITE; 784 vascii->bviewer = NULL; 785 vascii->subviewer = NULL; 786 vascii->sviewer = NULL; 787 vascii->tab = 0; 788 vascii->tab_store = 0; 789 vascii->filename = NULL; 790 vascii->closefile = PETSC_TRUE; 791 792 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII)); 793 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII)); 794 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII)); 795 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII)); 796 PetscFunctionReturn(0); 797 } 798 799 /*@C 800 PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified file from 801 several processors. Output of the first processor is followed by that of the 802 second, etc. 803 804 Not Collective, must call collective `PetscViewerFlush()` to get the results out 805 806 Input Parameters: 807 + viewer - the `PETSCVIEWERASCII` `PetscViewer` 808 - format - the usual printf() format string 809 810 Level: intermediate 811 812 Notes: 813 You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called. 814 Then you can do multiple independent calls to this routine. 815 816 The actual synchronized print is then done using `PetscViewerFlush()`. 817 `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output 818 to conclude the "synchronized session". 819 820 So the typical calling sequence looks like 821 .vb 822 PetscViewerASCIIPushSynchronized(viewer); 823 PetscViewerASCIISynchronizedPrintf(viewer, ...); 824 PetscViewerASCIISynchronizedPrintf(viewer, ...); 825 ... 826 PetscViewerFlush(viewer); 827 PetscViewerASCIISynchronizedPrintf(viewer, ...); 828 PetscViewerASCIISynchronizedPrintf(viewer, ...); 829 ... 830 PetscViewerFlush(viewer); 831 PetscViewerASCIIPopSynchronized(viewer); 832 .ve 833 834 Fortran Note: 835 Can only print a single character* string 836 837 .seealso: `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 838 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 839 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 840 @*/ 841 PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...) { 842 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 843 PetscMPIInt rank; 844 PetscInt tab = vascii->tab; 845 MPI_Comm comm; 846 FILE *fp; 847 PetscBool iascii, hasbviewer = PETSC_FALSE; 848 int err; 849 850 PetscFunctionBegin; 851 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 852 PetscValidCharPointer(format, 2); 853 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 854 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 855 PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call"); 856 857 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 858 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 859 860 if (vascii->bviewer) { 861 hasbviewer = PETSC_TRUE; 862 if (rank == 0) { 863 vascii = (PetscViewer_ASCII *)vascii->bviewer->data; 864 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 865 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 866 } 867 } 868 869 fp = vascii->fd; 870 871 if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */ 872 va_list Argp; 873 /* flush my own messages that I may have queued up */ 874 PrintfQueue next = vascii->petsc_printfqueuebase, previous; 875 PetscInt i; 876 for (i = 0; i < vascii->petsc_printfqueuelength; i++) { 877 PetscCall(PetscFPrintf(comm, fp, "%s", next->string)); 878 previous = next; 879 next = next->next; 880 PetscCall(PetscFree(previous->string)); 881 PetscCall(PetscFree(previous)); 882 } 883 vascii->petsc_printfqueue = NULL; 884 vascii->petsc_printfqueuelength = 0; 885 886 while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " ")); 887 888 va_start(Argp, format); 889 PetscCall((*PetscVFPrintf)(fp, format, Argp)); 890 err = fflush(fp); 891 PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file"); 892 if (petsc_history) { 893 va_start(Argp, format); 894 PetscCall((*PetscVFPrintf)(petsc_history, format, Argp)); 895 err = fflush(petsc_history); 896 PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file"); 897 } 898 va_end(Argp); 899 } else { /* other processors add to queue */ 900 char *string; 901 va_list Argp; 902 size_t fullLength; 903 PrintfQueue next; 904 905 PetscCall(PetscNew(&next)); 906 if (vascii->petsc_printfqueue) { 907 vascii->petsc_printfqueue->next = next; 908 vascii->petsc_printfqueue = next; 909 } else { 910 vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next; 911 } 912 vascii->petsc_printfqueuelength++; 913 next->size = QUEUESTRINGSIZE; 914 PetscCall(PetscCalloc1(next->size, &next->string)); 915 string = next->string; 916 tab *= 2; 917 while (tab--) *string++ = ' '; 918 va_start(Argp, format); 919 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp)); 920 va_end(Argp); 921 if (fullLength > (size_t)(next->size - 2 * vascii->tab)) { 922 PetscCall(PetscFree(next->string)); 923 next->size = fullLength + 2 * vascii->tab; 924 PetscCall(PetscCalloc1(next->size, &next->string)); 925 string = next->string; 926 tab = 2 * vascii->tab; 927 while (tab--) *string++ = ' '; 928 va_start(Argp, format); 929 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp)); 930 va_end(Argp); 931 } 932 } 933 PetscFunctionReturn(0); 934 } 935 936 /*@C 937 PetscViewerASCIIRead - Reads from a ASCII file 938 939 Only process 0 in the `PetscViewer` may call this 940 941 Input Parameters: 942 + viewer - the ascii viewer 943 . data - location to write the data 944 . num - number of items of data to read 945 - datatype - type of data to read 946 947 Output Parameters: 948 . count - number of items of data actually read, or NULL 949 950 Level: beginner 951 952 .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()` 953 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 954 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 955 @*/ 956 PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype) { 957 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 958 FILE *fd = vascii->fd; 959 PetscInt i; 960 int ret = 0; 961 PetscMPIInt rank; 962 963 PetscFunctionBegin; 964 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 965 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 966 PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer"); 967 for (i = 0; i < num; i++) { 968 if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i])); 969 else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i])); 970 else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i])); 971 else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i])); 972 else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i])); 973 else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i])); 974 else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i])); 975 else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i])); 976 #if defined(PETSC_USE_REAL___FLOAT128) 977 else if (dtype == PETSC___FLOAT128) { 978 double tmp; 979 ret = fscanf(fd, "%lg", &tmp); 980 ((__float128 *)data)[i] = tmp; 981 } 982 #endif 983 else 984 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype); 985 PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype); 986 if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */ 987 } 988 if (count) *count = i; 989 else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num); 990 PetscFunctionReturn(0); 991 } 992