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