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