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