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