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