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