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