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 %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 static PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer) 38 { 39 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 40 PetscViewerLink *vlink; 41 PetscBool flg; 42 43 PetscFunctionBegin; 44 PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 45 PetscCall(PetscViewerFileClose_ASCII(viewer)); 46 PetscCall(PetscFree(vascii)); 47 48 /* remove the viewer from the list in the MPI Communicator */ 49 if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0)); 50 51 PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg)); 52 if (flg) { 53 if (vlink && vlink->viewer == viewer) { 54 if (vlink->next) { 55 PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next)); 56 } else { 57 PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval)); 58 } 59 PetscCall(PetscFree(vlink)); 60 } else { 61 while (vlink && vlink->next) { 62 if (vlink->next->viewer == viewer) { 63 PetscViewerLink *nv = vlink->next; 64 vlink->next = vlink->next->next; 65 PetscCall(PetscFree(nv)); 66 } 67 vlink = vlink->next; 68 } 69 } 70 } 71 72 if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) { 73 PetscViewer aviewer; 74 PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, (PetscMPIInt *)&flg)); 75 if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval)); 76 } 77 if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) { 78 PetscViewer aviewer; 79 PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, (PetscMPIInt *)&flg)); 80 if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval)); 81 } 82 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL)); 83 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL)); 84 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL)); 85 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL)); 86 PetscFunctionReturn(PETSC_SUCCESS); 87 } 88 89 static PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer) 90 { 91 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 92 93 PetscFunctionBegin; 94 PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer)); 95 PetscFunctionReturn(PETSC_SUCCESS); 96 } 97 98 static PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer) 99 { 100 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 101 MPI_Comm comm; 102 PetscMPIInt rank, size; 103 FILE *fd = vascii->fd; 104 105 PetscFunctionBegin; 106 PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 107 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 108 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 109 PetscCallMPI(MPI_Comm_size(comm, &size)); 110 111 if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd)); 112 113 if (vascii->allowsynchronized) { 114 PetscMPIInt tag, i, j, n = 0, dummy = 0; 115 char *message; 116 MPI_Status status; 117 118 PetscCall(PetscCommDuplicate(comm, &comm, &tag)); 119 120 /* First processor waits for messages from all other processors */ 121 if (rank == 0) { 122 /* flush my own messages that I may have queued up */ 123 PrintfQueue next = vascii->petsc_printfqueuebase, previous; 124 for (i = 0; i < vascii->petsc_printfqueuelength; i++) { 125 if (!vascii->bviewer) { 126 PetscCall(PetscFPrintf(comm, fd, "%s", next->string)); 127 } else { 128 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string)); 129 } 130 previous = next; 131 next = next->next; 132 PetscCall(PetscFree(previous->string)); 133 PetscCall(PetscFree(previous)); 134 } 135 vascii->petsc_printfqueue = NULL; 136 vascii->petsc_printfqueuelength = 0; 137 for (i = 1; i < size; i++) { 138 /* to prevent a flood of messages to process zero, request each message separately */ 139 PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm)); 140 PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status)); 141 for (j = 0; j < n; j++) { 142 PetscMPIInt size = 0; 143 144 PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status)); 145 PetscCall(PetscMalloc1(size, &message)); 146 PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status)); 147 if (!vascii->bviewer) { 148 PetscCall(PetscFPrintf(comm, fd, "%s", message)); 149 } else { 150 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message)); 151 } 152 PetscCall(PetscFree(message)); 153 } 154 } 155 } else { /* other processors send queue to processor 0 */ 156 PrintfQueue next = vascii->petsc_printfqueuebase, previous; 157 158 PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status)); 159 PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm)); 160 for (i = 0; i < vascii->petsc_printfqueuelength; i++) { 161 PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm)); 162 PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm)); 163 previous = next; 164 next = next->next; 165 PetscCall(PetscFree(previous->string)); 166 PetscCall(PetscFree(previous)); 167 } 168 vascii->petsc_printfqueue = NULL; 169 vascii->petsc_printfqueuelength = 0; 170 } 171 PetscCall(PetscCommDestroy(&comm)); 172 } 173 PetscFunctionReturn(PETSC_SUCCESS); 174 } 175 176 /*@C 177 PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`. 178 179 Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer; No Fortran Support 180 181 Input Parameter: 182 . viewer - `PetscViewer` context, obtained from `PetscViewerASCIIOpen()` 183 184 Output Parameter: 185 . fd - file pointer 186 187 Level: intermediate 188 189 Note: 190 For the standard `PETSCVIEWERASCII` the value is valid only on MPI rank 0 of the viewer 191 192 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, 193 `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()` 194 @*/ 195 PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd) 196 { 197 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 198 199 PetscFunctionBegin; 200 PetscCheck(!vascii->fileunit, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot request file pointer for viewers that use Fortran files"); 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 /*@ 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 /*@ 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 /*@ 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 /*@ 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 petscviewerasciisetfileunit_ PETSCVIEWERASCIISETFILEUNIT 510 #define petscviewerasciiworldsetfileunit_ PETSCVIEWERASCIIWORLDSETFILEUNIT 511 #define petscfortranprinttounit_ PETSCFORTRANPRINTTOUNIT 512 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 513 #define petscviewerasciiopenwithfileunit_ petscviewerasciiopenwithfileunit 514 #define petscviewerasciisetfileunit_ petscviewerasciisetfileunit 515 #define petscviewerasciiworldsetfileunit_ petscviewerasciiworldsetfileunit 516 #define petscfortranprinttounit_ petscfortranprinttounit 517 #endif 518 519 #if defined(__cplusplus) 520 extern "C" void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T); 521 #else 522 extern void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T); 523 #endif 524 525 #define PETSCDEFAULTBUFFERSIZE 8 * 1024 526 527 static PetscInt PETSC_VIEWER_ASCII_WORLD_fileunit = 0; 528 529 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header 530 /*MC 531 PetscViewerASCIIWORLDSetFileUnit - sets `PETSC_VIEWER_STDOUT_WORLD` to write to a Fortran IO unit 532 533 Synopsis: 534 #include <petscviewer.h> 535 void PetscViewerASCIIWORLDSetFileUnit(PetscInt unit, PetscErrorCode ierr) 536 537 Input Parameter: 538 . unit - the unit number 539 540 Output Parameter: 541 . ierr - the error code 542 543 Level: intermediate 544 545 Notes: 546 Must be called before `PetscInitialize()` 547 548 This may not work currently with some viewers that (improperly) use the `fd` directly instead of `PetscViewerASCIIPrintf()` 549 550 With this option, for example, `-log_options` results will be saved to the Fortran file 551 552 Any process may call this but only the unit passed on the first process is used 553 554 Fortran Note: 555 Only for Fortran 556 557 Developer Note: 558 `PetscViewerASCIIWORLDSetFilename()` could be added in the future 559 560 .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIWORLDSetFileUnit()` 561 M*/ 562 PETSC_EXTERN void petscviewerasciiworldsetfileunit_(PetscInt *unit, PetscErrorCode *ierr) 563 { 564 PETSC_VIEWER_ASCII_WORLD_fileunit = *unit; 565 } 566 567 #include <petsc/private/fortranimpl.h> 568 569 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header 570 /*MC 571 PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` to write to a Fortran IO unit 572 573 Synopsis: 574 #include <petscviewer.h> 575 void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr) 576 577 Input Parameters: 578 + lab - the viewer 579 - unit - the unit number 580 581 Output Parameter: 582 . ierr - the error code 583 584 Level: intermediate 585 586 Note: 587 `PetscViewerDestroy()` does not close the unit for this `PetscViewer` 588 589 Fortran Notes: 590 Only for Fortran, use `PetscViewerASCIISetFILE()` for C 591 592 .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIWORLDSetFileUnit()` 593 M*/ 594 PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, PetscInt *unit, PetscErrorCode *ierr) 595 { 596 PetscViewer_ASCII *vascii; 597 PetscViewer v; 598 599 PetscPatchDefaultViewers_Fortran(lab, v); 600 vascii = (PetscViewer_ASCII *)v->data; 601 if (vascii->mode == FILE_MODE_READ) { 602 *ierr = PETSC_ERR_ARG_WRONGSTATE; 603 return; 604 } 605 vascii->fileunit = *unit; 606 } 607 608 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header 609 /*MC 610 PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit 611 612 Synopsis: 613 #include <petscviewer.h> 614 void PetscViewerASCIIOpenWithFileUnit(MPI_Comm comm, PetscInt unit, PetscViewer viewer, PetscErrorCode ierr) 615 616 Input Parameters: 617 + comm - the `MPI_Comm` to share the viewer 618 - unit - the unit number 619 620 Output Parameters: 621 + lab - the viewer 622 - ierr - the error code 623 624 Level: intermediate 625 626 Note: 627 `PetscViewerDestroy()` does not close the unit for this `PetscViewer` 628 629 Fortran Notes: 630 Only for Fortran, use `PetscViewerASCIIOpenWithFILE()` for C 631 632 .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()` 633 M*/ 634 PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Comm *comm, PetscInt *unit, PetscViewer *lab, PetscErrorCode *ierr) 635 { 636 *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab); 637 if (*ierr) return; 638 *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII); 639 if (*ierr) return; 640 *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE); 641 if (*ierr) return; 642 petscviewerasciisetfileunit_(lab, unit, ierr); 643 } 644 645 static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp) 646 { 647 PetscErrorCode ierr; 648 char str[PETSCDEFAULTBUFFERSIZE]; 649 size_t len; 650 651 PetscFunctionBegin; 652 PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp)); 653 PetscCall(PetscStrlen(str, &len)); 654 petscfortranprinttounit_(&unit, str, &ierr, (int)len); 655 PetscFunctionReturn(PETSC_SUCCESS); 656 } 657 658 static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[]) 659 { 660 PetscErrorCode ierr; 661 size_t len; 662 663 PetscFunctionBegin; 664 PetscCall(PetscStrlen(str, &len)); 665 petscfortranprinttounit_(&unit, str, &ierr, (int)len); 666 PetscFunctionReturn(PETSC_SUCCESS); 667 } 668 669 #else 670 671 /* these will never be used; but are needed to link with */ 672 static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp) 673 { 674 PetscFunctionBegin; 675 PetscFunctionReturn(PETSC_SUCCESS); 676 } 677 678 static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[]) 679 { 680 PetscFunctionBegin; 681 PetscFunctionReturn(PETSC_SUCCESS); 682 } 683 #endif 684 685 /*@ 686 PetscViewerASCIIGetStdout - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processes 687 in a communicator that prints to `stdout`. Error returning version of `PETSC_VIEWER_STDOUT_()` 688 689 Collective 690 691 Input Parameter: 692 . comm - the MPI communicator to share the `PetscViewer` 693 694 Output Parameter: 695 . viewer - the viewer 696 697 Level: beginner 698 699 Note: 700 Use `PetscViewerDestroy()` to destroy it 701 702 Developer Note: 703 This should be used in all PETSc source code instead of `PETSC_VIEWER_STDOUT_()` since it allows error checking 704 705 .seealso: [](sec_viewers), `PetscViewerASCIIGetStderr()`, `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`, 706 `PETSC_VIEWER_STDOUT_SELF` 707 @*/ 708 PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm, PetscViewer *viewer) 709 { 710 PetscBool flg; 711 MPI_Comm ncomm; 712 713 PetscFunctionBegin; 714 PetscAssertPointer(viewer, 2); 715 PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout)); 716 PetscCall(PetscCommDuplicate(comm, &ncomm, NULL)); 717 if (Petsc_Viewer_Stdout_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Stdout_keyval, NULL)); 718 PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, (PetscMPIInt *)&flg)); 719 if (!flg) { /* PetscViewer not yet created */ 720 #if defined(PETSC_USE_FORTRAN_BINDINGS) 721 PetscMPIInt size, gsize; 722 723 PetscCallMPI(MPI_Comm_size(comm, &size)); 724 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &gsize)); 725 if (size == gsize) { PetscCallMPI(MPI_Bcast(&PETSC_VIEWER_ASCII_WORLD_fileunit, 1, MPIU_INT, 0, comm)); } 726 if (PETSC_VIEWER_ASCII_WORLD_fileunit) { 727 PetscErrorCode ierr; 728 729 petscviewerasciiopenwithfileunit_(&ncomm, &PETSC_VIEWER_ASCII_WORLD_fileunit, viewer, &ierr); 730 } else 731 #endif 732 { 733 PetscCall(PetscViewerCreate(ncomm, viewer)); 734 PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII)); 735 PetscCall(PetscViewerFileSetName(*viewer, "stdout")); 736 } 737 PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer)); 738 PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer)); 739 } 740 PetscCall(PetscCommDestroy(&ncomm)); 741 PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout)); 742 PetscFunctionReturn(PETSC_SUCCESS); 743 } 744 745 /*@C 746 PetscViewerASCIIPrintf - Prints to a file, only from the first 747 processor in the `PetscViewer` of type `PETSCVIEWERASCII` 748 749 Not Collective, but only the first MPI rank in the viewer has any effect 750 751 Input Parameters: 752 + viewer - obtained with `PetscViewerASCIIOpen()` 753 - format - the usual printf() format string 754 755 Level: developer 756 757 Fortran Notes: 758 The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran. 759 That is, you can only pass a single character string from Fortran. 760 761 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 762 `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, 763 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()` 764 @*/ 765 PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...) 766 { 767 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 768 PetscMPIInt rank; 769 PetscInt tab = 0, intab = ascii->tab; 770 FILE *fd = ascii->fd; 771 PetscBool iascii; 772 773 PetscFunctionBegin; 774 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 775 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 776 PetscAssertPointer(format, 2); 777 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 778 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 779 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 780 if (rank) PetscFunctionReturn(PETSC_SUCCESS); 781 782 if (ascii->bviewer) { /* pass string up to parent viewer */ 783 char *string; 784 va_list Argp; 785 size_t fullLength; 786 787 PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string)); 788 for (; tab < ascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; } 789 va_start(Argp, format); 790 PetscCall(PetscVSNPrintf(string + 2 * intab, QUEUESTRINGSIZE - 2 * intab, format, &fullLength, Argp)); 791 va_end(Argp); 792 PetscCall(PetscViewerASCIISynchronizedPrintf(ascii->bviewer, "%s", string)); 793 PetscCall(PetscFree(string)); 794 } else { /* write directly to file */ 795 va_list Argp; 796 797 tab = intab; 798 while (tab--) { 799 if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, " ")); 800 else PetscCall(PetscFPrintfFortran(ascii->fileunit, " ")); 801 } 802 803 va_start(Argp, format); 804 if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp)); 805 else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp)); 806 va_end(Argp); 807 PetscCall(PetscFFlush(fd)); 808 } 809 PetscFunctionReturn(PETSC_SUCCESS); 810 } 811 812 /*@ 813 PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use. 814 815 Collective 816 817 Input Parameters: 818 + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY` 819 - name - the name of the file it should use 820 821 Level: advanced 822 823 Note: 824 This will have no effect on viewers that are not related to files 825 826 .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`, 827 `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()` 828 @*/ 829 PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[]) 830 { 831 char filename[PETSC_MAX_PATH_LEN]; 832 833 PetscFunctionBegin; 834 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 835 PetscAssertPointer(name, 2); 836 PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename))); 837 PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename)); 838 PetscFunctionReturn(PETSC_SUCCESS); 839 } 840 841 /*@C 842 PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using 843 844 Not Collective 845 846 Input Parameter: 847 . viewer - the `PetscViewer` 848 849 Output Parameter: 850 . name - the name of the file it is using 851 852 Level: advanced 853 854 Note: 855 This will have no effect on viewers that are not related to files 856 857 .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()` 858 @*/ 859 PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char *name[]) 860 { 861 PetscFunctionBegin; 862 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 863 PetscAssertPointer(name, 2); 864 PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name)); 865 PetscFunctionReturn(PETSC_SUCCESS); 866 } 867 868 static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name) 869 { 870 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 871 872 PetscFunctionBegin; 873 *name = vascii->filename; 874 PetscFunctionReturn(PETSC_SUCCESS); 875 } 876 877 #include <errno.h> 878 static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[]) 879 { 880 size_t len; 881 char fname[PETSC_MAX_PATH_LEN], *gz = NULL; 882 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 883 PetscBool isstderr, isstdout; 884 PetscMPIInt rank; 885 886 PetscFunctionBegin; 887 PetscCall(PetscViewerFileClose_ASCII(viewer)); 888 if (!name) PetscFunctionReturn(PETSC_SUCCESS); 889 PetscCall(PetscStrallocpy(name, &vascii->filename)); 890 891 /* Is this file to be compressed */ 892 vascii->storecompressed = PETSC_FALSE; 893 894 PetscCall(PetscStrstr(vascii->filename, ".gz", &gz)); 895 if (gz) { 896 PetscCall(PetscStrlen(gz, &len)); 897 if (len == 3) { 898 PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first"); 899 *gz = 0; 900 vascii->storecompressed = PETSC_TRUE; 901 } 902 } 903 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 904 if (rank == 0) { 905 PetscCall(PetscStrcmp(name, "stderr", &isstderr)); 906 PetscCall(PetscStrcmp(name, "stdout", &isstdout)); 907 /* empty filename means stdout */ 908 if (name[0] == 0) isstdout = PETSC_TRUE; 909 if (isstderr) vascii->fd = PETSC_STDERR; 910 else if (isstdout) vascii->fd = PETSC_STDOUT; 911 else { 912 PetscCall(PetscFixFilename(name, fname)); 913 switch (vascii->mode) { 914 case FILE_MODE_READ: 915 vascii->fd = fopen(fname, "r"); 916 break; 917 case FILE_MODE_WRITE: 918 vascii->fd = fopen(fname, "w"); 919 break; 920 case FILE_MODE_APPEND: 921 vascii->fd = fopen(fname, "a"); 922 break; 923 case FILE_MODE_UPDATE: 924 vascii->fd = fopen(fname, "r+"); 925 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 926 break; 927 case FILE_MODE_APPEND_UPDATE: 928 /* I really want a file which is opened at the end for updating, 929 not a+, which opens at the beginning, but makes writes at the end. 930 */ 931 vascii->fd = fopen(fname, "r+"); 932 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 933 else { 934 int ret = fseek(vascii->fd, 0, SEEK_END); 935 PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret); 936 } 937 break; 938 default: 939 SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]); 940 } 941 PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno)); 942 } 943 } 944 PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name)); 945 PetscFunctionReturn(PETSC_SUCCESS); 946 } 947 948 static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer) 949 { 950 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii; 951 952 PetscFunctionBegin; 953 PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored"); 954 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 955 /* 956 The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work 957 because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed 958 (since the count never gets to zero) in some examples this displays information that otherwise would be lost 959 960 This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example, 961 PCView_GASM(). 962 */ 963 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 964 PetscCall(PetscViewerFlush(viewer)); 965 PetscCall(PetscViewerCreate(subcomm, outviewer)); 966 PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII)); 967 PetscCall(PetscViewerASCIIPushSynchronized(*outviewer)); 968 ovascii = (PetscViewer_ASCII *)(*outviewer)->data; 969 ovascii->fd = vascii->fd; 970 ovascii->closefile = PETSC_FALSE; 971 972 vascii->sviewer = *outviewer; 973 (*outviewer)->format = viewer->format; 974 ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer; 975 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer; 976 PetscFunctionReturn(PETSC_SUCCESS); 977 } 978 979 static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer) 980 { 981 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 982 983 PetscFunctionBegin; 984 PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer"); 985 PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer"); 986 987 PetscCall(PetscViewerASCIIPopSynchronized(*outviewer)); 988 ascii->sviewer = NULL; 989 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII; 990 PetscCall(PetscViewerDestroy(outviewer)); 991 PetscCall(PetscViewerFlush(viewer)); 992 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 993 PetscFunctionReturn(PETSC_SUCCESS); 994 } 995 996 static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer) 997 { 998 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data; 999 1000 PetscFunctionBegin; 1001 if (ascii->fileunit) PetscCall(PetscViewerASCIIPrintf(viewer, "Fortran FILE UNIT: %" PetscInt_FMT "\n", ascii->fileunit)); 1002 else if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename)); 1003 PetscFunctionReturn(PETSC_SUCCESS); 1004 } 1005 1006 /*MC 1007 PETSCVIEWERASCII - A viewer that prints to `stdout`, `stderr`, or an ASCII file 1008 1009 Level: beginner 1010 1011 .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, 1012 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, 1013 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 1014 M*/ 1015 PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer) 1016 { 1017 PetscViewer_ASCII *vascii; 1018 1019 PetscFunctionBegin; 1020 PetscCall(PetscNew(&vascii)); 1021 viewer->data = (void *)vascii; 1022 1023 viewer->ops->destroy = PetscViewerDestroy_ASCII; 1024 viewer->ops->flush = PetscViewerFlush_ASCII; 1025 viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII; 1026 viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII; 1027 viewer->ops->view = PetscViewerView_ASCII; 1028 viewer->ops->read = PetscViewerASCIIRead; 1029 1030 /* defaults to stdout unless set with PetscViewerFileSetName() */ 1031 vascii->fd = PETSC_STDOUT; 1032 vascii->mode = FILE_MODE_WRITE; 1033 vascii->bviewer = NULL; 1034 vascii->subviewer = NULL; 1035 vascii->sviewer = NULL; 1036 vascii->tab = 0; 1037 vascii->tab_store = 0; 1038 vascii->filename = NULL; 1039 vascii->closefile = PETSC_TRUE; 1040 1041 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII)); 1042 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII)); 1043 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII)); 1044 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII)); 1045 PetscFunctionReturn(PETSC_SUCCESS); 1046 } 1047 1048 /*@C 1049 PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from 1050 several processors. Output of the first processor is followed by that of the 1051 second, etc. 1052 1053 Not Collective, must call collective `PetscViewerFlush()` to get the results flushed 1054 1055 Input Parameters: 1056 + viewer - the `PETSCVIEWERASCII` `PetscViewer` 1057 - format - the usual printf() format string 1058 1059 Level: intermediate 1060 1061 Notes: 1062 You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called. 1063 Then you can do multiple independent calls to this routine. 1064 1065 The actual synchronized print is then done using `PetscViewerFlush()`. 1066 `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output 1067 to conclude the "synchronized session". 1068 1069 So the typical calling sequence looks like 1070 .vb 1071 PetscViewerASCIIPushSynchronized(viewer); 1072 PetscViewerASCIISynchronizedPrintf(viewer, ...); 1073 PetscViewerASCIISynchronizedPrintf(viewer, ...); 1074 ... 1075 PetscViewerFlush(viewer); 1076 PetscViewerASCIISynchronizedPrintf(viewer, ...); 1077 PetscViewerASCIISynchronizedPrintf(viewer, ...); 1078 ... 1079 PetscViewerFlush(viewer); 1080 PetscViewerASCIIPopSynchronized(viewer); 1081 .ve 1082 1083 Fortran Notes: 1084 Can only print a single character* string 1085 1086 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 1087 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 1088 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 1089 @*/ 1090 PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...) 1091 { 1092 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 1093 PetscMPIInt rank; 1094 PetscInt tab = 0; 1095 MPI_Comm comm; 1096 PetscBool iascii; 1097 1098 PetscFunctionBegin; 1099 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 1100 PetscAssertPointer(format, 2); 1101 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 1102 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 1103 PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call"); 1104 1105 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 1106 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1107 1108 if (vascii->bviewer) { 1109 char *string; 1110 va_list Argp; 1111 size_t fullLength; 1112 1113 PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string)); 1114 for (; tab < vascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; } 1115 va_start(Argp, format); 1116 PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp)); 1117 va_end(Argp); 1118 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string)); 1119 PetscCall(PetscFree(string)); 1120 } else if (rank == 0) { /* First processor prints immediately to fp */ 1121 va_list Argp; 1122 FILE *fp = vascii->fd; 1123 1124 tab = vascii->tab; 1125 while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " ")); 1126 1127 va_start(Argp, format); 1128 PetscCall((*PetscVFPrintf)(fp, format, Argp)); 1129 va_end(Argp); 1130 PetscCall(PetscFFlush(fp)); 1131 if (petsc_history) { 1132 va_start(Argp, format); 1133 PetscCall((*PetscVFPrintf)(petsc_history, format, Argp)); 1134 va_end(Argp); 1135 PetscCall(PetscFFlush(petsc_history)); 1136 } 1137 va_end(Argp); 1138 } else { /* other processors add to queue */ 1139 char *string; 1140 va_list Argp; 1141 size_t fullLength; 1142 PrintfQueue next; 1143 1144 PetscCall(PetscNew(&next)); 1145 if (vascii->petsc_printfqueue) { 1146 vascii->petsc_printfqueue->next = next; 1147 vascii->petsc_printfqueue = next; 1148 } else { 1149 vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next; 1150 } 1151 vascii->petsc_printfqueuelength++; 1152 next->size = QUEUESTRINGSIZE; 1153 PetscCall(PetscCalloc1(next->size, &next->string)); 1154 string = next->string; 1155 1156 tab = vascii->tab; 1157 tab *= 2; 1158 while (tab--) *string++ = ' '; 1159 va_start(Argp, format); 1160 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp)); 1161 va_end(Argp); 1162 if (fullLength > (size_t)(next->size - 2 * vascii->tab)) { 1163 PetscCall(PetscFree(next->string)); 1164 next->size = fullLength + 2 * vascii->tab; 1165 PetscCall(PetscCalloc1(next->size, &next->string)); 1166 string = next->string; 1167 tab = 2 * vascii->tab; 1168 while (tab--) *string++ = ' '; 1169 va_start(Argp, format); 1170 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp)); 1171 va_end(Argp); 1172 } 1173 } 1174 PetscFunctionReturn(PETSC_SUCCESS); 1175 } 1176 1177 /*@C 1178 PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file 1179 1180 Only MPI rank 0 in the `PetscViewer` may call this 1181 1182 Input Parameters: 1183 + viewer - the `PETSCVIEWERASCII` viewer 1184 . data - location to write the data, treated as an array of type indicated by `datatype` 1185 . num - number of items of data to read 1186 - dtype - type of data to read 1187 1188 Output Parameter: 1189 . count - number of items of data actually read, or `NULL` 1190 1191 Level: beginner 1192 1193 .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()` 1194 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 1195 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 1196 @*/ 1197 PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype) 1198 { 1199 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 1200 FILE *fd = vascii->fd; 1201 PetscInt i; 1202 int ret = 0; 1203 PetscMPIInt rank; 1204 1205 PetscFunctionBegin; 1206 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 1207 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 1208 PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer"); 1209 for (i = 0; i < num; i++) { 1210 if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i])); 1211 else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i])); 1212 else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i])); 1213 else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i])); 1214 else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i])); 1215 else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i])); 1216 else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i])); 1217 else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i])); 1218 #if defined(PETSC_USE_REAL___FLOAT128) 1219 else if (dtype == PETSC___FLOAT128) { 1220 double tmp; 1221 ret = fscanf(fd, "%lg", &tmp); 1222 ((__float128 *)data)[i] = tmp; 1223 } 1224 #endif 1225 else 1226 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype); 1227 PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype); 1228 if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */ 1229 } 1230 if (count) *count = i; 1231 else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num); 1232 PetscFunctionReturn(PETSC_SUCCESS); 1233 } 1234