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 *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(PetscViewerFlush(viewer)); 858 PetscCall(PetscViewerCreate(subcomm, outviewer)); 859 PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII)); 860 PetscCall(PetscViewerASCIIPushSynchronized(*outviewer)); 861 ovascii = (PetscViewer_ASCII *)(*outviewer)->data; 862 ovascii->fd = vascii->fd; 863 ovascii->closefile = PETSC_FALSE; 864 865 vascii->sviewer = *outviewer; 866 (*outviewer)->format = viewer->format; 867 ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer; 868 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer; 869 PetscFunctionReturn(PETSC_SUCCESS); 870 } 871 872 static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer) 873 { 874 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data; 875 876 PetscFunctionBegin; 877 PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer"); 878 PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer"); 879 880 PetscCall(PetscViewerASCIIPopSynchronized(*outviewer)); 881 ascii->sviewer = NULL; 882 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII; 883 PetscCall(PetscViewerDestroy(outviewer)); 884 PetscCall(PetscViewerFlush(viewer)); 885 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 886 PetscFunctionReturn(PETSC_SUCCESS); 887 } 888 889 static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer) 890 { 891 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data; 892 893 PetscFunctionBegin; 894 if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename)); 895 PetscFunctionReturn(PETSC_SUCCESS); 896 } 897 898 /*MC 899 PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file 900 901 Level: beginner 902 903 .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, 904 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, 905 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 906 M*/ 907 PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer) 908 { 909 PetscViewer_ASCII *vascii; 910 911 PetscFunctionBegin; 912 PetscCall(PetscNew(&vascii)); 913 viewer->data = (void *)vascii; 914 915 viewer->ops->destroy = PetscViewerDestroy_ASCII; 916 viewer->ops->flush = PetscViewerFlush_ASCII; 917 viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII; 918 viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII; 919 viewer->ops->view = PetscViewerView_ASCII; 920 viewer->ops->read = PetscViewerASCIIRead; 921 922 /* defaults to stdout unless set with PetscViewerFileSetName() */ 923 vascii->fd = PETSC_STDOUT; 924 vascii->mode = FILE_MODE_WRITE; 925 vascii->bviewer = NULL; 926 vascii->subviewer = NULL; 927 vascii->sviewer = NULL; 928 vascii->tab = 0; 929 vascii->tab_store = 0; 930 vascii->filename = NULL; 931 vascii->closefile = PETSC_TRUE; 932 933 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII)); 934 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII)); 935 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII)); 936 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII)); 937 PetscFunctionReturn(PETSC_SUCCESS); 938 } 939 940 /*@C 941 PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from 942 several processors. Output of the first processor is followed by that of the 943 second, etc. 944 945 Not Collective, must call collective `PetscViewerFlush()` to get the results flushed 946 947 Input Parameters: 948 + viewer - the `PETSCVIEWERASCII` `PetscViewer` 949 - format - the usual printf() format string 950 951 Level: intermediate 952 953 Notes: 954 You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called. 955 Then you can do multiple independent calls to this routine. 956 957 The actual synchronized print is then done using `PetscViewerFlush()`. 958 `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output 959 to conclude the "synchronized session". 960 961 So the typical calling sequence looks like 962 .vb 963 PetscViewerASCIIPushSynchronized(viewer); 964 PetscViewerASCIISynchronizedPrintf(viewer, ...); 965 PetscViewerASCIISynchronizedPrintf(viewer, ...); 966 ... 967 PetscViewerFlush(viewer); 968 PetscViewerASCIISynchronizedPrintf(viewer, ...); 969 PetscViewerASCIISynchronizedPrintf(viewer, ...); 970 ... 971 PetscViewerFlush(viewer); 972 PetscViewerASCIIPopSynchronized(viewer); 973 .ve 974 975 Fortran Notes: 976 Can only print a single character* string 977 978 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`, 979 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`, 980 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()` 981 @*/ 982 PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...) 983 { 984 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 985 PetscMPIInt rank; 986 PetscInt tab = 0; 987 MPI_Comm comm; 988 PetscBool iascii; 989 990 PetscFunctionBegin; 991 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 992 PetscAssertPointer(format, 2); 993 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 994 PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer"); 995 PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call"); 996 997 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 998 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 999 1000 if (vascii->bviewer) { 1001 char *string; 1002 va_list Argp; 1003 size_t fullLength; 1004 1005 PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string)); 1006 for (; tab < vascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; } 1007 va_start(Argp, format); 1008 PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp)); 1009 va_end(Argp); 1010 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string)); 1011 PetscCall(PetscFree(string)); 1012 } else if (rank == 0) { /* First processor prints immediately to fp */ 1013 va_list Argp; 1014 FILE *fp = vascii->fd; 1015 1016 tab = vascii->tab; 1017 while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " ")); 1018 1019 va_start(Argp, format); 1020 PetscCall((*PetscVFPrintf)(fp, format, Argp)); 1021 va_end(Argp); 1022 PetscCall(PetscFFlush(fp)); 1023 if (petsc_history) { 1024 va_start(Argp, format); 1025 PetscCall((*PetscVFPrintf)(petsc_history, format, Argp)); 1026 va_end(Argp); 1027 PetscCall(PetscFFlush(petsc_history)); 1028 } 1029 va_end(Argp); 1030 } else { /* other processors add to queue */ 1031 char *string; 1032 va_list Argp; 1033 size_t fullLength; 1034 PrintfQueue next; 1035 1036 PetscCall(PetscNew(&next)); 1037 if (vascii->petsc_printfqueue) { 1038 vascii->petsc_printfqueue->next = next; 1039 vascii->petsc_printfqueue = next; 1040 } else { 1041 vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next; 1042 } 1043 vascii->petsc_printfqueuelength++; 1044 next->size = QUEUESTRINGSIZE; 1045 PetscCall(PetscCalloc1(next->size, &next->string)); 1046 string = next->string; 1047 1048 tab = vascii->tab; 1049 tab *= 2; 1050 while (tab--) *string++ = ' '; 1051 va_start(Argp, format); 1052 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp)); 1053 va_end(Argp); 1054 if (fullLength > (size_t)(next->size - 2 * vascii->tab)) { 1055 PetscCall(PetscFree(next->string)); 1056 next->size = fullLength + 2 * vascii->tab; 1057 PetscCall(PetscCalloc1(next->size, &next->string)); 1058 string = next->string; 1059 tab = 2 * vascii->tab; 1060 while (tab--) *string++ = ' '; 1061 va_start(Argp, format); 1062 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp)); 1063 va_end(Argp); 1064 } 1065 } 1066 PetscFunctionReturn(PETSC_SUCCESS); 1067 } 1068 1069 /*@C 1070 PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file 1071 1072 Only MPI rank 0 in the `PetscViewer` may call this 1073 1074 Input Parameters: 1075 + viewer - the `PETSCVIEWERASCII` viewer 1076 . data - location to write the data, treated as an array of type indicated by `datatype` 1077 . num - number of items of data to read 1078 - dtype - type of data to read 1079 1080 Output Parameter: 1081 . count - number of items of data actually read, or `NULL` 1082 1083 Level: beginner 1084 1085 .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()` 1086 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 1087 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()` 1088 @*/ 1089 PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype) 1090 { 1091 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 1092 FILE *fd = vascii->fd; 1093 PetscInt i; 1094 int ret = 0; 1095 PetscMPIInt rank; 1096 1097 PetscFunctionBegin; 1098 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 1099 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 1100 PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer"); 1101 for (i = 0; i < num; i++) { 1102 if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i])); 1103 else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i])); 1104 else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i])); 1105 else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i])); 1106 else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i])); 1107 else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i])); 1108 else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i])); 1109 else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i])); 1110 #if defined(PETSC_USE_REAL___FLOAT128) 1111 else if (dtype == PETSC___FLOAT128) { 1112 double tmp; 1113 ret = fscanf(fd, "%lg", &tmp); 1114 ((__float128 *)data)[i] = tmp; 1115 } 1116 #endif 1117 else 1118 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype); 1119 PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype); 1120 if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */ 1121 } 1122 if (count) *count = i; 1123 else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num); 1124 PetscFunctionReturn(PETSC_SUCCESS); 1125 } 1126