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