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 /* ----------------------------------------------------------------------*/ 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 PetscCheck(!vascii->fileunit, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot request file pointer for viewers that use Fortran files"); 202 *fd = vascii->fd; 203 PetscFunctionReturn(PETSC_SUCCESS); 204 } 205 206 static PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode) 207 { 208 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 209 210 PetscFunctionBegin; 211 *mode = vascii->mode; 212 PetscFunctionReturn(PETSC_SUCCESS); 213 } 214 215 static PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode) 216 { 217 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 218 219 PetscFunctionBegin; 220 vascii->mode = mode; 221 PetscFunctionReturn(PETSC_SUCCESS); 222 } 223 224 /* 225 If petsc_history is on, then all Petsc*Printf() results are saved 226 if the appropriate (usually .petschistory) file. 227 */ 228 PETSC_INTERN FILE *petsc_history; 229 230 /*@ 231 PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times before printing 232 233 Not Collective, but only first processor in set has any effect; No Fortran Support 234 235 Input Parameters: 236 + viewer - obtained with `PetscViewerASCIIOpen()` 237 - tabs - number of tabs 238 239 Level: developer 240 241 Note: 242 `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage 243 244 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 245 `PetscViewerASCIIGetTab()`, 246 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 247 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, 248 `PetscViewerASCIIPushTab()` 249 @*/ 250 PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs) 251 { 252 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 253 PetscBool iascii; 254 255 PetscFunctionBegin; 256 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 257 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 258 if (iascii) ascii->tab = tabs; 259 PetscFunctionReturn(PETSC_SUCCESS); 260 } 261 262 /*@ 263 PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`. 264 265 Not Collective, meaningful on first processor only; No Fortran Support 266 267 Input Parameter: 268 . viewer - obtained with `PetscViewerASCIIOpen()` 269 270 Output Parameter: 271 . tabs - number of tabs 272 273 Level: developer 274 275 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 276 `PetscViewerASCIISetTab()`, 277 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 278 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()` 279 @*/ 280 PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs) 281 { 282 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 283 PetscBool iascii; 284 285 PetscFunctionBegin; 286 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 287 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 288 if (iascii && tabs) *tabs = ascii->tab; 289 PetscFunctionReturn(PETSC_SUCCESS); 290 } 291 292 /*@ 293 PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing 294 295 Not Collective, but only first processor in set has any effect; No Fortran Support 296 297 Input Parameters: 298 + viewer - obtained with `PetscViewerASCIIOpen()` 299 - tabs - number of tabs 300 301 Level: developer 302 303 Note: 304 `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage 305 306 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 307 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 308 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()` 309 @*/ 310 PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs) 311 { 312 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 313 PetscBool iascii; 314 315 PetscFunctionBegin; 316 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 317 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 318 if (iascii) ascii->tab += tabs; 319 PetscFunctionReturn(PETSC_SUCCESS); 320 } 321 322 /*@ 323 PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing 324 325 Not Collective, but only first processor in set has any effect; No Fortran Support 326 327 Input Parameters: 328 + viewer - obtained with `PetscViewerASCIIOpen()` 329 - tabs - number of tabs 330 331 Level: developer 332 333 Note: 334 `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage 335 336 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 337 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 338 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, 339 `PetscViewerASCIIPushTab()` 340 @*/ 341 PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs) 342 { 343 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 344 PetscBool iascii; 345 346 PetscFunctionBegin; 347 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 348 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 349 if (iascii) ascii->tab -= tabs; 350 PetscFunctionReturn(PETSC_SUCCESS); 351 } 352 353 /*@ 354 PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer 355 356 Collective 357 358 Input Parameter: 359 . viewer - obtained with `PetscViewerASCIIOpen()` 360 361 Level: intermediate 362 363 Note: 364 See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly. 365 366 .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 367 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 368 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 369 @*/ 370 PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer) 371 { 372 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 373 PetscBool iascii; 374 375 PetscFunctionBegin; 376 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 377 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 378 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 379 if (iascii) ascii->allowsynchronized++; 380 PetscFunctionReturn(PETSC_SUCCESS); 381 } 382 383 /*@ 384 PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer 385 386 Collective 387 388 Input Parameter: 389 . viewer - obtained with `PetscViewerASCIIOpen()` 390 391 Level: intermediate 392 393 Note: 394 See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly. 395 396 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, 397 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 398 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 399 @*/ 400 PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer) 401 { 402 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 403 PetscBool iascii; 404 405 PetscFunctionBegin; 406 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 407 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 408 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 409 if (iascii) { 410 ascii->allowsynchronized--; 411 PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()"); 412 } 413 PetscFunctionReturn(PETSC_SUCCESS); 414 } 415 416 /*@ 417 PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()` 418 lines are tabbed. 419 420 Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support 421 422 Input Parameter: 423 . viewer - obtained with `PetscViewerASCIIOpen()` 424 425 Level: developer 426 427 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 428 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 429 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()` 430 @*/ 431 PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer) 432 { 433 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 434 PetscBool iascii; 435 436 PetscFunctionBegin; 437 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 438 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 439 if (iascii) ascii->tab++; 440 PetscFunctionReturn(PETSC_SUCCESS); 441 } 442 443 /*@ 444 PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by 445 `PetscViewerASCIIPushTab()` 446 447 Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support 448 449 Input Parameter: 450 . viewer - obtained with `PetscViewerASCIIOpen()` 451 452 Level: developer 453 454 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 455 `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 456 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()` 457 @*/ 458 PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer) 459 { 460 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 461 PetscBool iascii; 462 463 PetscFunctionBegin; 464 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 465 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 466 if (iascii) { 467 PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed"); 468 ascii->tab--; 469 } 470 PetscFunctionReturn(PETSC_SUCCESS); 471 } 472 473 /*@ 474 PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer` 475 476 Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support 477 478 Input Parameters: 479 + viewer - obtained with `PetscViewerASCIIOpen()` 480 - flg - `PETSC_TRUE` or `PETSC_FALSE` 481 482 Level: developer 483 484 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, 485 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`, 486 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()` 487 @*/ 488 PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg) 489 { 490 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 491 PetscBool iascii; 492 493 PetscFunctionBegin; 494 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 495 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 496 if (iascii) { 497 if (flg) ascii->tab = ascii->tab_store; 498 else { 499 ascii->tab_store = ascii->tab; 500 ascii->tab = 0; 501 } 502 } 503 PetscFunctionReturn(PETSC_SUCCESS); 504 } 505 506 #if defined(PETSC_USE_FORTRAN_BINDINGS) 507 508 #if defined(PETSC_HAVE_FORTRAN_CAPS) 509 #define petscviewerasciiopenwithfileunit_ PETSCVIEWERASCIIOPENWITHFILEUNIT 510 #define petscviewerasciisetfileunit_ PETSCVIEWERASCIISETFILEUNIT 511 #define petscviewerasciiworldsetfileunit_ PETSCVIEWERASCIIWORLDSETFILEUNIT 512 #define petscfortranprinttounit_ PETSCFORTRANPRINTTOUNIT 513 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 514 #define petscviewerasciiopenwithfileunit_ petscviewerasciiopenwithfileunit 515 #define petscviewerasciisetfileunit_ petscviewerasciisetfileunit 516 #define petscviewerasciiworldsetfileunit_ petscviewerasciiworldsetfileunit 517 #define petscfortranprinttounit_ petscfortranprinttounit 518 #endif 519 520 #if defined(__cplusplus) 521 extern "C" void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T); 522 #else 523 extern void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T); 524 #endif 525 526 #define PETSCDEFAULTBUFFERSIZE 8 * 1024 527 528 static PetscInt PETSC_VIEWER_ASCII_WORLD_fileunit = 0; 529 530 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header 531 /*MC 532 PetscViewerASCIIWORLDSetFileUnit - sets `PETSC_VIEWER_STDOUT_WORLD` to write to a Fortran IO unit 533 534 Synopsis: 535 #include <petscviewer.h> 536 void PetscViewerASCIIWORLDSetFileUnit(PetscInt unit, PetscErrorCode ierr) 537 538 Input Parameter: 539 . unit - the unit number 540 541 Output Parameter: 542 . ierr - the error code 543 544 Level: intermediate 545 546 Notes: 547 Must be called before `PetscInitialize()` 548 549 This may not work currently with some viewers that (improperly) use the `fd` directly instead of `PetscViewerASCIIPrintf()` 550 551 With this option, for example, `-log_options` results will be saved to the Fortran file 552 553 Any process may call this but only the unit passed on the first process is used 554 555 Fortran Note: 556 Only for Fortran 557 558 Developer Note: 559 `PetscViewerASCIIWORLDSetFilename()` could be added in the future 560 561 .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIWORLDSetFileUnit()` 562 M*/ 563 PETSC_EXTERN void petscviewerasciiworldsetfileunit_(PetscInt *unit, PetscErrorCode *ierr) 564 { 565 PETSC_VIEWER_ASCII_WORLD_fileunit = *unit; 566 } 567 568 #include <petsc/private/fortranimpl.h> 569 570 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header 571 /*MC 572 PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` to write to a Fortran IO unit 573 574 Synopsis: 575 #include <petscviewer.h> 576 void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr) 577 578 Input Parameters: 579 + lab - the viewer 580 - unit - the unit number 581 582 Output Parameter: 583 . ierr - the error code 584 585 Level: intermediate 586 587 Note: 588 `PetscViewerDestroy()` does not close the unit for this `PetscViewer` 589 590 Fortran Notes: 591 Only for Fortran, use `PetscViewerASCIISetFILE()` for C 592 593 .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIWORLDSetFileUnit()` 594 M*/ 595 PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, PetscInt *unit, PetscErrorCode *ierr) 596 { 597 PetscViewer_ASCII *vascii; 598 PetscViewer v; 599 600 PetscPatchDefaultViewers_Fortran(lab, v); 601 vascii = (PetscViewer_ASCII *)v->data; 602 if (vascii->mode == FILE_MODE_READ) { 603 *ierr = PETSC_ERR_ARG_WRONGSTATE; 604 return; 605 } 606 vascii->fileunit = *unit; 607 } 608 609 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header 610 /*MC 611 PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit 612 613 Synopsis: 614 #include <petscviewer.h> 615 void PetscViewerASCIIOpenWithFileUnit(MPI_Comm comm, PetscInt unit, PetscViewer viewer, PetscErrorCode ierr) 616 617 Input Parameters: 618 + comm - the `MPI_Comm` to share the viewer 619 - unit - the unit number 620 621 Output Parameters: 622 + lab - the viewer 623 - ierr - the error code 624 625 Level: intermediate 626 627 Note: 628 `PetscViewerDestroy()` does not close the unit for this `PetscViewer` 629 630 Fortran Notes: 631 Only for Fortran, use `PetscViewerASCIIOpenWithFILE()` for C 632 633 .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()` 634 M*/ 635 PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Comm *comm, PetscInt *unit, PetscViewer *lab, PetscErrorCode *ierr) 636 { 637 *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab); 638 if (*ierr) return; 639 *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII); 640 if (*ierr) return; 641 *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE); 642 if (*ierr) return; 643 petscviewerasciisetfileunit_(lab, unit, ierr); 644 } 645 646 static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp) 647 { 648 PetscErrorCode ierr; 649 char str[PETSCDEFAULTBUFFERSIZE]; 650 size_t len; 651 652 PetscFunctionBegin; 653 PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp)); 654 PetscCall(PetscStrlen(str, &len)); 655 petscfortranprinttounit_(&unit, str, &ierr, (int)len); 656 PetscFunctionReturn(PETSC_SUCCESS); 657 } 658 659 static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[]) 660 { 661 PetscErrorCode ierr; 662 size_t len; 663 664 PetscFunctionBegin; 665 PetscCall(PetscStrlen(str, &len)); 666 petscfortranprinttounit_(&unit, str, &ierr, (int)len); 667 PetscFunctionReturn(PETSC_SUCCESS); 668 } 669 670 #else 671 672 /* these will never be used; but are needed to link with */ 673 static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp) 674 { 675 PetscFunctionBegin; 676 PetscFunctionReturn(PETSC_SUCCESS); 677 } 678 679 static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[]) 680 { 681 PetscFunctionBegin; 682 PetscFunctionReturn(PETSC_SUCCESS); 683 } 684 #endif 685 686 /*@ 687 PetscViewerASCIIGetStdout - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processes 688 in a communicator. Error returning version of `PETSC_VIEWER_STDOUT_()` 689 690 Collective 691 692 Input Parameter: 693 . comm - the MPI communicator to share the `PetscViewer` 694 695 Output Parameter: 696 . viewer - the viewer 697 698 Level: beginner 699 700 Note: 701 This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it 702 703 Developer Note: 704 This should be used in all PETSc source code instead of `PETSC_VIEWER_STDOUT_()` since it allows error checking 705 706 .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`, 707 `PETSC_VIEWER_STDOUT_SELF` 708 @*/ 709 PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm, PetscViewer *viewer) 710 { 711 PetscBool flg; 712 MPI_Comm ncomm; 713 714 PetscFunctionBegin; 715 PetscAssertPointer(viewer, 2); 716 PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout)); 717 PetscCall(PetscCommDuplicate(comm, &ncomm, NULL)); 718 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)); 719 PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, (PetscMPIInt *)&flg)); 720 if (!flg) { /* PetscViewer not yet created */ 721 #if defined(PETSC_USE_FORTRAN_BINDINGS) 722 PetscMPIInt size, gsize; 723 724 PetscCallMPI(MPI_Comm_size(comm, &size)); 725 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &gsize)); 726 if (size == gsize) { PetscCallMPI(MPI_Bcast(&PETSC_VIEWER_ASCII_WORLD_fileunit, 1, MPIU_INT, 0, comm)); } 727 if (PETSC_VIEWER_ASCII_WORLD_fileunit) { 728 PetscErrorCode ierr; 729 730 petscviewerasciiopenwithfileunit_(&ncomm, &PETSC_VIEWER_ASCII_WORLD_fileunit, viewer, &ierr); 731 } else 732 #endif 733 PetscCall(PetscViewerASCIIOpen(ncomm, "stdout", viewer)); 734 ((PetscObject)*viewer)->persistent = PETSC_TRUE; 735 PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer)); 736 PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer)); 737 } 738 PetscCall(PetscCommDestroy(&ncomm)); 739 PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout)); 740 PetscFunctionReturn(PETSC_SUCCESS); 741 } 742 743 /*@C 744 PetscViewerASCIIPrintf - Prints to a file, only from the first 745 processor in the `PetscViewer` of type `PETSCVIEWERASCII` 746 747 Not Collective, but only the first MPI rank in the viewer has any effect 748 749 Input Parameters: 750 + viewer - obtained with `PetscViewerASCIIOpen()` 751 - format - the usual printf() format string 752 753 Level: developer 754 755 Fortran Notes: 756 The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran. 757 That is, you can only pass a single character string from Fortran. 758 759 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 760 `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, 761 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()` 762 @*/ 763 PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...) 764 { 765 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 766 PetscMPIInt rank; 767 PetscInt tab = 0, intab = ascii->tab; 768 FILE *fd = ascii->fd; 769 PetscBool iascii; 770 771 PetscFunctionBegin; 772 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 773 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 774 PetscAssertPointer(format, 2); 775 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 776 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 777 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 778 if (rank) PetscFunctionReturn(PETSC_SUCCESS); 779 780 if (ascii->bviewer) { /* pass string up to parent viewer */ 781 char *string; 782 va_list Argp; 783 size_t fullLength; 784 785 PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string)); 786 for (; tab < ascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; } 787 va_start(Argp, format); 788 PetscCall(PetscVSNPrintf(string + 2 * intab, QUEUESTRINGSIZE - 2 * intab, format, &fullLength, Argp)); 789 va_end(Argp); 790 PetscCall(PetscViewerASCIISynchronizedPrintf(ascii->bviewer, "%s", string)); 791 PetscCall(PetscFree(string)); 792 } else { /* write directly to file */ 793 va_list Argp; 794 795 tab = intab; 796 while (tab--) { 797 if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, " ")); 798 else PetscCall(PetscFPrintfFortran(ascii->fileunit, " ")); 799 } 800 801 va_start(Argp, format); 802 if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp)); 803 else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp)); 804 va_end(Argp); 805 PetscCall(PetscFFlush(fd)); 806 } 807 PetscFunctionReturn(PETSC_SUCCESS); 808 } 809 810 /*@ 811 PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use. 812 813 Collective 814 815 Input Parameters: 816 + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY` 817 - name - the name of the file it should use 818 819 Level: advanced 820 821 Note: 822 This will have no effect on viewers that are not related to files 823 824 .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`, 825 `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()` 826 @*/ 827 PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[]) 828 { 829 char filename[PETSC_MAX_PATH_LEN]; 830 831 PetscFunctionBegin; 832 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 833 PetscAssertPointer(name, 2); 834 PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename))); 835 PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename)); 836 PetscFunctionReturn(PETSC_SUCCESS); 837 } 838 839 /*@C 840 PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using 841 842 Not Collective 843 844 Input Parameter: 845 . viewer - the `PetscViewer` 846 847 Output Parameter: 848 . name - the name of the file it is using 849 850 Level: advanced 851 852 Note: 853 This will have no effect on viewers that are not related to files 854 855 .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()` 856 @*/ 857 PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char *name[]) 858 { 859 PetscFunctionBegin; 860 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 861 PetscAssertPointer(name, 2); 862 PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name)); 863 PetscFunctionReturn(PETSC_SUCCESS); 864 } 865 866 static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name) 867 { 868 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 869 870 PetscFunctionBegin; 871 *name = vascii->filename; 872 PetscFunctionReturn(PETSC_SUCCESS); 873 } 874 875 #include <errno.h> 876 static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[]) 877 { 878 size_t len; 879 char fname[PETSC_MAX_PATH_LEN], *gz = NULL; 880 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 881 PetscBool isstderr, isstdout; 882 PetscMPIInt rank; 883 884 PetscFunctionBegin; 885 PetscCall(PetscViewerFileClose_ASCII(viewer)); 886 if (!name) PetscFunctionReturn(PETSC_SUCCESS); 887 PetscCall(PetscStrallocpy(name, &vascii->filename)); 888 889 /* Is this file to be compressed */ 890 vascii->storecompressed = PETSC_FALSE; 891 892 PetscCall(PetscStrstr(vascii->filename, ".gz", &gz)); 893 if (gz) { 894 PetscCall(PetscStrlen(gz, &len)); 895 if (len == 3) { 896 PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first"); 897 *gz = 0; 898 vascii->storecompressed = PETSC_TRUE; 899 } 900 } 901 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 902 if (rank == 0) { 903 PetscCall(PetscStrcmp(name, "stderr", &isstderr)); 904 PetscCall(PetscStrcmp(name, "stdout", &isstdout)); 905 /* empty filename means stdout */ 906 if (name[0] == 0) isstdout = PETSC_TRUE; 907 if (isstderr) vascii->fd = PETSC_STDERR; 908 else if (isstdout) vascii->fd = PETSC_STDOUT; 909 else { 910 PetscCall(PetscFixFilename(name, fname)); 911 switch (vascii->mode) { 912 case FILE_MODE_READ: 913 vascii->fd = fopen(fname, "r"); 914 break; 915 case FILE_MODE_WRITE: 916 vascii->fd = fopen(fname, "w"); 917 break; 918 case FILE_MODE_APPEND: 919 vascii->fd = fopen(fname, "a"); 920 break; 921 case FILE_MODE_UPDATE: 922 vascii->fd = fopen(fname, "r+"); 923 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 924 break; 925 case FILE_MODE_APPEND_UPDATE: 926 /* I really want a file which is opened at the end for updating, 927 not a+, which opens at the beginning, but makes writes at the end. 928 */ 929 vascii->fd = fopen(fname, "r+"); 930 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 931 else { 932 int ret = fseek(vascii->fd, 0, SEEK_END); 933 PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret); 934 } 935 break; 936 default: 937 SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]); 938 } 939 PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno)); 940 } 941 } 942 PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name)); 943 PetscFunctionReturn(PETSC_SUCCESS); 944 } 945 946 static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer) 947 { 948 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii; 949 950 PetscFunctionBegin; 951 PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored"); 952 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 953 /* 954 The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work 955 because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed 956 (since the count never gets to zero) in some examples this displays information that otherwise would be lost 957 958 This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example, 959 PCView_GASM(). 960 */ 961 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 962 PetscCall(PetscViewerFlush(viewer)); 963 PetscCall(PetscViewerCreate(subcomm, outviewer)); 964 PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII)); 965 PetscCall(PetscViewerASCIIPushSynchronized(*outviewer)); 966 ovascii = (PetscViewer_ASCII *)(*outviewer)->data; 967 ovascii->fd = vascii->fd; 968 ovascii->closefile = PETSC_FALSE; 969 970 vascii->sviewer = *outviewer; 971 (*outviewer)->format = viewer->format; 972 ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer; 973 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer; 974 PetscFunctionReturn(PETSC_SUCCESS); 975 } 976 977 static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer) 978 { 979 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 980 981 PetscFunctionBegin; 982 PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer"); 983 PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer"); 984 985 PetscCall(PetscViewerASCIIPopSynchronized(*outviewer)); 986 ascii->sviewer = NULL; 987 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII; 988 PetscCall(PetscViewerDestroy(outviewer)); 989 PetscCall(PetscViewerFlush(viewer)); 990 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 991 PetscFunctionReturn(PETSC_SUCCESS); 992 } 993 994 static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer) 995 { 996 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data; 997 998 PetscFunctionBegin; 999 if (ascii->fileunit) PetscCall(PetscViewerASCIIPrintf(viewer, "Fortran FILE UNIT: %" PetscInt_FMT "\n", ascii->fileunit)); 1000 else if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename)); 1001 PetscFunctionReturn(PETSC_SUCCESS); 1002 } 1003 1004 /*MC 1005 PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file 1006 1007 Level: beginner 1008 1009 .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, 1010 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, 1011 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 1012 M*/ 1013 PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer) 1014 { 1015 PetscViewer_ASCII *vascii; 1016 1017 PetscFunctionBegin; 1018 PetscCall(PetscNew(&vascii)); 1019 viewer->data = (void *)vascii; 1020 1021 viewer->ops->destroy = PetscViewerDestroy_ASCII; 1022 viewer->ops->flush = PetscViewerFlush_ASCII; 1023 viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII; 1024 viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII; 1025 viewer->ops->view = PetscViewerView_ASCII; 1026 viewer->ops->read = PetscViewerASCIIRead; 1027 1028 /* defaults to stdout unless set with PetscViewerFileSetName() */ 1029 vascii->fd = PETSC_STDOUT; 1030 vascii->mode = FILE_MODE_WRITE; 1031 vascii->bviewer = NULL; 1032 vascii->subviewer = NULL; 1033 vascii->sviewer = NULL; 1034 vascii->tab = 0; 1035 vascii->tab_store = 0; 1036 vascii->filename = NULL; 1037 vascii->closefile = PETSC_TRUE; 1038 1039 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII)); 1040 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII)); 1041 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII)); 1042 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII)); 1043 PetscFunctionReturn(PETSC_SUCCESS); 1044 } 1045 1046 /*@C 1047 PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from 1048 several processors. Output of the first processor is followed by that of the 1049 second, etc. 1050 1051 Not Collective, must call collective `PetscViewerFlush()` to get the results flushed 1052 1053 Input Parameters: 1054 + viewer - the `PETSCVIEWERASCII` `PetscViewer` 1055 - format - the usual printf() format string 1056 1057 Level: intermediate 1058 1059 Notes: 1060 You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called. 1061 Then you can do multiple independent calls to this routine. 1062 1063 The actual synchronized print is then done using `PetscViewerFlush()`. 1064 `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output 1065 to conclude the "synchronized session". 1066 1067 So the typical calling sequence looks like 1068 .vb 1069 PetscViewerASCIIPushSynchronized(viewer); 1070 PetscViewerASCIISynchronizedPrintf(viewer, ...); 1071 PetscViewerASCIISynchronizedPrintf(viewer, ...); 1072 ... 1073 PetscViewerFlush(viewer); 1074 PetscViewerASCIISynchronizedPrintf(viewer, ...); 1075 PetscViewerASCIISynchronizedPrintf(viewer, ...); 1076 ... 1077 PetscViewerFlush(viewer); 1078 PetscViewerASCIIPopSynchronized(viewer); 1079 .ve 1080 1081 Fortran Notes: 1082 Can only print a single character* string 1083 1084 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 1085 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 1086 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 1087 @*/ 1088 PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...) 1089 { 1090 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 1091 PetscMPIInt rank; 1092 PetscInt tab = 0; 1093 MPI_Comm comm; 1094 PetscBool iascii; 1095 1096 PetscFunctionBegin; 1097 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 1098 PetscAssertPointer(format, 2); 1099 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 1100 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 1101 PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call"); 1102 1103 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 1104 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1105 1106 if (vascii->bviewer) { 1107 char *string; 1108 va_list Argp; 1109 size_t fullLength; 1110 1111 PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string)); 1112 for (; tab < vascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; } 1113 va_start(Argp, format); 1114 PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp)); 1115 va_end(Argp); 1116 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string)); 1117 PetscCall(PetscFree(string)); 1118 } else if (rank == 0) { /* First processor prints immediately to fp */ 1119 va_list Argp; 1120 FILE *fp = vascii->fd; 1121 1122 tab = vascii->tab; 1123 while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " ")); 1124 1125 va_start(Argp, format); 1126 PetscCall((*PetscVFPrintf)(fp, format, Argp)); 1127 va_end(Argp); 1128 PetscCall(PetscFFlush(fp)); 1129 if (petsc_history) { 1130 va_start(Argp, format); 1131 PetscCall((*PetscVFPrintf)(petsc_history, format, Argp)); 1132 va_end(Argp); 1133 PetscCall(PetscFFlush(petsc_history)); 1134 } 1135 va_end(Argp); 1136 } else { /* other processors add to queue */ 1137 char *string; 1138 va_list Argp; 1139 size_t fullLength; 1140 PrintfQueue next; 1141 1142 PetscCall(PetscNew(&next)); 1143 if (vascii->petsc_printfqueue) { 1144 vascii->petsc_printfqueue->next = next; 1145 vascii->petsc_printfqueue = next; 1146 } else { 1147 vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next; 1148 } 1149 vascii->petsc_printfqueuelength++; 1150 next->size = QUEUESTRINGSIZE; 1151 PetscCall(PetscCalloc1(next->size, &next->string)); 1152 string = next->string; 1153 1154 tab = vascii->tab; 1155 tab *= 2; 1156 while (tab--) *string++ = ' '; 1157 va_start(Argp, format); 1158 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp)); 1159 va_end(Argp); 1160 if (fullLength > (size_t)(next->size - 2 * vascii->tab)) { 1161 PetscCall(PetscFree(next->string)); 1162 next->size = fullLength + 2 * vascii->tab; 1163 PetscCall(PetscCalloc1(next->size, &next->string)); 1164 string = next->string; 1165 tab = 2 * vascii->tab; 1166 while (tab--) *string++ = ' '; 1167 va_start(Argp, format); 1168 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp)); 1169 va_end(Argp); 1170 } 1171 } 1172 PetscFunctionReturn(PETSC_SUCCESS); 1173 } 1174 1175 /*@C 1176 PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file 1177 1178 Only MPI rank 0 in the `PetscViewer` may call this 1179 1180 Input Parameters: 1181 + viewer - the `PETSCVIEWERASCII` viewer 1182 . data - location to write the data, treated as an array of type indicated by `datatype` 1183 . num - number of items of data to read 1184 - dtype - type of data to read 1185 1186 Output Parameter: 1187 . count - number of items of data actually read, or `NULL` 1188 1189 Level: beginner 1190 1191 .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()` 1192 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 1193 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 1194 @*/ 1195 PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype) 1196 { 1197 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 1198 FILE *fd = vascii->fd; 1199 PetscInt i; 1200 int ret = 0; 1201 PetscMPIInt rank; 1202 1203 PetscFunctionBegin; 1204 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 1205 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 1206 PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer"); 1207 for (i = 0; i < num; i++) { 1208 if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i])); 1209 else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i])); 1210 else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i])); 1211 else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i])); 1212 else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i])); 1213 else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i])); 1214 else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i])); 1215 else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i])); 1216 #if defined(PETSC_USE_REAL___FLOAT128) 1217 else if (dtype == PETSC___FLOAT128) { 1218 double tmp; 1219 ret = fscanf(fd, "%lg", &tmp); 1220 ((__float128 *)data)[i] = tmp; 1221 } 1222 #endif 1223 else 1224 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype); 1225 PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype); 1226 if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */ 1227 } 1228 if (count) *count = i; 1229 else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num); 1230 PetscFunctionReturn(PETSC_SUCCESS); 1231 } 1232