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