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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 98 } 99 100 PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer) 101 { 102 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 103 MPI_Comm comm; 104 PetscMPIInt rank, size; 105 FILE *fd = vascii->fd; 106 107 PetscFunctionBegin; 108 PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 109 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 110 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 111 PetscCallMPI(MPI_Comm_size(comm, &size)); 112 113 if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd)); 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(PETSC_SUCCESS); 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; No Fortran Support 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 MPI rank 0 of the viewer 193 194 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, 195 `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()` 196 @*/ 197 PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd) 198 { 199 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 200 201 PetscFunctionBegin; 202 *fd = vascii->fd; 203 PetscFunctionReturn(PETSC_SUCCESS); 204 } 205 206 PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode) 207 { 208 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 209 210 PetscFunctionBegin; 211 *mode = vascii->mode; 212 PetscFunctionReturn(PETSC_SUCCESS); 213 } 214 215 PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode) 216 { 217 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 218 219 PetscFunctionBegin; 220 vascii->mode = mode; 221 PetscFunctionReturn(PETSC_SUCCESS); 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 before printing 232 233 Not Collective, but only first processor in set has any effect; No Fortran Support 234 235 Input Parameters: 236 + viewer - obtained with `PetscViewerASCIIOpen()` 237 - tabs - number of tabs 238 239 Level: developer 240 241 Note: 242 `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage 243 244 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 245 `PetscViewerASCIIGetTab()`, 246 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 247 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, 248 `PetscViewerASCIIPushTab()` 249 @*/ 250 PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs) 251 { 252 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 253 PetscBool iascii; 254 255 PetscFunctionBegin; 256 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 257 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 258 if (iascii) ascii->tab = tabs; 259 PetscFunctionReturn(PETSC_SUCCESS); 260 } 261 262 /*@ 263 PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`. 264 265 Not Collective, meaningful on first processor only; No Fortran Support 266 267 Input Parameter: 268 . viewer - obtained with `PetscViewerASCIIOpen()` 269 270 Output Parameter: 271 . tabs - number of tabs 272 273 Level: developer 274 275 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 276 `PetscViewerASCIISetTab()`, 277 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 278 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()` 279 @*/ 280 PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs) 281 { 282 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 283 PetscBool iascii; 284 285 PetscFunctionBegin; 286 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 287 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 288 if (iascii && tabs) *tabs = ascii->tab; 289 PetscFunctionReturn(PETSC_SUCCESS); 290 } 291 292 /*@ 293 PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing 294 295 Not Collective, but only first processor in set has any effect; No Fortran Support 296 297 Input Parameters: 298 + viewer - obtained with `PetscViewerASCIIOpen()` 299 - tabs - number of tabs 300 301 Level: developer 302 303 Note: 304 `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage 305 306 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 307 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 308 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()` 309 @*/ 310 PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs) 311 { 312 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 313 PetscBool iascii; 314 315 PetscFunctionBegin; 316 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 317 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 318 if (iascii) ascii->tab += tabs; 319 PetscFunctionReturn(PETSC_SUCCESS); 320 } 321 322 /*@ 323 PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing 324 325 Not Collective, but only first processor in set has any effect; No Fortran Support 326 327 Input Parameters: 328 + viewer - obtained with `PetscViewerASCIIOpen()` 329 - tabs - number of tabs 330 331 Level: developer 332 333 Note: 334 `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage 335 336 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 337 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 338 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, 339 `PetscViewerASCIIPushTab()` 340 @*/ 341 PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs) 342 { 343 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 344 PetscBool iascii; 345 346 PetscFunctionBegin; 347 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 348 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 349 if (iascii) ascii->tab -= tabs; 350 PetscFunctionReturn(PETSC_SUCCESS); 351 } 352 353 /*@C 354 PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer 355 356 Collective 357 358 Input Parameter: 359 . viewer - obtained with `PetscViewerASCIIOpen()` 360 361 Level: intermediate 362 363 Note: 364 See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly. 365 366 .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 367 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 368 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 369 @*/ 370 PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer) 371 { 372 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 373 PetscBool iascii; 374 375 PetscFunctionBegin; 376 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 377 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 378 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 379 if (iascii) ascii->allowsynchronized++; 380 PetscFunctionReturn(PETSC_SUCCESS); 381 } 382 383 /*@C 384 PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer 385 386 Collective 387 388 Input Parameter: 389 . viewer - obtained with `PetscViewerASCIIOpen()` 390 391 Level: intermediate 392 393 Note: 394 See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly. 395 396 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, 397 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 398 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 399 @*/ 400 PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer) 401 { 402 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 403 PetscBool iascii; 404 405 PetscFunctionBegin; 406 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 407 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 408 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 409 if (iascii) { 410 ascii->allowsynchronized--; 411 PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()"); 412 } 413 PetscFunctionReturn(PETSC_SUCCESS); 414 } 415 416 /*@C 417 PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()` 418 lines are tabbed. 419 420 Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support 421 422 Input Parameter: 423 . viewer - obtained with `PetscViewerASCIIOpen()` 424 425 Level: developer 426 427 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 428 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 429 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()` 430 @*/ 431 PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer) 432 { 433 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 434 PetscBool iascii; 435 436 PetscFunctionBegin; 437 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 438 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 439 if (iascii) ascii->tab++; 440 PetscFunctionReturn(PETSC_SUCCESS); 441 } 442 443 /*@C 444 PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by 445 `PetscViewerASCIIPushTab()` 446 447 Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support 448 449 Input Parameter: 450 . viewer - obtained with `PetscViewerASCIIOpen()` 451 452 Level: developer 453 454 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 455 `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 456 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()` 457 @*/ 458 PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer) 459 { 460 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 461 PetscBool iascii; 462 463 PetscFunctionBegin; 464 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 465 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 466 if (iascii) { 467 PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed"); 468 ascii->tab--; 469 } 470 PetscFunctionReturn(PETSC_SUCCESS); 471 } 472 473 /*@ 474 PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer` 475 476 Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support 477 478 Input Parameters: 479 + viewer - obtained with `PetscViewerASCIIOpen()` 480 - flg - `PETSC_TRUE` or `PETSC_FALSE` 481 482 Level: developer 483 484 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 485 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`, 486 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()` 487 @*/ 488 PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg) 489 { 490 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 491 PetscBool iascii; 492 493 PetscFunctionBegin; 494 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 495 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 496 if (iascii) { 497 if (flg) ascii->tab = ascii->tab_store; 498 else { 499 ascii->tab_store = ascii->tab; 500 ascii->tab = 0; 501 } 502 } 503 PetscFunctionReturn(PETSC_SUCCESS); 504 } 505 506 /*@C 507 PetscViewerASCIIPrintf - Prints to a file, only from the first 508 processor in the `PetscViewer` of type `PETSCVIEWERASCII` 509 510 Not Collective, but only the first MPI rank in the viewer 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: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 523 `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, 524 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()` 525 @*/ 526 PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...) 527 { 528 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 529 PetscMPIInt rank; 530 PetscInt tab, intab = ascii->tab; 531 FILE *fd = ascii->fd; 532 PetscBool iascii; 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(PETSC_SUCCESS); 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 va_end(Argp); 574 PetscCall(PetscFFlush(fd)); 575 if (petsc_history) { 576 tab = intab; 577 while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, petsc_history, " ")); 578 va_start(Argp, format); 579 PetscCall((*PetscVFPrintf)(petsc_history, format, Argp)); 580 va_end(Argp); 581 PetscCall(PetscFFlush(petsc_history)); 582 } 583 } 584 PetscFunctionReturn(PETSC_SUCCESS); 585 } 586 587 /*@C 588 PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use. 589 590 Collective 591 592 Input Parameters: 593 + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY` 594 - name - the name of the file it should use 595 596 Level: advanced 597 598 Note: 599 This will have no effect on viewers that are not related to files 600 601 .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`, 602 `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()` 603 @*/ 604 PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[]) 605 { 606 char filename[PETSC_MAX_PATH_LEN]; 607 608 PetscFunctionBegin; 609 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 610 PetscValidCharPointer(name, 2); 611 PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename))); 612 PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename)); 613 PetscFunctionReturn(PETSC_SUCCESS); 614 } 615 616 /*@C 617 PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using 618 619 Not Collective 620 621 Input Parameter: 622 . viewer - the `PetscViewer` 623 624 Output Parameter: 625 . name - the name of the file it is using 626 627 Level: advanced 628 629 Note: 630 This will have no effect on viewers that are not related to files 631 632 .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()` 633 @*/ 634 PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name) 635 { 636 PetscFunctionBegin; 637 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 638 PetscValidPointer(name, 2); 639 PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name)); 640 PetscFunctionReturn(PETSC_SUCCESS); 641 } 642 643 PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name) 644 { 645 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 646 647 PetscFunctionBegin; 648 *name = vascii->filename; 649 PetscFunctionReturn(PETSC_SUCCESS); 650 } 651 652 PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[]) 653 { 654 size_t len; 655 char fname[PETSC_MAX_PATH_LEN], *gz = NULL; 656 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 657 PetscBool isstderr, isstdout; 658 PetscMPIInt rank; 659 660 PetscFunctionBegin; 661 PetscCall(PetscViewerFileClose_ASCII(viewer)); 662 if (!name) PetscFunctionReturn(PETSC_SUCCESS); 663 PetscCall(PetscStrallocpy(name, &vascii->filename)); 664 665 /* Is this file to be compressed */ 666 vascii->storecompressed = PETSC_FALSE; 667 668 PetscCall(PetscStrstr(vascii->filename, ".gz", &gz)); 669 if (gz) { 670 PetscCall(PetscStrlen(gz, &len)); 671 if (len == 3) { 672 PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first"); 673 *gz = 0; 674 vascii->storecompressed = PETSC_TRUE; 675 } 676 } 677 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 678 if (rank == 0) { 679 PetscCall(PetscStrcmp(name, "stderr", &isstderr)); 680 PetscCall(PetscStrcmp(name, "stdout", &isstdout)); 681 /* empty filename means stdout */ 682 if (name[0] == 0) isstdout = PETSC_TRUE; 683 if (isstderr) vascii->fd = PETSC_STDERR; 684 else if (isstdout) vascii->fd = PETSC_STDOUT; 685 else { 686 PetscCall(PetscFixFilename(name, fname)); 687 switch (vascii->mode) { 688 case FILE_MODE_READ: 689 vascii->fd = fopen(fname, "r"); 690 break; 691 case FILE_MODE_WRITE: 692 vascii->fd = fopen(fname, "w"); 693 break; 694 case FILE_MODE_APPEND: 695 vascii->fd = fopen(fname, "a"); 696 break; 697 case FILE_MODE_UPDATE: 698 vascii->fd = fopen(fname, "r+"); 699 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 700 break; 701 case FILE_MODE_APPEND_UPDATE: 702 /* I really want a file which is opened at the end for updating, 703 not a+, which opens at the beginning, but makes writes at the end. 704 */ 705 vascii->fd = fopen(fname, "r+"); 706 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 707 else { 708 int ret = fseek(vascii->fd, 0, SEEK_END); 709 PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret); 710 } 711 break; 712 default: 713 SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]); 714 } 715 PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname); 716 } 717 } 718 #if defined(PETSC_USE_LOG) 719 PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name)); 720 #endif 721 PetscFunctionReturn(PETSC_SUCCESS); 722 } 723 724 PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer) 725 { 726 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii; 727 728 PetscFunctionBegin; 729 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 730 PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored"); 731 /* 732 The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work 733 because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed 734 (since the count never gets to zero) in some examples this displays information that otherwise would be lost 735 736 This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example, 737 PCView_GASM(). 738 */ 739 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 740 PetscCall(PetscViewerCreate(subcomm, outviewer)); 741 PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII)); 742 PetscCall(PetscViewerASCIIPushSynchronized(*outviewer)); 743 ovascii = (PetscViewer_ASCII *)(*outviewer)->data; 744 ovascii->fd = vascii->fd; 745 ovascii->tab = vascii->tab; 746 ovascii->closefile = PETSC_FALSE; 747 748 vascii->sviewer = *outviewer; 749 (*outviewer)->format = viewer->format; 750 ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer; 751 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer; 752 PetscFunctionReturn(PETSC_SUCCESS); 753 } 754 755 PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer) 756 { 757 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 758 759 PetscFunctionBegin; 760 PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer"); 761 PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer"); 762 763 PetscCall(PetscViewerASCIIPopSynchronized(*outviewer)); 764 ascii->sviewer = NULL; 765 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII; 766 PetscCall(PetscViewerDestroy(outviewer)); 767 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 768 PetscFunctionReturn(PETSC_SUCCESS); 769 } 770 771 PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer) 772 { 773 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data; 774 775 PetscFunctionBegin; 776 if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename)); 777 PetscFunctionReturn(PETSC_SUCCESS); 778 } 779 780 /*MC 781 PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file 782 783 Level: beginner 784 785 .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, 786 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, 787 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 788 M*/ 789 PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer) 790 { 791 PetscViewer_ASCII *vascii; 792 793 PetscFunctionBegin; 794 PetscCall(PetscNew(&vascii)); 795 viewer->data = (void *)vascii; 796 797 viewer->ops->destroy = PetscViewerDestroy_ASCII; 798 viewer->ops->flush = PetscViewerFlush_ASCII; 799 viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII; 800 viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII; 801 viewer->ops->view = PetscViewerView_ASCII; 802 viewer->ops->read = PetscViewerASCIIRead; 803 804 /* defaults to stdout unless set with PetscViewerFileSetName() */ 805 vascii->fd = PETSC_STDOUT; 806 vascii->mode = FILE_MODE_WRITE; 807 vascii->bviewer = NULL; 808 vascii->subviewer = NULL; 809 vascii->sviewer = NULL; 810 vascii->tab = 0; 811 vascii->tab_store = 0; 812 vascii->filename = NULL; 813 vascii->closefile = PETSC_TRUE; 814 815 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII)); 816 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII)); 817 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII)); 818 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII)); 819 PetscFunctionReturn(PETSC_SUCCESS); 820 } 821 822 /*@C 823 PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from 824 several processors. Output of the first processor is followed by that of the 825 second, etc. 826 827 Not Collective, must call collective `PetscViewerFlush()` to get the results flushed 828 829 Input Parameters: 830 + viewer - the `PETSCVIEWERASCII` `PetscViewer` 831 - format - the usual printf() format string 832 833 Level: intermediate 834 835 Notes: 836 You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called. 837 Then you can do multiple independent calls to this routine. 838 839 The actual synchronized print is then done using `PetscViewerFlush()`. 840 `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output 841 to conclude the "synchronized session". 842 843 So the typical calling sequence looks like 844 .vb 845 PetscViewerASCIIPushSynchronized(viewer); 846 PetscViewerASCIISynchronizedPrintf(viewer, ...); 847 PetscViewerASCIISynchronizedPrintf(viewer, ...); 848 ... 849 PetscViewerFlush(viewer); 850 PetscViewerASCIISynchronizedPrintf(viewer, ...); 851 PetscViewerASCIISynchronizedPrintf(viewer, ...); 852 ... 853 PetscViewerFlush(viewer); 854 PetscViewerASCIIPopSynchronized(viewer); 855 .ve 856 857 Fortran Note: 858 Can only print a single character* string 859 860 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 861 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 862 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 863 @*/ 864 PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...) 865 { 866 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 867 PetscMPIInt rank; 868 PetscInt tab = vascii->tab; 869 MPI_Comm comm; 870 FILE *fp; 871 PetscBool iascii, hasbviewer = PETSC_FALSE; 872 873 PetscFunctionBegin; 874 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 875 PetscValidCharPointer(format, 2); 876 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 877 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 878 PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call"); 879 880 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 881 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 882 883 if (vascii->bviewer) { 884 hasbviewer = PETSC_TRUE; 885 if (rank == 0) { 886 vascii = (PetscViewer_ASCII *)vascii->bviewer->data; 887 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 888 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 889 } 890 } 891 892 fp = vascii->fd; 893 894 if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */ 895 va_list Argp; 896 /* flush my own messages that I may have queued up */ 897 PrintfQueue next = vascii->petsc_printfqueuebase, previous; 898 PetscInt i; 899 for (i = 0; i < vascii->petsc_printfqueuelength; i++) { 900 PetscCall(PetscFPrintf(comm, fp, "%s", next->string)); 901 previous = next; 902 next = next->next; 903 PetscCall(PetscFree(previous->string)); 904 PetscCall(PetscFree(previous)); 905 } 906 vascii->petsc_printfqueue = NULL; 907 vascii->petsc_printfqueuelength = 0; 908 909 while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " ")); 910 911 va_start(Argp, format); 912 PetscCall((*PetscVFPrintf)(fp, format, Argp)); 913 va_end(Argp); 914 PetscCall(PetscFFlush(fp)); 915 if (petsc_history) { 916 va_start(Argp, format); 917 PetscCall((*PetscVFPrintf)(petsc_history, format, Argp)); 918 va_end(Argp); 919 PetscCall(PetscFFlush(petsc_history)); 920 } 921 va_end(Argp); 922 } else { /* other processors add to queue */ 923 char *string; 924 va_list Argp; 925 size_t fullLength; 926 PrintfQueue next; 927 928 PetscCall(PetscNew(&next)); 929 if (vascii->petsc_printfqueue) { 930 vascii->petsc_printfqueue->next = next; 931 vascii->petsc_printfqueue = next; 932 } else { 933 vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next; 934 } 935 vascii->petsc_printfqueuelength++; 936 next->size = QUEUESTRINGSIZE; 937 PetscCall(PetscCalloc1(next->size, &next->string)); 938 string = next->string; 939 tab *= 2; 940 while (tab--) *string++ = ' '; 941 va_start(Argp, format); 942 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp)); 943 va_end(Argp); 944 if (fullLength > (size_t)(next->size - 2 * vascii->tab)) { 945 PetscCall(PetscFree(next->string)); 946 next->size = fullLength + 2 * vascii->tab; 947 PetscCall(PetscCalloc1(next->size, &next->string)); 948 string = next->string; 949 tab = 2 * vascii->tab; 950 while (tab--) *string++ = ' '; 951 va_start(Argp, format); 952 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp)); 953 va_end(Argp); 954 } 955 } 956 PetscFunctionReturn(PETSC_SUCCESS); 957 } 958 959 /*@C 960 PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file 961 962 Only MPI rank 0 in the `PetscViewer` may call this 963 964 Input Parameters: 965 + viewer - the `PETSCVIEWERASCII` viewer 966 . data - location to write the data, treated as an array of type indicated by `datatype` 967 . num - number of items of data to read 968 - datatype - type of data to read 969 970 Output Parameter: 971 . count - number of items of data actually read, or `NULL` 972 973 Level: beginner 974 975 .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()` 976 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 977 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 978 @*/ 979 PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype) 980 { 981 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 982 FILE *fd = vascii->fd; 983 PetscInt i; 984 int ret = 0; 985 PetscMPIInt rank; 986 987 PetscFunctionBegin; 988 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 989 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 990 PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer"); 991 for (i = 0; i < num; i++) { 992 if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i])); 993 else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i])); 994 else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i])); 995 else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i])); 996 else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i])); 997 else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i])); 998 else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i])); 999 else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i])); 1000 #if defined(PETSC_USE_REAL___FLOAT128) 1001 else if (dtype == PETSC___FLOAT128) { 1002 double tmp; 1003 ret = fscanf(fd, "%lg", &tmp); 1004 ((__float128 *)data)[i] = tmp; 1005 } 1006 #endif 1007 else 1008 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype); 1009 PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype); 1010 if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */ 1011 } 1012 if (count) *count = i; 1013 else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num); 1014 PetscFunctionReturn(PETSC_SUCCESS); 1015 } 1016