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