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