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 /*@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 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header 527 /*MC 528 PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` to write to a Fortran IO unit 529 530 Synopsis: 531 #include <petscviewer.h> 532 void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr) 533 534 Input Parameters: 535 + lab - the viewer 536 - unit - the unit number 537 538 Output Parameter: 539 . ierr - the error code 540 541 Level: intermediate 542 543 Note: 544 `PetscViewerDestroy()` does not close the unit for this `PetscViewer` 545 546 Fortran Notes: 547 Only for Fortran, use `PetscViewerASCIISetFILE()` for C 548 549 .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()` 550 M*/ 551 PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, PetscInt *unit, PetscErrorCode *ierr) 552 { 553 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)(*lab)->data; 554 555 if (vascii->mode == FILE_MODE_READ) { 556 *ierr = PETSC_ERR_ARG_WRONGSTATE; 557 return; 558 } 559 vascii->fileunit = *unit; 560 } 561 562 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header 563 /*MC 564 PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit 565 566 Synopsis: 567 #include <petscviewer.h> 568 void PetscViewerASCIIOpenWithFileUnit(MPI_Comm comm, PetscInt unit, PetscViewer viewer, PetscErrorCode ierr) 569 570 Input Parameters: 571 + comm - the `MPI_Comm` to share the viewer 572 - unit - the unit number 573 574 Output Parameters: 575 + lab - the viewer 576 - ierr - the error code 577 578 Level: intermediate 579 580 Note: 581 `PetscViewerDestroy()` does not close the unit for this `PetscViewer` 582 583 Fortran Notes: 584 Only for Fortran, use `PetscViewerASCIIOpenWithFILE()` for C 585 586 .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()` 587 M*/ 588 PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Comm *comm, PetscInt *unit, PetscViewer *lab, PetscErrorCode *ierr) 589 { 590 *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab); 591 if (*ierr) return; 592 *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII); 593 if (*ierr) return; 594 *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE); 595 if (*ierr) return; 596 petscviewerasciisetfileunit_(lab, unit, ierr); 597 } 598 599 static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp) 600 { 601 PetscErrorCode ierr; 602 char str[PETSCDEFAULTBUFFERSIZE]; 603 size_t len; 604 605 PetscFunctionBegin; 606 PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp)); 607 PetscCall(PetscStrlen(str, &len)); 608 petscfortranprinttounit_(&unit, str, &ierr, (int)len); 609 PetscFunctionReturn(PETSC_SUCCESS); 610 } 611 612 static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[]) 613 { 614 PetscErrorCode ierr; 615 size_t len; 616 617 PetscFunctionBegin; 618 PetscCall(PetscStrlen(str, &len)); 619 petscfortranprinttounit_(&unit, str, &ierr, (int)len); 620 PetscFunctionReturn(PETSC_SUCCESS); 621 } 622 623 #else 624 625 /* these will never be used; but are needed to link with */ 626 static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp) 627 { 628 PetscFunctionBegin; 629 PetscFunctionReturn(PETSC_SUCCESS); 630 } 631 632 static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[]) 633 { 634 PetscFunctionBegin; 635 PetscFunctionReturn(PETSC_SUCCESS); 636 } 637 #endif 638 639 /*@C 640 PetscViewerASCIIPrintf - Prints to a file, only from the first 641 processor in the `PetscViewer` of type `PETSCVIEWERASCII` 642 643 Not Collective, but only the first MPI rank in the viewer has any effect 644 645 Input Parameters: 646 + viewer - obtained with `PetscViewerASCIIOpen()` 647 - format - the usual printf() format string 648 649 Level: developer 650 651 Fortran Notes: 652 The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran. 653 That is, you can only pass a single character string from Fortran. 654 655 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`, 656 `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, 657 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()` 658 @*/ 659 PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...) 660 { 661 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 662 PetscMPIInt rank; 663 PetscInt tab = 0, intab = ascii->tab; 664 FILE *fd = ascii->fd; 665 PetscBool iascii; 666 667 PetscFunctionBegin; 668 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 669 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()"); 670 PetscAssertPointer(format, 2); 671 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 672 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 673 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 674 if (rank) PetscFunctionReturn(PETSC_SUCCESS); 675 676 if (ascii->bviewer) { /* pass string up to parent viewer */ 677 char *string; 678 va_list Argp; 679 size_t fullLength; 680 681 PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string)); 682 for (; tab < ascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; } 683 va_start(Argp, format); 684 PetscCall(PetscVSNPrintf(string + 2 * intab, QUEUESTRINGSIZE - 2 * intab, format, &fullLength, Argp)); 685 va_end(Argp); 686 PetscCall(PetscViewerASCIISynchronizedPrintf(ascii->bviewer, "%s", string)); 687 PetscCall(PetscFree(string)); 688 } else { /* write directly to file */ 689 va_list Argp; 690 691 tab = intab; 692 while (tab--) { 693 if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, " ")); 694 else PetscCall(PetscFPrintfFortran(ascii->fileunit, " ")); 695 } 696 697 va_start(Argp, format); 698 if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp)); 699 else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp)); 700 va_end(Argp); 701 PetscCall(PetscFFlush(fd)); 702 } 703 PetscFunctionReturn(PETSC_SUCCESS); 704 } 705 706 /*@C 707 PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use. 708 709 Collective 710 711 Input Parameters: 712 + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY` 713 - name - the name of the file it should use 714 715 Level: advanced 716 717 Note: 718 This will have no effect on viewers that are not related to files 719 720 .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`, 721 `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()` 722 @*/ 723 PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[]) 724 { 725 char filename[PETSC_MAX_PATH_LEN]; 726 727 PetscFunctionBegin; 728 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 729 PetscAssertPointer(name, 2); 730 PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename))); 731 PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename)); 732 PetscFunctionReturn(PETSC_SUCCESS); 733 } 734 735 /*@C 736 PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using 737 738 Not Collective 739 740 Input Parameter: 741 . viewer - the `PetscViewer` 742 743 Output Parameter: 744 . name - the name of the file it is using 745 746 Level: advanced 747 748 Note: 749 This will have no effect on viewers that are not related to files 750 751 .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()` 752 @*/ 753 PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name) 754 { 755 PetscFunctionBegin; 756 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 757 PetscAssertPointer(name, 2); 758 PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name)); 759 PetscFunctionReturn(PETSC_SUCCESS); 760 } 761 762 static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name) 763 { 764 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 765 766 PetscFunctionBegin; 767 *name = vascii->filename; 768 PetscFunctionReturn(PETSC_SUCCESS); 769 } 770 771 #include <errno.h> 772 static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[]) 773 { 774 size_t len; 775 char fname[PETSC_MAX_PATH_LEN], *gz = NULL; 776 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 777 PetscBool isstderr, isstdout; 778 PetscMPIInt rank; 779 780 PetscFunctionBegin; 781 PetscCall(PetscViewerFileClose_ASCII(viewer)); 782 if (!name) PetscFunctionReturn(PETSC_SUCCESS); 783 PetscCall(PetscStrallocpy(name, &vascii->filename)); 784 785 /* Is this file to be compressed */ 786 vascii->storecompressed = PETSC_FALSE; 787 788 PetscCall(PetscStrstr(vascii->filename, ".gz", &gz)); 789 if (gz) { 790 PetscCall(PetscStrlen(gz, &len)); 791 if (len == 3) { 792 PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first"); 793 *gz = 0; 794 vascii->storecompressed = PETSC_TRUE; 795 } 796 } 797 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 798 if (rank == 0) { 799 PetscCall(PetscStrcmp(name, "stderr", &isstderr)); 800 PetscCall(PetscStrcmp(name, "stdout", &isstdout)); 801 /* empty filename means stdout */ 802 if (name[0] == 0) isstdout = PETSC_TRUE; 803 if (isstderr) vascii->fd = PETSC_STDERR; 804 else if (isstdout) vascii->fd = PETSC_STDOUT; 805 else { 806 PetscCall(PetscFixFilename(name, fname)); 807 switch (vascii->mode) { 808 case FILE_MODE_READ: 809 vascii->fd = fopen(fname, "r"); 810 break; 811 case FILE_MODE_WRITE: 812 vascii->fd = fopen(fname, "w"); 813 break; 814 case FILE_MODE_APPEND: 815 vascii->fd = fopen(fname, "a"); 816 break; 817 case FILE_MODE_UPDATE: 818 vascii->fd = fopen(fname, "r+"); 819 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 820 break; 821 case FILE_MODE_APPEND_UPDATE: 822 /* I really want a file which is opened at the end for updating, 823 not a+, which opens at the beginning, but makes writes at the end. 824 */ 825 vascii->fd = fopen(fname, "r+"); 826 if (!vascii->fd) vascii->fd = fopen(fname, "w+"); 827 else { 828 int ret = fseek(vascii->fd, 0, SEEK_END); 829 PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret); 830 } 831 break; 832 default: 833 SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]); 834 } 835 PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno)); 836 } 837 } 838 PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name)); 839 PetscFunctionReturn(PETSC_SUCCESS); 840 } 841 842 static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer) 843 { 844 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii; 845 846 PetscFunctionBegin; 847 PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored"); 848 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 849 /* 850 The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work 851 because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed 852 (since the count never gets to zero) in some examples this displays information that otherwise would be lost 853 854 This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example, 855 PCView_GASM(). 856 */ 857 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 858 PetscCall(PetscViewerFlush(viewer)); 859 PetscCall(PetscViewerCreate(subcomm, outviewer)); 860 PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII)); 861 PetscCall(PetscViewerASCIIPushSynchronized(*outviewer)); 862 ovascii = (PetscViewer_ASCII *)(*outviewer)->data; 863 ovascii->fd = vascii->fd; 864 ovascii->closefile = PETSC_FALSE; 865 866 vascii->sviewer = *outviewer; 867 (*outviewer)->format = viewer->format; 868 ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer; 869 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer; 870 PetscFunctionReturn(PETSC_SUCCESS); 871 } 872 873 static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer) 874 { 875 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 876 877 PetscFunctionBegin; 878 PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer"); 879 PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer"); 880 881 PetscCall(PetscViewerASCIIPopSynchronized(*outviewer)); 882 ascii->sviewer = NULL; 883 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII; 884 PetscCall(PetscViewerDestroy(outviewer)); 885 PetscCall(PetscViewerFlush(viewer)); 886 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 887 PetscFunctionReturn(PETSC_SUCCESS); 888 } 889 890 static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer) 891 { 892 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data; 893 894 PetscFunctionBegin; 895 if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename)); 896 PetscFunctionReturn(PETSC_SUCCESS); 897 } 898 899 /*MC 900 PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file 901 902 Level: beginner 903 904 .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, 905 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, 906 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 907 M*/ 908 PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer) 909 { 910 PetscViewer_ASCII *vascii; 911 912 PetscFunctionBegin; 913 PetscCall(PetscNew(&vascii)); 914 viewer->data = (void *)vascii; 915 916 viewer->ops->destroy = PetscViewerDestroy_ASCII; 917 viewer->ops->flush = PetscViewerFlush_ASCII; 918 viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII; 919 viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII; 920 viewer->ops->view = PetscViewerView_ASCII; 921 viewer->ops->read = PetscViewerASCIIRead; 922 923 /* defaults to stdout unless set with PetscViewerFileSetName() */ 924 vascii->fd = PETSC_STDOUT; 925 vascii->mode = FILE_MODE_WRITE; 926 vascii->bviewer = NULL; 927 vascii->subviewer = NULL; 928 vascii->sviewer = NULL; 929 vascii->tab = 0; 930 vascii->tab_store = 0; 931 vascii->filename = NULL; 932 vascii->closefile = PETSC_TRUE; 933 934 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII)); 935 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII)); 936 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII)); 937 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII)); 938 PetscFunctionReturn(PETSC_SUCCESS); 939 } 940 941 /*@C 942 PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from 943 several processors. Output of the first processor is followed by that of the 944 second, etc. 945 946 Not Collective, must call collective `PetscViewerFlush()` to get the results flushed 947 948 Input Parameters: 949 + viewer - the `PETSCVIEWERASCII` `PetscViewer` 950 - format - the usual printf() format string 951 952 Level: intermediate 953 954 Notes: 955 You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called. 956 Then you can do multiple independent calls to this routine. 957 958 The actual synchronized print is then done using `PetscViewerFlush()`. 959 `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output 960 to conclude the "synchronized session". 961 962 So the typical calling sequence looks like 963 .vb 964 PetscViewerASCIIPushSynchronized(viewer); 965 PetscViewerASCIISynchronizedPrintf(viewer, ...); 966 PetscViewerASCIISynchronizedPrintf(viewer, ...); 967 ... 968 PetscViewerFlush(viewer); 969 PetscViewerASCIISynchronizedPrintf(viewer, ...); 970 PetscViewerASCIISynchronizedPrintf(viewer, ...); 971 ... 972 PetscViewerFlush(viewer); 973 PetscViewerASCIIPopSynchronized(viewer); 974 .ve 975 976 Fortran Notes: 977 Can only print a single character* string 978 979 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 980 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 981 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 982 @*/ 983 PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...) 984 { 985 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 986 PetscMPIInt rank; 987 PetscInt tab = 0; 988 MPI_Comm comm; 989 PetscBool iascii; 990 991 PetscFunctionBegin; 992 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 993 PetscAssertPointer(format, 2); 994 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 995 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 996 PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call"); 997 998 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 999 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1000 1001 if (vascii->bviewer) { 1002 char *string; 1003 va_list Argp; 1004 size_t fullLength; 1005 1006 PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string)); 1007 for (; tab < vascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; } 1008 va_start(Argp, format); 1009 PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp)); 1010 va_end(Argp); 1011 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string)); 1012 PetscCall(PetscFree(string)); 1013 } else if (rank == 0) { /* First processor prints immediately to fp */ 1014 va_list Argp; 1015 FILE *fp = vascii->fd; 1016 1017 tab = vascii->tab; 1018 while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " ")); 1019 1020 va_start(Argp, format); 1021 PetscCall((*PetscVFPrintf)(fp, format, Argp)); 1022 va_end(Argp); 1023 PetscCall(PetscFFlush(fp)); 1024 if (petsc_history) { 1025 va_start(Argp, format); 1026 PetscCall((*PetscVFPrintf)(petsc_history, format, Argp)); 1027 va_end(Argp); 1028 PetscCall(PetscFFlush(petsc_history)); 1029 } 1030 va_end(Argp); 1031 } else { /* other processors add to queue */ 1032 char *string; 1033 va_list Argp; 1034 size_t fullLength; 1035 PrintfQueue next; 1036 1037 PetscCall(PetscNew(&next)); 1038 if (vascii->petsc_printfqueue) { 1039 vascii->petsc_printfqueue->next = next; 1040 vascii->petsc_printfqueue = next; 1041 } else { 1042 vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next; 1043 } 1044 vascii->petsc_printfqueuelength++; 1045 next->size = QUEUESTRINGSIZE; 1046 PetscCall(PetscCalloc1(next->size, &next->string)); 1047 string = next->string; 1048 1049 tab = vascii->tab; 1050 tab *= 2; 1051 while (tab--) *string++ = ' '; 1052 va_start(Argp, format); 1053 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp)); 1054 va_end(Argp); 1055 if (fullLength > (size_t)(next->size - 2 * vascii->tab)) { 1056 PetscCall(PetscFree(next->string)); 1057 next->size = fullLength + 2 * vascii->tab; 1058 PetscCall(PetscCalloc1(next->size, &next->string)); 1059 string = next->string; 1060 tab = 2 * vascii->tab; 1061 while (tab--) *string++ = ' '; 1062 va_start(Argp, format); 1063 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp)); 1064 va_end(Argp); 1065 } 1066 } 1067 PetscFunctionReturn(PETSC_SUCCESS); 1068 } 1069 1070 /*@C 1071 PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file 1072 1073 Only MPI rank 0 in the `PetscViewer` may call this 1074 1075 Input Parameters: 1076 + viewer - the `PETSCVIEWERASCII` viewer 1077 . data - location to write the data, treated as an array of type indicated by `datatype` 1078 . num - number of items of data to read 1079 - dtype - type of data to read 1080 1081 Output Parameter: 1082 . count - number of items of data actually read, or `NULL` 1083 1084 Level: beginner 1085 1086 .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()` 1087 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 1088 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 1089 @*/ 1090 PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype) 1091 { 1092 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 1093 FILE *fd = vascii->fd; 1094 PetscInt i; 1095 int ret = 0; 1096 PetscMPIInt rank; 1097 1098 PetscFunctionBegin; 1099 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 1100 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 1101 PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer"); 1102 for (i = 0; i < num; i++) { 1103 if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i])); 1104 else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i])); 1105 else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i])); 1106 else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i])); 1107 else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i])); 1108 else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i])); 1109 else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i])); 1110 else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i])); 1111 #if defined(PETSC_USE_REAL___FLOAT128) 1112 else if (dtype == PETSC___FLOAT128) { 1113 double tmp; 1114 ret = fscanf(fd, "%lg", &tmp); 1115 ((__float128 *)data)[i] = tmp; 1116 } 1117 #endif 1118 else 1119 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype); 1120 PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype); 1121 if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */ 1122 } 1123 if (count) *count = i; 1124 else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num); 1125 PetscFunctionReturn(PETSC_SUCCESS); 1126 } 1127