1 2 #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h> /*I "petscviewer.h" I*/ 3 4 #define QUEUESTRINGSIZE 8192 5 6 static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer) 7 { 8 PetscMPIInt rank; 9 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 10 int err; 11 12 PetscFunctionBegin; 13 PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 14 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 15 if (rank == 0 && vascii->fd != stderr && vascii->fd != PETSC_STDOUT) { 16 if (vascii->fd && vascii->closefile) { 17 err = fclose(vascii->fd); 18 PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file"); 19 } 20 if (vascii->storecompressed) { 21 char par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN]; 22 FILE *fp; 23 PetscCall(PetscStrncpy(par, "gzip ", sizeof(par))); 24 PetscCall(PetscStrlcat(par, vascii->filename, sizeof(par))); 25 #if defined(PETSC_HAVE_POPEN) 26 PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp)); 27 PetscCheck(!fgets(buf, 1024, fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from compression command %s\n%s", par, buf); 28 PetscCall(PetscPClose(PETSC_COMM_SELF, fp)); 29 #else 30 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine"); 31 #endif 32 } 33 } 34 PetscCall(PetscFree(vascii->filename)); 35 PetscFunctionReturn(PETSC_SUCCESS); 36 } 37 38 /* ----------------------------------------------------------------------*/ 39 PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer) 40 { 41 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 42 PetscViewerLink *vlink; 43 PetscBool flg; 44 45 PetscFunctionBegin; 46 PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 47 PetscCall(PetscViewerFileClose_ASCII(viewer)); 48 PetscCall(PetscFree(vascii)); 49 50 /* remove the viewer from the list in the MPI Communicator */ 51 if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0)); 52 53 PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg)); 54 if (flg) { 55 if (vlink && vlink->viewer == viewer) { 56 if (vlink->next) { 57 PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next)); 58 } else { 59 PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval)); 60 } 61 PetscCall(PetscFree(vlink)); 62 } else { 63 while (vlink && vlink->next) { 64 if (vlink->next->viewer == viewer) { 65 PetscViewerLink *nv = vlink->next; 66 vlink->next = vlink->next->next; 67 PetscCall(PetscFree(nv)); 68 } 69 vlink = vlink->next; 70 } 71 } 72 } 73 74 if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) { 75 PetscViewer aviewer; 76 PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, (PetscMPIInt *)&flg)); 77 if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval)); 78 } 79 if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) { 80 PetscViewer aviewer; 81 PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, (PetscMPIInt *)&flg)); 82 if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval)); 83 } 84 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL)); 85 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL)); 86 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL)); 87 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL)); 88 PetscFunctionReturn(PETSC_SUCCESS); 89 } 90 91 PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer) 92 { 93 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 94 95 PetscFunctionBegin; 96 PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer)); 97 PetscFunctionReturn(PETSC_SUCCESS); 98 } 99 100 PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer) 101 { 102 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 103 MPI_Comm comm; 104 PetscMPIInt rank, size; 105 FILE *fd = vascii->fd; 106 107 PetscFunctionBegin; 108 PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 109 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 110 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 111 PetscCallMPI(MPI_Comm_size(comm, &size)); 112 113 if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd)); 114 115 if (vascii->allowsynchronized) { 116 PetscMPIInt tag, i, j, n = 0, dummy = 0; 117 char *message; 118 MPI_Status status; 119 120 PetscCall(PetscCommDuplicate(comm, &comm, &tag)); 121 122 /* First processor waits for messages from all other processors */ 123 if (rank == 0) { 124 /* flush my own messages that I may have queued up */ 125 PrintfQueue next = vascii->petsc_printfqueuebase, previous; 126 for (i = 0; i < vascii->petsc_printfqueuelength; i++) { 127 if (!vascii->bviewer) { 128 PetscCall(PetscFPrintf(comm, fd, "%s", next->string)); 129 } else { 130 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string)); 131 } 132 previous = next; 133 next = next->next; 134 PetscCall(PetscFree(previous->string)); 135 PetscCall(PetscFree(previous)); 136 } 137 vascii->petsc_printfqueue = NULL; 138 vascii->petsc_printfqueuelength = 0; 139 for (i = 1; i < size; i++) { 140 /* to prevent a flood of messages to process zero, request each message separately */ 141 PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm)); 142 PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status)); 143 for (j = 0; j < n; j++) { 144 PetscMPIInt size = 0; 145 146 PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status)); 147 PetscCall(PetscMalloc1(size, &message)); 148 PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status)); 149 if (!vascii->bviewer) { 150 PetscCall(PetscFPrintf(comm, fd, "%s", message)); 151 } else { 152 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message)); 153 } 154 PetscCall(PetscFree(message)); 155 } 156 } 157 } else { /* other processors send queue to processor 0 */ 158 PrintfQueue next = vascii->petsc_printfqueuebase, previous; 159 160 PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status)); 161 PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm)); 162 for (i = 0; i < vascii->petsc_printfqueuelength; i++) { 163 PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm)); 164 PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm)); 165 previous = next; 166 next = next->next; 167 PetscCall(PetscFree(previous->string)); 168 PetscCall(PetscFree(previous)); 169 } 170 vascii->petsc_printfqueue = NULL; 171 vascii->petsc_printfqueuelength = 0; 172 } 173 PetscCall(PetscCommDestroy(&comm)); 174 } 175 PetscFunctionReturn(PETSC_SUCCESS); 176 } 177 178 /*@C 179 PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`. 180 181 Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer; No Fortran Support 182 183 Input Parameter: 184 . viewer - `PetscViewer` context, obtained from `PetscViewerASCIIOpen()` 185 186 Output Parameter: 187 . fd - file pointer 188 189 Level: intermediate 190 191 Note: 192 For the standard `PETSCVIEWERASCII` the value is valid only on MPI rank 0 of the viewer 193 194 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, 195 `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()` 196 @*/ 197 PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd) 198 { 199 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 200 201 PetscFunctionBegin; 202 *fd = vascii->fd; 203 PetscFunctionReturn(PETSC_SUCCESS); 204 } 205 206 PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode) 207 { 208 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 209 210 PetscFunctionBegin; 211 *mode = vascii->mode; 212 PetscFunctionReturn(PETSC_SUCCESS); 213 } 214 215 PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode) 216 { 217 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 218 219 PetscFunctionBegin; 220 vascii->mode = mode; 221 PetscFunctionReturn(PETSC_SUCCESS); 222 } 223 224 /* 225 If petsc_history is on, then all Petsc*Printf() results are saved 226 if the appropriate (usually .petschistory) file. 227 */ 228 PETSC_INTERN FILE *petsc_history; 229 230 /*@ 231 PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times before printing 232 233 Not Collective, but only first processor in set has any effect; No Fortran Support 234 235 Input Parameters: 236 + viewer - obtained with `PetscViewerASCIIOpen()` 237 - tabs - number of tabs 238 239 Level: developer 240 241 Note: 242 `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage 243 244 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 245 `PetscViewerASCIIGetTab()`, 246 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 247 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, 248 `PetscViewerASCIIPushTab()` 249 @*/ 250 PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs) 251 { 252 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 253 PetscBool iascii; 254 255 PetscFunctionBegin; 256 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 257 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 258 if (iascii) ascii->tab = tabs; 259 PetscFunctionReturn(PETSC_SUCCESS); 260 } 261 262 /*@ 263 PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`. 264 265 Not Collective, meaningful on first processor only; No Fortran Support 266 267 Input Parameter: 268 . viewer - obtained with `PetscViewerASCIIOpen()` 269 270 Output Parameter: 271 . tabs - number of tabs 272 273 Level: developer 274 275 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 276 `PetscViewerASCIISetTab()`, 277 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 278 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()` 279 @*/ 280 PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs) 281 { 282 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 283 PetscBool iascii; 284 285 PetscFunctionBegin; 286 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 287 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 288 if (iascii && tabs) *tabs = ascii->tab; 289 PetscFunctionReturn(PETSC_SUCCESS); 290 } 291 292 /*@ 293 PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing 294 295 Not Collective, but only first processor in set has any effect; No Fortran Support 296 297 Input Parameters: 298 + viewer - obtained with `PetscViewerASCIIOpen()` 299 - tabs - number of tabs 300 301 Level: developer 302 303 Note: 304 `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage 305 306 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 307 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 308 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()` 309 @*/ 310 PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs) 311 { 312 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 313 PetscBool iascii; 314 315 PetscFunctionBegin; 316 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 317 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 318 if (iascii) ascii->tab += tabs; 319 PetscFunctionReturn(PETSC_SUCCESS); 320 } 321 322 /*@ 323 PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing 324 325 Not Collective, but only first processor in set has any effect; No Fortran Support 326 327 Input Parameters: 328 + viewer - obtained with `PetscViewerASCIIOpen()` 329 - tabs - number of tabs 330 331 Level: developer 332 333 Note: 334 `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage 335 336 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 337 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 338 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, 339 `PetscViewerASCIIPushTab()` 340 @*/ 341 PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs) 342 { 343 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 344 PetscBool iascii; 345 346 PetscFunctionBegin; 347 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 348 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 349 if (iascii) ascii->tab -= tabs; 350 PetscFunctionReturn(PETSC_SUCCESS); 351 } 352 353 /*@C 354 PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer 355 356 Collective 357 358 Input Parameter: 359 . viewer - obtained with `PetscViewerASCIIOpen()` 360 361 Level: intermediate 362 363 Note: 364 See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly. 365 366 .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 367 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 368 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 369 @*/ 370 PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer) 371 { 372 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 373 PetscBool iascii; 374 375 PetscFunctionBegin; 376 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 377 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 378 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 379 if (iascii) ascii->allowsynchronized++; 380 PetscFunctionReturn(PETSC_SUCCESS); 381 } 382 383 /*@C 384 PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer 385 386 Collective 387 388 Input Parameter: 389 . viewer - obtained with `PetscViewerASCIIOpen()` 390 391 Level: intermediate 392 393 Note: 394 See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly. 395 396 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, 397 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 398 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 399 @*/ 400 PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer) 401 { 402 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 403 PetscBool iascii; 404 405 PetscFunctionBegin; 406 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 407 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 408 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 409 if (iascii) { 410 ascii->allowsynchronized--; 411 PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()"); 412 } 413 PetscFunctionReturn(PETSC_SUCCESS); 414 } 415 416 /*@C 417 PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()` 418 lines are tabbed. 419 420 Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support 421 422 Input Parameter: 423 . viewer - obtained with `PetscViewerASCIIOpen()` 424 425 Level: developer 426 427 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 428 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 429 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()` 430 @*/ 431 PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer) 432 { 433 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 434 PetscBool iascii; 435 436 PetscFunctionBegin; 437 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 438 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 439 if (iascii) ascii->tab++; 440 PetscFunctionReturn(PETSC_SUCCESS); 441 } 442 443 /*@C 444 PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by 445 `PetscViewerASCIIPushTab()` 446 447 Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support 448 449 Input Parameter: 450 . viewer - obtained with `PetscViewerASCIIOpen()` 451 452 Level: developer 453 454 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 455 `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 456 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()` 457 @*/ 458 PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer) 459 { 460 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 461 PetscBool iascii; 462 463 PetscFunctionBegin; 464 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 465 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 466 if (iascii) { 467 PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed"); 468 ascii->tab--; 469 } 470 PetscFunctionReturn(PETSC_SUCCESS); 471 } 472 473 /*@ 474 PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer` 475 476 Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support 477 478 Input Parameters: 479 + viewer - obtained with `PetscViewerASCIIOpen()` 480 - flg - `PETSC_TRUE` or `PETSC_FALSE` 481 482 Level: developer 483 484 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 485 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`, 486 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()` 487 @*/ 488 PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg) 489 { 490 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 491 PetscBool iascii; 492 493 PetscFunctionBegin; 494 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 495 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 496 if (iascii) { 497 if (flg) ascii->tab = ascii->tab_store; 498 else { 499 ascii->tab_store = ascii->tab; 500 ascii->tab = 0; 501 } 502 } 503 PetscFunctionReturn(PETSC_SUCCESS); 504 } 505 506 #if defined(PETSC_USE_FORTRAN_BINDINGS) 507 508 #if defined(PETSC_HAVE_FORTRAN_CAPS) 509 #define petscviewerasciiopenwithfileunit_ PETSCVIEWERASCIIOPENWITHFILEUNIT 510 #define petscviewerasciisetfilefileunit_ PETSCVIEWERASCIISETFILEUNIT 511 #define petscfortranprinttounit_ PETSCFORTRANPRINTTOUNIT 512 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 513 #define petscviewerasciiopenwithfileunit_ petscviewerasciiopenwithfileunit 514 #define petscviewerasciisetfileunit_ petscviewerasciisetfileunit 515 #define petscfortranprinttounit_ petscfortranprinttounit 516 #endif 517 518 #if defined(__cplusplus) 519 extern "C" void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T); 520 #else 521 extern void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T); 522 #endif 523 524 #define PETSCDEFAULTBUFFERSIZE 8 * 1024 525 526 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header 527 /*@M 528 PetscViewerASCIISetFileUnit - sets the `PETSCASCIIVIEWER` to write to a Fortan IO unit 529 530 Synopsis: 531 #include <petscviewer.h> 532 void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr) 533 534 Input Parameters: 535 + lab - the viewer 536 - unit - the unit number 537 538 Output Parameter: 539 . ierr - the error code 540 541 Level: intermediate 542 543 Note: 544 `PetscViewerDestroy()` does not close the unit for this `PetscViewer` 545 546 Fortran Notes: 547 Only for Fortran, use `PetscViewerASCIISetFILE()` for C 548 549 .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()` 550 @*/ 551 PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, PetscInt *unit, PetscErrorCode *ierr) 552 { 553 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)(*lab)->data; 554 555 if (vascii->mode == FILE_MODE_READ) { 556 *ierr = PETSC_ERR_ARG_WRONGSTATE; 557 return; 558 } 559 vascii->fileunit = *unit; 560 } 561 562 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header 563 /*@M 564 PetscViewerASCIIOpenWithFileUnit - opens a `PETSCASCIIVIEWER` to write to a Fortan IO unit 565 566 Synopsis: 567 #include <petscviewer.h> 568 void PetscViewerASCIIOpenWithFileUnit(MPI_Comm comm, PetscInt unit, PetscViewer viewer, PetscErrorCode ierr) 569 570 Input Parameters: 571 + comm - the `MPI_Comm` to share the viewer 572 - unit - the unit number 573 574 Output Parameters: 575 + lab - the viewer 576 - ierr - the error code 577 578 Level: intermediate 579 580 Note: 581 `PetscViewerDestroy()` does not close the unit for this `PetscViewer` 582 583 Fortran Notes: 584 Only for Fortran, use `PetscViewerASCIIOpenWithFILE()` for C 585 586 .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()` 587 @*/ 588 PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Comm *comm, PetscInt *unit, PetscViewer *lab, PetscErrorCode *ierr) 589 { 590 *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab); 591 if (*ierr) return; 592 *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII); 593 if (*ierr) return; 594 *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE); 595 if (*ierr) return; 596 petscviewerasciisetfileunit_(lab, unit, ierr); 597 } 598 599 static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp) 600 { 601 PetscErrorCode ierr; 602 char str[PETSCDEFAULTBUFFERSIZE]; 603 size_t len; 604 605 PetscFunctionBegin; 606 PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp)); 607 PetscCall(PetscStrlen(str, &len)); 608 petscfortranprinttounit_(&unit, str, &ierr, (int)len); 609 PetscFunctionReturn(PETSC_SUCCESS); 610 } 611 612 static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[]) 613 { 614 PetscErrorCode ierr; 615 size_t len; 616 617 PetscFunctionBegin; 618 PetscCall(PetscStrlen(str, &len)); 619 petscfortranprinttounit_(&unit, str, &ierr, (int)len); 620 PetscFunctionReturn(PETSC_SUCCESS); 621 } 622 623 #else 624 625 /* these will never be used; but are needed to link with */ 626 static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp) 627 { 628 PetscFunctionBegin; 629 PetscFunctionReturn(PETSC_SUCCESS); 630 } 631 632 static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[]) 633 { 634 PetscFunctionBegin; 635 PetscFunctionReturn(PETSC_SUCCESS); 636 } 637 #endif 638 639 /*@C 640 PetscViewerASCIIPrintf - Prints to a file, only from the first 641 processor in the `PetscViewer` of type `PETSCVIEWERASCII` 642 643 Not Collective, but only the first MPI rank in the viewer has any effect 644 645 Input Parameters: 646 + viewer - obtained with `PetscViewerASCIIOpen()` 647 - format - the usual printf() format string 648 649 Level: developer 650 651 Fortran Notes: 652 The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran. 653 That is, you can only pass a single character string from Fortran. 654 655 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 656 `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, 657 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()` 658 @*/ 659 PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...) 660 { 661 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 662 PetscMPIInt rank; 663 PetscInt tab, intab = ascii->tab; 664 FILE *fd = ascii->fd; 665 PetscBool iascii; 666 667 PetscFunctionBegin; 668 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 669 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 670 PetscAssertPointer(format, 2); 671 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 672 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 673 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 674 if (rank) PetscFunctionReturn(PETSC_SUCCESS); 675 676 if (ascii->bviewer) { /* pass string up to parent viewer */ 677 char *string; 678 va_list Argp; 679 size_t fullLength; 680 681 PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string)); 682 va_start(Argp, format); 683 PetscCall(PetscVSNPrintf(string, QUEUESTRINGSIZE, format, &fullLength, Argp)); 684 va_end(Argp); 685 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%s", string)); 686 PetscCall(PetscFree(string)); 687 } else { /* write directly to file */ 688 va_list Argp; 689 /* flush my own messages that I may have queued up */ 690 PrintfQueue next = ascii->petsc_printfqueuebase, previous; 691 PetscInt i; 692 for (i = 0; i < ascii->petsc_printfqueuelength; i++) { 693 if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "%s", next->string)); 694 else PetscCall(PetscFPrintfFortran(ascii->fileunit, next->string)); 695 previous = next; 696 next = next->next; 697 PetscCall(PetscFree(previous->string)); 698 PetscCall(PetscFree(previous)); 699 } 700 ascii->petsc_printfqueue = NULL; 701 ascii->petsc_printfqueuelength = 0; 702 tab = intab; 703 while (tab--) { 704 if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, " ")); 705 else PetscCall(PetscFPrintfFortran(ascii->fileunit, " ")); 706 } 707 708 va_start(Argp, format); 709 if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp)); 710 else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp)); 711 va_end(Argp); 712 PetscCall(PetscFFlush(fd)); 713 } 714 PetscFunctionReturn(PETSC_SUCCESS); 715 } 716 717 /*@C 718 PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use. 719 720 Collective 721 722 Input Parameters: 723 + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY` 724 - name - the name of the file it should use 725 726 Level: advanced 727 728 Note: 729 This will have no effect on viewers that are not related to files 730 731 .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`, 732 `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()` 733 @*/ 734 PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[]) 735 { 736 char filename[PETSC_MAX_PATH_LEN]; 737 738 PetscFunctionBegin; 739 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 740 PetscAssertPointer(name, 2); 741 PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename))); 742 PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename)); 743 PetscFunctionReturn(PETSC_SUCCESS); 744 } 745 746 /*@C 747 PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using 748 749 Not Collective 750 751 Input Parameter: 752 . viewer - the `PetscViewer` 753 754 Output Parameter: 755 . name - the name of the file it is using 756 757 Level: advanced 758 759 Note: 760 This will have no effect on viewers that are not related to files 761 762 .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()` 763 @*/ 764 PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name) 765 { 766 PetscFunctionBegin; 767 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 768 PetscAssertPointer(name, 2); 769 PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name)); 770 PetscFunctionReturn(PETSC_SUCCESS); 771 } 772 773 PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name) 774 { 775 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 776 777 PetscFunctionBegin; 778 *name = vascii->filename; 779 PetscFunctionReturn(PETSC_SUCCESS); 780 } 781 782 #include <errno.h> 783 PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[]) 784 { 785 size_t len; 786 char fname[PETSC_MAX_PATH_LEN], *gz = NULL; 787 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 788 PetscBool isstderr, isstdout; 789 PetscMPIInt rank; 790 791 PetscFunctionBegin; 792 PetscCall(PetscViewerFileClose_ASCII(viewer)); 793 if (!name) PetscFunctionReturn(PETSC_SUCCESS); 794 PetscCall(PetscStrallocpy(name, &vascii->filename)); 795 796 /* Is this file to be compressed */ 797 vascii->storecompressed = PETSC_FALSE; 798 799 PetscCall(PetscStrstr(vascii->filename, ".gz", &gz)); 800 if (gz) { 801 PetscCall(PetscStrlen(gz, &len)); 802 if (len == 3) { 803 PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first"); 804 *gz = 0; 805 vascii->storecompressed = PETSC_TRUE; 806 } 807 } 808 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 809 if (rank == 0) { 810 PetscCall(PetscStrcmp(name, "stderr", &isstderr)); 811 PetscCall(PetscStrcmp(name, "stdout", &isstdout)); 812 /* empty filename means stdout */ 813 if (name[0] == 0) isstdout = PETSC_TRUE; 814 if (isstderr) vascii->fd = PETSC_STDERR; 815 else if (isstdout) vascii->fd = PETSC_STDOUT; 816 else { 817 PetscCall(PetscFixFilename(name, fname)); 818 switch (vascii->mode) { 819 case FILE_MODE_READ: 820 vascii->fd = fopen(fname, "r"); 821 break; 822 case FILE_MODE_WRITE: 823 vascii->fd = fopen(fname, "w"); 824 break; 825 case FILE_MODE_APPEND: 826 vascii->fd = fopen(fname, "a"); 827 break; 828 case FILE_MODE_UPDATE: 829 vascii->fd = fopen(fname, "r+"); 830 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 831 break; 832 case FILE_MODE_APPEND_UPDATE: 833 /* I really want a file which is opened at the end for updating, 834 not a+, which opens at the beginning, but makes writes at the end. 835 */ 836 vascii->fd = fopen(fname, "r+"); 837 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 838 else { 839 int ret = fseek(vascii->fd, 0, SEEK_END); 840 PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret); 841 } 842 break; 843 default: 844 SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]); 845 } 846 PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno)); 847 } 848 } 849 #if defined(PETSC_USE_LOG) 850 PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name)); 851 #endif 852 PetscFunctionReturn(PETSC_SUCCESS); 853 } 854 855 PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer) 856 { 857 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii; 858 859 PetscFunctionBegin; 860 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 861 PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored"); 862 /* 863 The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work 864 because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed 865 (since the count never gets to zero) in some examples this displays information that otherwise would be lost 866 867 This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example, 868 PCView_GASM(). 869 */ 870 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 871 PetscCall(PetscViewerCreate(subcomm, outviewer)); 872 PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII)); 873 PetscCall(PetscViewerASCIIPushSynchronized(*outviewer)); 874 ovascii = (PetscViewer_ASCII *)(*outviewer)->data; 875 ovascii->fd = vascii->fd; 876 ovascii->tab = vascii->tab; 877 ovascii->closefile = PETSC_FALSE; 878 879 vascii->sviewer = *outviewer; 880 (*outviewer)->format = viewer->format; 881 ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer; 882 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer; 883 PetscFunctionReturn(PETSC_SUCCESS); 884 } 885 886 PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer) 887 { 888 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 889 890 PetscFunctionBegin; 891 PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer"); 892 PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer"); 893 894 PetscCall(PetscViewerASCIIPopSynchronized(*outviewer)); 895 ascii->sviewer = NULL; 896 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII; 897 PetscCall(PetscViewerDestroy(outviewer)); 898 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 899 PetscFunctionReturn(PETSC_SUCCESS); 900 } 901 902 PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer) 903 { 904 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data; 905 906 PetscFunctionBegin; 907 if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename)); 908 PetscFunctionReturn(PETSC_SUCCESS); 909 } 910 911 /*MC 912 PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file 913 914 Level: beginner 915 916 .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, 917 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, 918 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 919 M*/ 920 PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer) 921 { 922 PetscViewer_ASCII *vascii; 923 924 PetscFunctionBegin; 925 PetscCall(PetscNew(&vascii)); 926 viewer->data = (void *)vascii; 927 928 viewer->ops->destroy = PetscViewerDestroy_ASCII; 929 viewer->ops->flush = PetscViewerFlush_ASCII; 930 viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII; 931 viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII; 932 viewer->ops->view = PetscViewerView_ASCII; 933 viewer->ops->read = PetscViewerASCIIRead; 934 935 /* defaults to stdout unless set with PetscViewerFileSetName() */ 936 vascii->fd = PETSC_STDOUT; 937 vascii->mode = FILE_MODE_WRITE; 938 vascii->bviewer = NULL; 939 vascii->subviewer = NULL; 940 vascii->sviewer = NULL; 941 vascii->tab = 0; 942 vascii->tab_store = 0; 943 vascii->filename = NULL; 944 vascii->closefile = PETSC_TRUE; 945 946 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII)); 947 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII)); 948 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII)); 949 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII)); 950 PetscFunctionReturn(PETSC_SUCCESS); 951 } 952 953 /*@C 954 PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from 955 several processors. Output of the first processor is followed by that of the 956 second, etc. 957 958 Not Collective, must call collective `PetscViewerFlush()` to get the results flushed 959 960 Input Parameters: 961 + viewer - the `PETSCVIEWERASCII` `PetscViewer` 962 - format - the usual printf() format string 963 964 Level: intermediate 965 966 Notes: 967 You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called. 968 Then you can do multiple independent calls to this routine. 969 970 The actual synchronized print is then done using `PetscViewerFlush()`. 971 `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output 972 to conclude the "synchronized session". 973 974 So the typical calling sequence looks like 975 .vb 976 PetscViewerASCIIPushSynchronized(viewer); 977 PetscViewerASCIISynchronizedPrintf(viewer, ...); 978 PetscViewerASCIISynchronizedPrintf(viewer, ...); 979 ... 980 PetscViewerFlush(viewer); 981 PetscViewerASCIISynchronizedPrintf(viewer, ...); 982 PetscViewerASCIISynchronizedPrintf(viewer, ...); 983 ... 984 PetscViewerFlush(viewer); 985 PetscViewerASCIIPopSynchronized(viewer); 986 .ve 987 988 Fortran Notes: 989 Can only print a single character* string 990 991 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 992 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 993 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 994 @*/ 995 PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...) 996 { 997 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 998 PetscMPIInt rank; 999 PetscInt tab = vascii->tab; 1000 MPI_Comm comm; 1001 FILE *fp; 1002 PetscBool iascii, hasbviewer = PETSC_FALSE; 1003 1004 PetscFunctionBegin; 1005 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 1006 PetscAssertPointer(format, 2); 1007 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 1008 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 1009 PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call"); 1010 1011 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 1012 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1013 1014 if (vascii->bviewer) { 1015 hasbviewer = PETSC_TRUE; 1016 if (rank == 0) { 1017 vascii = (PetscViewer_ASCII *)vascii->bviewer->data; 1018 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 1019 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1020 } 1021 } 1022 1023 fp = vascii->fd; 1024 1025 if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */ 1026 va_list Argp; 1027 /* flush my own messages that I may have queued up */ 1028 PrintfQueue next = vascii->petsc_printfqueuebase, previous; 1029 PetscInt i; 1030 for (i = 0; i < vascii->petsc_printfqueuelength; i++) { 1031 PetscCall(PetscFPrintf(comm, fp, "%s", next->string)); 1032 previous = next; 1033 next = next->next; 1034 PetscCall(PetscFree(previous->string)); 1035 PetscCall(PetscFree(previous)); 1036 } 1037 vascii->petsc_printfqueue = NULL; 1038 vascii->petsc_printfqueuelength = 0; 1039 1040 while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " ")); 1041 1042 va_start(Argp, format); 1043 PetscCall((*PetscVFPrintf)(fp, format, Argp)); 1044 va_end(Argp); 1045 PetscCall(PetscFFlush(fp)); 1046 if (petsc_history) { 1047 va_start(Argp, format); 1048 PetscCall((*PetscVFPrintf)(petsc_history, format, Argp)); 1049 va_end(Argp); 1050 PetscCall(PetscFFlush(petsc_history)); 1051 } 1052 va_end(Argp); 1053 } else { /* other processors add to queue */ 1054 char *string; 1055 va_list Argp; 1056 size_t fullLength; 1057 PrintfQueue next; 1058 1059 PetscCall(PetscNew(&next)); 1060 if (vascii->petsc_printfqueue) { 1061 vascii->petsc_printfqueue->next = next; 1062 vascii->petsc_printfqueue = next; 1063 } else { 1064 vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next; 1065 } 1066 vascii->petsc_printfqueuelength++; 1067 next->size = QUEUESTRINGSIZE; 1068 PetscCall(PetscCalloc1(next->size, &next->string)); 1069 string = next->string; 1070 tab *= 2; 1071 while (tab--) *string++ = ' '; 1072 va_start(Argp, format); 1073 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp)); 1074 va_end(Argp); 1075 if (fullLength > (size_t)(next->size - 2 * vascii->tab)) { 1076 PetscCall(PetscFree(next->string)); 1077 next->size = fullLength + 2 * vascii->tab; 1078 PetscCall(PetscCalloc1(next->size, &next->string)); 1079 string = next->string; 1080 tab = 2 * vascii->tab; 1081 while (tab--) *string++ = ' '; 1082 va_start(Argp, format); 1083 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp)); 1084 va_end(Argp); 1085 } 1086 } 1087 PetscFunctionReturn(PETSC_SUCCESS); 1088 } 1089 1090 /*@C 1091 PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file 1092 1093 Only MPI rank 0 in the `PetscViewer` may call this 1094 1095 Input Parameters: 1096 + viewer - the `PETSCVIEWERASCII` viewer 1097 . data - location to write the data, treated as an array of type indicated by `datatype` 1098 . num - number of items of data to read 1099 - dtype - type of data to read 1100 1101 Output Parameter: 1102 . count - number of items of data actually read, or `NULL` 1103 1104 Level: beginner 1105 1106 .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()` 1107 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 1108 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 1109 @*/ 1110 PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype) 1111 { 1112 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 1113 FILE *fd = vascii->fd; 1114 PetscInt i; 1115 int ret = 0; 1116 PetscMPIInt rank; 1117 1118 PetscFunctionBegin; 1119 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 1120 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 1121 PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer"); 1122 for (i = 0; i < num; i++) { 1123 if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i])); 1124 else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i])); 1125 else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i])); 1126 else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i])); 1127 else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i])); 1128 else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i])); 1129 else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i])); 1130 else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i])); 1131 #if defined(PETSC_USE_REAL___FLOAT128) 1132 else if (dtype == PETSC___FLOAT128) { 1133 double tmp; 1134 ret = fscanf(fd, "%lg", &tmp); 1135 ((__float128 *)data)[i] = tmp; 1136 } 1137 #endif 1138 else 1139 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype); 1140 PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype); 1141 if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */ 1142 } 1143 if (count) *count = i; 1144 else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num); 1145 PetscFunctionReturn(PETSC_SUCCESS); 1146 } 1147