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 /*MC 528 PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` 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 M*/ 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 /*MC 564 PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` 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 M*/ 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 PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name)); 850 PetscFunctionReturn(PETSC_SUCCESS); 851 } 852 853 PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer) 854 { 855 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii; 856 857 PetscFunctionBegin; 858 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 859 PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored"); 860 /* 861 The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work 862 because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed 863 (since the count never gets to zero) in some examples this displays information that otherwise would be lost 864 865 This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example, 866 PCView_GASM(). 867 */ 868 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 869 PetscCall(PetscViewerCreate(subcomm, outviewer)); 870 PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII)); 871 PetscCall(PetscViewerASCIIPushSynchronized(*outviewer)); 872 ovascii = (PetscViewer_ASCII *)(*outviewer)->data; 873 ovascii->fd = vascii->fd; 874 ovascii->tab = vascii->tab; 875 ovascii->closefile = PETSC_FALSE; 876 877 vascii->sviewer = *outviewer; 878 (*outviewer)->format = viewer->format; 879 ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer; 880 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer; 881 PetscFunctionReturn(PETSC_SUCCESS); 882 } 883 884 PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer) 885 { 886 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 887 888 PetscFunctionBegin; 889 PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer"); 890 PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer"); 891 892 PetscCall(PetscViewerASCIIPopSynchronized(*outviewer)); 893 ascii->sviewer = NULL; 894 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII; 895 PetscCall(PetscViewerDestroy(outviewer)); 896 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 897 PetscFunctionReturn(PETSC_SUCCESS); 898 } 899 900 PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer) 901 { 902 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data; 903 904 PetscFunctionBegin; 905 if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename)); 906 PetscFunctionReturn(PETSC_SUCCESS); 907 } 908 909 /*MC 910 PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file 911 912 Level: beginner 913 914 .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, 915 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, 916 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 917 M*/ 918 PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer) 919 { 920 PetscViewer_ASCII *vascii; 921 922 PetscFunctionBegin; 923 PetscCall(PetscNew(&vascii)); 924 viewer->data = (void *)vascii; 925 926 viewer->ops->destroy = PetscViewerDestroy_ASCII; 927 viewer->ops->flush = PetscViewerFlush_ASCII; 928 viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII; 929 viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII; 930 viewer->ops->view = PetscViewerView_ASCII; 931 viewer->ops->read = PetscViewerASCIIRead; 932 933 /* defaults to stdout unless set with PetscViewerFileSetName() */ 934 vascii->fd = PETSC_STDOUT; 935 vascii->mode = FILE_MODE_WRITE; 936 vascii->bviewer = NULL; 937 vascii->subviewer = NULL; 938 vascii->sviewer = NULL; 939 vascii->tab = 0; 940 vascii->tab_store = 0; 941 vascii->filename = NULL; 942 vascii->closefile = PETSC_TRUE; 943 944 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII)); 945 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII)); 946 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII)); 947 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII)); 948 PetscFunctionReturn(PETSC_SUCCESS); 949 } 950 951 /*@C 952 PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from 953 several processors. Output of the first processor is followed by that of the 954 second, etc. 955 956 Not Collective, must call collective `PetscViewerFlush()` to get the results flushed 957 958 Input Parameters: 959 + viewer - the `PETSCVIEWERASCII` `PetscViewer` 960 - format - the usual printf() format string 961 962 Level: intermediate 963 964 Notes: 965 You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called. 966 Then you can do multiple independent calls to this routine. 967 968 The actual synchronized print is then done using `PetscViewerFlush()`. 969 `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output 970 to conclude the "synchronized session". 971 972 So the typical calling sequence looks like 973 .vb 974 PetscViewerASCIIPushSynchronized(viewer); 975 PetscViewerASCIISynchronizedPrintf(viewer, ...); 976 PetscViewerASCIISynchronizedPrintf(viewer, ...); 977 ... 978 PetscViewerFlush(viewer); 979 PetscViewerASCIISynchronizedPrintf(viewer, ...); 980 PetscViewerASCIISynchronizedPrintf(viewer, ...); 981 ... 982 PetscViewerFlush(viewer); 983 PetscViewerASCIIPopSynchronized(viewer); 984 .ve 985 986 Fortran Notes: 987 Can only print a single character* string 988 989 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 990 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 991 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 992 @*/ 993 PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...) 994 { 995 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 996 PetscMPIInt rank; 997 PetscInt tab = vascii->tab; 998 MPI_Comm comm; 999 FILE *fp; 1000 PetscBool iascii, hasbviewer = PETSC_FALSE; 1001 1002 PetscFunctionBegin; 1003 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 1004 PetscAssertPointer(format, 2); 1005 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 1006 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 1007 PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call"); 1008 1009 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 1010 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1011 1012 if (vascii->bviewer) { 1013 hasbviewer = PETSC_TRUE; 1014 if (rank == 0) { 1015 vascii = (PetscViewer_ASCII *)vascii->bviewer->data; 1016 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 1017 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1018 } 1019 } 1020 1021 fp = vascii->fd; 1022 1023 if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */ 1024 va_list Argp; 1025 /* flush my own messages that I may have queued up */ 1026 PrintfQueue next = vascii->petsc_printfqueuebase, previous; 1027 PetscInt i; 1028 for (i = 0; i < vascii->petsc_printfqueuelength; i++) { 1029 PetscCall(PetscFPrintf(comm, fp, "%s", next->string)); 1030 previous = next; 1031 next = next->next; 1032 PetscCall(PetscFree(previous->string)); 1033 PetscCall(PetscFree(previous)); 1034 } 1035 vascii->petsc_printfqueue = NULL; 1036 vascii->petsc_printfqueuelength = 0; 1037 1038 while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " ")); 1039 1040 va_start(Argp, format); 1041 PetscCall((*PetscVFPrintf)(fp, format, Argp)); 1042 va_end(Argp); 1043 PetscCall(PetscFFlush(fp)); 1044 if (petsc_history) { 1045 va_start(Argp, format); 1046 PetscCall((*PetscVFPrintf)(petsc_history, format, Argp)); 1047 va_end(Argp); 1048 PetscCall(PetscFFlush(petsc_history)); 1049 } 1050 va_end(Argp); 1051 } else { /* other processors add to queue */ 1052 char *string; 1053 va_list Argp; 1054 size_t fullLength; 1055 PrintfQueue next; 1056 1057 PetscCall(PetscNew(&next)); 1058 if (vascii->petsc_printfqueue) { 1059 vascii->petsc_printfqueue->next = next; 1060 vascii->petsc_printfqueue = next; 1061 } else { 1062 vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next; 1063 } 1064 vascii->petsc_printfqueuelength++; 1065 next->size = QUEUESTRINGSIZE; 1066 PetscCall(PetscCalloc1(next->size, &next->string)); 1067 string = next->string; 1068 tab *= 2; 1069 while (tab--) *string++ = ' '; 1070 va_start(Argp, format); 1071 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp)); 1072 va_end(Argp); 1073 if (fullLength > (size_t)(next->size - 2 * vascii->tab)) { 1074 PetscCall(PetscFree(next->string)); 1075 next->size = fullLength + 2 * vascii->tab; 1076 PetscCall(PetscCalloc1(next->size, &next->string)); 1077 string = next->string; 1078 tab = 2 * vascii->tab; 1079 while (tab--) *string++ = ' '; 1080 va_start(Argp, format); 1081 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp)); 1082 va_end(Argp); 1083 } 1084 } 1085 PetscFunctionReturn(PETSC_SUCCESS); 1086 } 1087 1088 /*@C 1089 PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file 1090 1091 Only MPI rank 0 in the `PetscViewer` may call this 1092 1093 Input Parameters: 1094 + viewer - the `PETSCVIEWERASCII` viewer 1095 . data - location to write the data, treated as an array of type indicated by `datatype` 1096 . num - number of items of data to read 1097 - dtype - type of data to read 1098 1099 Output Parameter: 1100 . count - number of items of data actually read, or `NULL` 1101 1102 Level: beginner 1103 1104 .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()` 1105 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 1106 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 1107 @*/ 1108 PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype) 1109 { 1110 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 1111 FILE *fd = vascii->fd; 1112 PetscInt i; 1113 int ret = 0; 1114 PetscMPIInt rank; 1115 1116 PetscFunctionBegin; 1117 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 1118 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 1119 PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer"); 1120 for (i = 0; i < num; i++) { 1121 if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i])); 1122 else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i])); 1123 else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i])); 1124 else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i])); 1125 else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i])); 1126 else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i])); 1127 else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i])); 1128 else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i])); 1129 #if defined(PETSC_USE_REAL___FLOAT128) 1130 else if (dtype == PETSC___FLOAT128) { 1131 double tmp; 1132 ret = fscanf(fd, "%lg", &tmp); 1133 ((__float128 *)data)[i] = tmp; 1134 } 1135 #endif 1136 else 1137 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype); 1138 PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype); 1139 if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */ 1140 } 1141 if (count) *count = i; 1142 else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num); 1143 PetscFunctionReturn(PETSC_SUCCESS); 1144 } 1145