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