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 #include <errno.h> 653 PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[]) 654 { 655 size_t len; 656 char fname[PETSC_MAX_PATH_LEN], *gz = NULL; 657 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 658 PetscBool isstderr, isstdout; 659 PetscMPIInt rank; 660 661 PetscFunctionBegin; 662 PetscCall(PetscViewerFileClose_ASCII(viewer)); 663 if (!name) PetscFunctionReturn(PETSC_SUCCESS); 664 PetscCall(PetscStrallocpy(name, &vascii->filename)); 665 666 /* Is this file to be compressed */ 667 vascii->storecompressed = PETSC_FALSE; 668 669 PetscCall(PetscStrstr(vascii->filename, ".gz", &gz)); 670 if (gz) { 671 PetscCall(PetscStrlen(gz, &len)); 672 if (len == 3) { 673 PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first"); 674 *gz = 0; 675 vascii->storecompressed = PETSC_TRUE; 676 } 677 } 678 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 679 if (rank == 0) { 680 PetscCall(PetscStrcmp(name, "stderr", &isstderr)); 681 PetscCall(PetscStrcmp(name, "stdout", &isstdout)); 682 /* empty filename means stdout */ 683 if (name[0] == 0) isstdout = PETSC_TRUE; 684 if (isstderr) vascii->fd = PETSC_STDERR; 685 else if (isstdout) vascii->fd = PETSC_STDOUT; 686 else { 687 PetscCall(PetscFixFilename(name, fname)); 688 switch (vascii->mode) { 689 case FILE_MODE_READ: 690 vascii->fd = fopen(fname, "r"); 691 break; 692 case FILE_MODE_WRITE: 693 vascii->fd = fopen(fname, "w"); 694 break; 695 case FILE_MODE_APPEND: 696 vascii->fd = fopen(fname, "a"); 697 break; 698 case FILE_MODE_UPDATE: 699 vascii->fd = fopen(fname, "r+"); 700 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 701 break; 702 case FILE_MODE_APPEND_UPDATE: 703 /* I really want a file which is opened at the end for updating, 704 not a+, which opens at the beginning, but makes writes at the end. 705 */ 706 vascii->fd = fopen(fname, "r+"); 707 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 708 else { 709 int ret = fseek(vascii->fd, 0, SEEK_END); 710 PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret); 711 } 712 break; 713 default: 714 SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]); 715 } 716 PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno)); 717 } 718 } 719 #if defined(PETSC_USE_LOG) 720 PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name)); 721 #endif 722 PetscFunctionReturn(PETSC_SUCCESS); 723 } 724 725 PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer) 726 { 727 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii; 728 729 PetscFunctionBegin; 730 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 731 PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored"); 732 /* 733 The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work 734 because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed 735 (since the count never gets to zero) in some examples this displays information that otherwise would be lost 736 737 This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example, 738 PCView_GASM(). 739 */ 740 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 741 PetscCall(PetscViewerCreate(subcomm, outviewer)); 742 PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII)); 743 PetscCall(PetscViewerASCIIPushSynchronized(*outviewer)); 744 ovascii = (PetscViewer_ASCII *)(*outviewer)->data; 745 ovascii->fd = vascii->fd; 746 ovascii->tab = vascii->tab; 747 ovascii->closefile = PETSC_FALSE; 748 749 vascii->sviewer = *outviewer; 750 (*outviewer)->format = viewer->format; 751 ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer; 752 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer; 753 PetscFunctionReturn(PETSC_SUCCESS); 754 } 755 756 PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer) 757 { 758 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 759 760 PetscFunctionBegin; 761 PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer"); 762 PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer"); 763 764 PetscCall(PetscViewerASCIIPopSynchronized(*outviewer)); 765 ascii->sviewer = NULL; 766 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII; 767 PetscCall(PetscViewerDestroy(outviewer)); 768 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 769 PetscFunctionReturn(PETSC_SUCCESS); 770 } 771 772 PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer) 773 { 774 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data; 775 776 PetscFunctionBegin; 777 if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename)); 778 PetscFunctionReturn(PETSC_SUCCESS); 779 } 780 781 /*MC 782 PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file 783 784 Level: beginner 785 786 .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, 787 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, 788 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 789 M*/ 790 PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer) 791 { 792 PetscViewer_ASCII *vascii; 793 794 PetscFunctionBegin; 795 PetscCall(PetscNew(&vascii)); 796 viewer->data = (void *)vascii; 797 798 viewer->ops->destroy = PetscViewerDestroy_ASCII; 799 viewer->ops->flush = PetscViewerFlush_ASCII; 800 viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII; 801 viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII; 802 viewer->ops->view = PetscViewerView_ASCII; 803 viewer->ops->read = PetscViewerASCIIRead; 804 805 /* defaults to stdout unless set with PetscViewerFileSetName() */ 806 vascii->fd = PETSC_STDOUT; 807 vascii->mode = FILE_MODE_WRITE; 808 vascii->bviewer = NULL; 809 vascii->subviewer = NULL; 810 vascii->sviewer = NULL; 811 vascii->tab = 0; 812 vascii->tab_store = 0; 813 vascii->filename = NULL; 814 vascii->closefile = PETSC_TRUE; 815 816 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII)); 817 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII)); 818 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII)); 819 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII)); 820 PetscFunctionReturn(PETSC_SUCCESS); 821 } 822 823 /*@C 824 PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from 825 several processors. Output of the first processor is followed by that of the 826 second, etc. 827 828 Not Collective, must call collective `PetscViewerFlush()` to get the results flushed 829 830 Input Parameters: 831 + viewer - the `PETSCVIEWERASCII` `PetscViewer` 832 - format - the usual printf() format string 833 834 Level: intermediate 835 836 Notes: 837 You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called. 838 Then you can do multiple independent calls to this routine. 839 840 The actual synchronized print is then done using `PetscViewerFlush()`. 841 `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output 842 to conclude the "synchronized session". 843 844 So the typical calling sequence looks like 845 .vb 846 PetscViewerASCIIPushSynchronized(viewer); 847 PetscViewerASCIISynchronizedPrintf(viewer, ...); 848 PetscViewerASCIISynchronizedPrintf(viewer, ...); 849 ... 850 PetscViewerFlush(viewer); 851 PetscViewerASCIISynchronizedPrintf(viewer, ...); 852 PetscViewerASCIISynchronizedPrintf(viewer, ...); 853 ... 854 PetscViewerFlush(viewer); 855 PetscViewerASCIIPopSynchronized(viewer); 856 .ve 857 858 Fortran Note: 859 Can only print a single character* string 860 861 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 862 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 863 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 864 @*/ 865 PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...) 866 { 867 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 868 PetscMPIInt rank; 869 PetscInt tab = vascii->tab; 870 MPI_Comm comm; 871 FILE *fp; 872 PetscBool iascii, hasbviewer = PETSC_FALSE; 873 874 PetscFunctionBegin; 875 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 876 PetscValidCharPointer(format, 2); 877 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 878 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 879 PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call"); 880 881 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 882 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 883 884 if (vascii->bviewer) { 885 hasbviewer = PETSC_TRUE; 886 if (rank == 0) { 887 vascii = (PetscViewer_ASCII *)vascii->bviewer->data; 888 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 889 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 890 } 891 } 892 893 fp = vascii->fd; 894 895 if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */ 896 va_list Argp; 897 /* flush my own messages that I may have queued up */ 898 PrintfQueue next = vascii->petsc_printfqueuebase, previous; 899 PetscInt i; 900 for (i = 0; i < vascii->petsc_printfqueuelength; i++) { 901 PetscCall(PetscFPrintf(comm, fp, "%s", next->string)); 902 previous = next; 903 next = next->next; 904 PetscCall(PetscFree(previous->string)); 905 PetscCall(PetscFree(previous)); 906 } 907 vascii->petsc_printfqueue = NULL; 908 vascii->petsc_printfqueuelength = 0; 909 910 while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " ")); 911 912 va_start(Argp, format); 913 PetscCall((*PetscVFPrintf)(fp, format, Argp)); 914 va_end(Argp); 915 PetscCall(PetscFFlush(fp)); 916 if (petsc_history) { 917 va_start(Argp, format); 918 PetscCall((*PetscVFPrintf)(petsc_history, format, Argp)); 919 va_end(Argp); 920 PetscCall(PetscFFlush(petsc_history)); 921 } 922 va_end(Argp); 923 } else { /* other processors add to queue */ 924 char *string; 925 va_list Argp; 926 size_t fullLength; 927 PrintfQueue next; 928 929 PetscCall(PetscNew(&next)); 930 if (vascii->petsc_printfqueue) { 931 vascii->petsc_printfqueue->next = next; 932 vascii->petsc_printfqueue = next; 933 } else { 934 vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next; 935 } 936 vascii->petsc_printfqueuelength++; 937 next->size = QUEUESTRINGSIZE; 938 PetscCall(PetscCalloc1(next->size, &next->string)); 939 string = next->string; 940 tab *= 2; 941 while (tab--) *string++ = ' '; 942 va_start(Argp, format); 943 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp)); 944 va_end(Argp); 945 if (fullLength > (size_t)(next->size - 2 * vascii->tab)) { 946 PetscCall(PetscFree(next->string)); 947 next->size = fullLength + 2 * vascii->tab; 948 PetscCall(PetscCalloc1(next->size, &next->string)); 949 string = next->string; 950 tab = 2 * vascii->tab; 951 while (tab--) *string++ = ' '; 952 va_start(Argp, format); 953 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp)); 954 va_end(Argp); 955 } 956 } 957 PetscFunctionReturn(PETSC_SUCCESS); 958 } 959 960 /*@C 961 PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file 962 963 Only MPI rank 0 in the `PetscViewer` may call this 964 965 Input Parameters: 966 + viewer - the `PETSCVIEWERASCII` viewer 967 . data - location to write the data, treated as an array of type indicated by `datatype` 968 . num - number of items of data to read 969 - datatype - type of data to read 970 971 Output Parameter: 972 . count - number of items of data actually read, or `NULL` 973 974 Level: beginner 975 976 .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()` 977 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 978 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 979 @*/ 980 PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype) 981 { 982 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 983 FILE *fd = vascii->fd; 984 PetscInt i; 985 int ret = 0; 986 PetscMPIInt rank; 987 988 PetscFunctionBegin; 989 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 990 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 991 PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer"); 992 for (i = 0; i < num; i++) { 993 if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i])); 994 else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i])); 995 else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i])); 996 else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i])); 997 else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i])); 998 else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i])); 999 else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i])); 1000 else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i])); 1001 #if defined(PETSC_USE_REAL___FLOAT128) 1002 else if (dtype == PETSC___FLOAT128) { 1003 double tmp; 1004 ret = fscanf(fd, "%lg", &tmp); 1005 ((__float128 *)data)[i] = tmp; 1006 } 1007 #endif 1008 else 1009 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype); 1010 PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype); 1011 if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */ 1012 } 1013 if (count) *count = i; 1014 else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num); 1015 PetscFunctionReturn(PETSC_SUCCESS); 1016 } 1017