Date: 2022-08-02T03:13:15+00:00

Actual source code: filev.c

      2: #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h>

      4: #define QUEUESTRINGSIZE 8192

      6: static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer)
      7: {
      8:   PetscMPIInt       rank;
      9:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
     10:   int               err;

     13:   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);
     18:     }
     19:     if (vascii->storecompressed) {
     20:       char par[PETSC_MAX_PATH_LEN],buf[PETSC_MAX_PATH_LEN];
     21:       FILE *fp;
     22:       PetscStrncpy(par,"gzip ",sizeof(par));
     23:       PetscStrlcat(par,vascii->filename,sizeof(par));
     24: #if defined(PETSC_HAVE_POPEN)
     25:       PetscPOpen(PETSC_COMM_SELF,NULL,par,"r",&fp);
     27:       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:   PetscFree(vascii->filename);
     34:   return 0;
     35: }

     37: /* ----------------------------------------------------------------------*/
     38: PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
     39: {
     40:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
     41:   PetscViewerLink   *vlink;
     42:   PetscBool         flg;

     45:   PetscViewerFileClose_ASCII(viewer);
     46:   PetscFree(vascii);

     48:   /* remove the viewer from the list in the MPI Communicator */
     49:   if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) {
     50:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,Petsc_DelViewer,&Petsc_Viewer_keyval,(void*)0);
     51:   }

     53:   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:         MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_keyval,vlink->next);
     58:       } else {
     59:         MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_keyval);
     60:       }
     61:       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:           PetscFree(nv);
     68:         }
     69:         vlink = vlink->next;
     70:       }
     71:     }
     72:   }

     74:   if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
     75:     PetscViewer aviewer;
     76:     MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stdout_keyval,(void**)&aviewer,(PetscMPIInt*)&flg);
     77:     if (flg && aviewer == viewer) {
     78:       MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stdout_keyval);
     79:     }
     80:   }
     81:   if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
     82:     PetscViewer aviewer;
     83:     MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stderr_keyval,(void**)&aviewer,(PetscMPIInt*)&flg);
     84:     if (flg && aviewer == viewer) {
     85:       MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer),Petsc_Viewer_Stderr_keyval);
     86:     }
     87:   }
     88:   return 0;
     89: }

     91: PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
     92: {
     93:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;

     95:   PetscViewerRestoreSubViewer(vascii->bviewer,0,&viewer);
     96:   return 0;
     97: }

     99: PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
    100: {
    101:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
    102:   int               err;
    103:   MPI_Comm          comm;
    104:   PetscMPIInt       rank,size;
    105:   FILE              *fd = vascii->fd;

    108:   PetscObjectGetComm((PetscObject)viewer,&comm);
    109:   MPI_Comm_rank(comm,&rank);
    110:   MPI_Comm_size(comm,&size);

    112:   if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) {
    113:     err = fflush(vascii->fd);
    115:   }

    117:   if (vascii->allowsynchronized) {
    118:     PetscMPIInt   tag,i,j,n = 0,dummy = 0;
    119:     char          *message;
    120:     MPI_Status    status;

    122:     PetscCommDuplicate(comm,&comm,&tag);

    124:     /* First processor waits for messages from all other processors */
    125:     if (rank == 0) {
    126:       /* flush my own messages that I may have queued up */
    127:       PrintfQueue next = vascii->petsc_printfqueuebase,previous;
    128:       for (i=0; i<vascii->petsc_printfqueuelength; i++) {
    129:         if (!vascii->bviewer) {
    130:           PetscFPrintf(comm,fd,"%s",next->string);
    131:         } else {
    132:           PetscViewerASCIISynchronizedPrintf(vascii->bviewer,"%s",next->string);
    133:         }
    134:         previous = next;
    135:         next     = next->next;
    136:         PetscFree(previous->string);
    137:         PetscFree(previous);
    138:       }
    139:       vascii->petsc_printfqueue       = NULL;
    140:       vascii->petsc_printfqueuelength = 0;
    141:       for (i=1; i<size; i++) {
    142:         /* to prevent a flood of messages to process zero, request each message separately */
    143:         MPI_Send(&dummy,1,MPI_INT,i,tag,comm);
    144:         MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);
    145:         for (j=0; j<n; j++) {
    146:           PetscMPIInt size = 0;

    148:           MPI_Recv(&size,1,MPI_INT,i,tag,comm,&status);
    149:           PetscMalloc1(size, &message);
    150:           MPI_Recv(message,size,MPI_CHAR,i,tag,comm,&status);
    151:           if (!vascii->bviewer) {
    152:             PetscFPrintf(comm,fd,"%s",message);
    153:           } else {
    154:             PetscViewerASCIISynchronizedPrintf(vascii->bviewer,"%s",message);
    155:           }
    156:           PetscFree(message);
    157:         }
    158:       }
    159:     } else { /* other processors send queue to processor 0 */
    160:       PrintfQueue next = vascii->petsc_printfqueuebase,previous;

    162:       MPI_Recv(&dummy,1,MPI_INT,0,tag,comm,&status);
    163:       MPI_Send(&vascii->petsc_printfqueuelength,1,MPI_INT,0,tag,comm);
    164:       for (i=0; i<vascii->petsc_printfqueuelength; i++) {
    165:         MPI_Send(&next->size,1,MPI_INT,0,tag,comm);
    166:         MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm);
    167:         previous = next;
    168:         next     = next->next;
    169:         PetscFree(previous->string);
    170:         PetscFree(previous);
    171:       }
    172:       vascii->petsc_printfqueue       = NULL;
    173:       vascii->petsc_printfqueuelength = 0;
    174:     }
    175:     PetscCommDestroy(&comm);
    176:   }
    177:   return 0;
    178: }

    180: /*@C
    181:     PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII PetscViewer.

    183:     Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer

    185:     Input Parameter:
    186: .    viewer - PetscViewer context, obtained from PetscViewerASCIIOpen()

    188:     Output Parameter:
    189: .    fd - file pointer

    191:     Notes: for the standard PETSCVIEWERASCII the value is valid only on process 0 of the viewer

    193:     Level: intermediate

    195:     Fortran Note:
    196:     This routine is not supported in Fortran.

    198: .seealso: 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;

    205:   *fd = vascii->fd;
    206:   return 0;
    207: }

    209: PetscErrorCode  PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
    210: {
    211:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;

    213:   *mode = vascii->mode;
    214:   return 0;
    215: }

    217: PetscErrorCode  PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
    218: {
    219:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;

    221:   vascii->mode = mode;
    222:   return 0;
    223: }

    225: /*
    226:    If petsc_history is on, then all Petsc*Printf() results are saved
    227:    if the appropriate (usually .petschistory) file.
    228: */
    229: PETSC_INTERN FILE *petsc_history;

    231: /*@
    232:     PetscViewerASCIISetTab - Causes PetscViewer to tab in a number of times

    234:     Not Collective, but only first processor in set has any effect

    236:     Input Parameters:
    237: +    viewer - obtained with PetscViewerASCIIOpen()
    238: -    tabs - number of tabs

    240:     Level: developer

    242:     Fortran Note:
    243:     This routine is not supported in Fortran.

    245: .seealso: 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;

    255:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    256:   if (iascii) ascii->tab = tabs;
    257:   return 0;
    258: }

    260: /*@
    261:     PetscViewerASCIIGetTab - Return the number of tabs used by PetscViewer.

    263:     Not Collective, meaningful on first processor only.

    265:     Input Parameters:
    266: .    viewer - obtained with PetscViewerASCIIOpen()

    268:     Output Parameters:
    269: .    tabs - number of tabs

    271:     Level: developer

    273:     Fortran Note:
    274:     This routine is not supported in Fortran.

    276: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISetTab(),
    277:           PetscViewerASCIIPopTab(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIOpen(),
    278:           PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer(), PetscViewerASCIIPushTab()
    279: @*/
    280: PetscErrorCode  PetscViewerASCIIGetTab(PetscViewer viewer,PetscInt *tabs)
    281: {
    282:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
    283:   PetscBool         iascii;

    286:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    287:   if (iascii && tabs) *tabs = ascii->tab;
    288:   return 0;
    289: }

    291: /*@
    292:     PetscViewerASCIIAddTab - Add to the number of times an ASCII viewer tabs before printing

    294:     Not Collective, but only first processor in set has any effect

    296:     Input Parameters:
    297: +    viewer - obtained with PetscViewerASCIIOpen()
    298: -    tabs - number of tabs

    300:     Level: developer

    302:     Fortran Note:
    303:     This routine is not supported in Fortran.

    305: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
    306:           PetscViewerASCIIPopTab(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIOpen(),
    307:           PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer(), PetscViewerASCIIPushTab()
    308: @*/
    309: PetscErrorCode  PetscViewerASCIIAddTab(PetscViewer viewer,PetscInt tabs)
    310: {
    311:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
    312:   PetscBool         iascii;

    315:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    316:   if (iascii) ascii->tab += tabs;
    317:   return 0;
    318: }

    320: /*@
    321:     PetscViewerASCIISubtractTab - Subtracts from the number of times an ASCII viewer tabs before printing

    323:     Not Collective, but only first processor in set has any effect

    325:     Input Parameters:
    326: +    viewer - obtained with PetscViewerASCIIOpen()
    327: -    tabs - number of tabs

    329:     Level: developer

    331:     Fortran Note:
    332:     This routine is not supported in Fortran.

    334: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
    335:           PetscViewerASCIIPopTab(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIOpen(),
    336:           PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer(), PetscViewerASCIIPushTab()
    337: @*/
    338: PetscErrorCode  PetscViewerASCIISubtractTab(PetscViewer viewer,PetscInt tabs)
    339: {
    340:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
    341:   PetscBool         iascii;

    344:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    345:   if (iascii) ascii->tab -= tabs;
    346:   return 0;
    347: }

    349: /*@C
    350:     PetscViewerASCIIPushSynchronized - Allows calls to PetscViewerASCIISynchronizedPrintf() for this viewer

    352:     Collective on PetscViewer

    354:     Input Parameters:
    355: .    viewer - obtained with PetscViewerASCIIOpen()

    357:     Level: intermediate

    359:     Notes:
    360:     See documentation of PetscViewerASCIISynchronizedPrintf() for more details how the synchronized output should be done properly.

    362: .seealso: PetscViewerASCIISynchronizedPrintf(), PetscViewerFlush(), PetscViewerASCIIPopSynchronized(),
    363:           PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIIOpen(),
    364:           PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType()
    365: @*/
    366: PetscErrorCode  PetscViewerASCIIPushSynchronized(PetscViewer viewer)
    367: {
    368:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
    369:   PetscBool         iascii;

    373:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    374:   if (iascii) ascii->allowsynchronized++;
    375:   return 0;
    376: }

    378: /*@C
    379:     PetscViewerASCIIPopSynchronized - Undoes most recent PetscViewerASCIIPushSynchronized() for this viewer

    381:     Collective on PetscViewer

    383:     Input Parameters:
    384: .    viewer - obtained with PetscViewerASCIIOpen()

    386:     Level: intermediate

    388:     Notes:
    389:     See documentation of PetscViewerASCIISynchronizedPrintf() for more details how the synchronized output should be done properly.

    391: .seealso: PetscViewerASCIIPushSynchronized(), PetscViewerASCIISynchronizedPrintf(), PetscViewerFlush(),
    392:           PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIIOpen(),
    393:           PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType()
    394: @*/
    395: PetscErrorCode  PetscViewerASCIIPopSynchronized(PetscViewer viewer)
    396: {
    397:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
    398:   PetscBool         iascii;

    402:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    403:   if (iascii) {
    404:     ascii->allowsynchronized--;
    406:   }
    407:   return 0;
    408: }

    410: /*@C
    411:     PetscViewerASCIIPushTab - Adds one more tab to the amount that PetscViewerASCIIPrintf()
    412:      lines are tabbed.

    414:     Not Collective, but only first processor in set has any effect

    416:     Input Parameters:
    417: .    viewer - obtained with PetscViewerASCIIOpen()

    419:     Level: developer

    421:     Fortran Note:
    422:     This routine is not supported in Fortran.

    424: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
    425:           PetscViewerASCIIPopTab(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIOpen(),
    426:           PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer()
    427: @*/
    428: PetscErrorCode  PetscViewerASCIIPushTab(PetscViewer viewer)
    429: {
    430:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
    431:   PetscBool         iascii;

    434:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    435:   if (iascii) ascii->tab++;
    436:   return 0;
    437: }

    439: /*@C
    440:     PetscViewerASCIIPopTab - Removes one tab from the amount that PetscViewerASCIIPrintf()
    441:      lines are tabbed.

    443:     Not Collective, but only first processor in set has any effect

    445:     Input Parameters:
    446: .    viewer - obtained with PetscViewerASCIIOpen()

    448:     Level: developer

    450:     Fortran Note:
    451:     This routine is not supported in Fortran.

    453: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
    454:           PetscViewerASCIIPushTab(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIOpen(),
    455:           PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer()
    456: @*/
    457: PetscErrorCode  PetscViewerASCIIPopTab(PetscViewer viewer)
    458: {
    459:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
    460:   PetscBool         iascii;

    463:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    464:   if (iascii) {
    466:     ascii->tab--;
    467:   }
    468:   return 0;
    469: }

    471: /*@
    472:     PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the ASCII PetscViewer

    474:     Not Collective, but only first processor in set has any effect

    476:     Input Parameters:
    477: +    viewer - obtained with PetscViewerASCIIOpen()
    478: -    flg - PETSC_TRUE or PETSC_FALSE

    480:     Level: developer

    482:     Fortran Note:
    483:     This routine is not supported in Fortran.

    485: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(),
    486:           PetscViewerASCIIPopTab(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPushTab(), PetscViewerASCIIOpen(),
    487:           PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer()
    488: @*/
    489: PetscErrorCode  PetscViewerASCIIUseTabs(PetscViewer viewer,PetscBool flg)
    490: {
    491:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
    492:   PetscBool         iascii;

    495:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    496:   if (iascii) {
    497:     if (flg) ascii->tab = ascii->tab_store;
    498:     else {
    499:       ascii->tab_store = ascii->tab;
    500:       ascii->tab       = 0;
    501:     }
    502:   }
    503:   return 0;
    504: }

    506: /* ----------------------------------------------------------------------- */

    508: /*@C
    509:     PetscViewerASCIIPrintf - Prints to a file, only from the first
    510:     processor in the PetscViewer

    512:     Not Collective, but only first processor in set has any effect

    514:     Input Parameters:
    515: +    viewer - obtained with PetscViewerASCIIOpen()
    516: -    format - the usual printf() format string

    518:     Level: developer

    520:     Fortran Note:
    521:     The call sequence is PetscViewerASCIIPrintf(PetscViewer, character(*), int ierr) from Fortran.
    522:     That is, you can only pass a single character string from Fortran.

    524: .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIOpen(),
    525:           PetscViewerASCIIPushTab(), PetscViewerASCIIPopTab(), PetscViewerASCIISynchronizedPrintf(),
    526:           PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType(), PetscViewerASCIIGetPointer(), PetscViewerASCIIPushSynchronized()
    527: @*/
    528: PetscErrorCode  PetscViewerASCIIPrintf(PetscViewer viewer,const char format[],...)
    529: {
    530:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)viewer->data;
    531:   PetscMPIInt       rank;
    532:   PetscInt          tab,intab = ascii->tab;
    533:   FILE              *fd = ascii->fd;
    534:   PetscBool         iascii;
    535:   int               err;

    540:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    542:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
    543:   if (rank) return 0;

    545:   if (ascii->bviewer) { /* pass string up to parent viewer */
    546:     char        *string;
    547:     va_list     Argp;
    548:     size_t      fullLength;

    550:     PetscCalloc1(QUEUESTRINGSIZE, &string);
    551:     va_start(Argp,format);
    552:     PetscVSNPrintf(string,QUEUESTRINGSIZE,format,&fullLength,Argp);
    553:     va_end(Argp);
    554:     PetscViewerASCIISynchronizedPrintf(viewer,"%s",string);
    555:     PetscFree(string);
    556:   } else { /* write directly to file */
    557:     va_list Argp;
    558:     /* flush my own messages that I may have queued up */
    559:     PrintfQueue next = ascii->petsc_printfqueuebase,previous;
    560:     PetscInt    i;
    561:     for (i=0; i<ascii->petsc_printfqueuelength; i++) {
    562:       PetscFPrintf(PETSC_COMM_SELF,fd,"%s",next->string);
    563:       previous = next;
    564:       next     = next->next;
    565:       PetscFree(previous->string);
    566:       PetscFree(previous);
    567:     }
    568:     ascii->petsc_printfqueue       = NULL;
    569:     ascii->petsc_printfqueuelength = 0;
    570:     tab = intab;
    571:     while (tab--) {
    572:       PetscFPrintf(PETSC_COMM_SELF,fd,"  ");
    573:     }

    575:     va_start(Argp,format);
    576:     (*PetscVFPrintf)(fd,format,Argp);
    577:     err  = fflush(fd);
    579:     if (petsc_history) {
    580:       va_start(Argp,format);
    581:       tab = intab;
    582:       while (tab--) {
    583:         PetscFPrintf(PETSC_COMM_SELF,petsc_history,"  ");
    584:       }
    585:       (*PetscVFPrintf)(petsc_history,format,Argp);
    586:       err  = fflush(petsc_history);
    588:     }
    589:     va_end(Argp);
    590:   }
    591:   return 0;
    592: }

    594: /*@C
    595:      PetscViewerFileSetName - Sets the name of the file the PetscViewer uses.

    597:     Collective on PetscViewer

    599:   Input Parameters:
    600: +  viewer - the PetscViewer; either ASCII or binary
    601: -  name - the name of the file it should use

    603:     Level: advanced

    605: .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PetscViewerDestroy(),
    606:           PetscViewerASCIIGetPointer(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf()

    608: @*/
    609: PetscErrorCode  PetscViewerFileSetName(PetscViewer viewer,const char name[])
    610: {
    611:   char           filename[PETSC_MAX_PATH_LEN];

    615:   PetscStrreplace(PetscObjectComm((PetscObject)viewer),name,filename,sizeof(filename));
    616:   PetscTryMethod(viewer,"PetscViewerFileSetName_C",(PetscViewer,const char[]),(viewer,filename));
    617:   return 0;
    618: }

    620: /*@C
    621:      PetscViewerFileGetName - Gets the name of the file the PetscViewer uses.

    623:     Not Collective

    625:   Input Parameter:
    626: .  viewer - the PetscViewer; either ASCII or binary

    628:   Output Parameter:
    629: .  name - the name of the file it is using

    631:     Level: advanced

    633: .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PetscViewerFileSetName()

    635: @*/
    636: PetscErrorCode  PetscViewerFileGetName(PetscViewer viewer,const char **name)
    637: {
    640:   PetscUseMethod(viewer,"PetscViewerFileGetName_C",(PetscViewer,const char**),(viewer,name));
    641:   return 0;
    642: }

    644: PetscErrorCode  PetscViewerFileGetName_ASCII(PetscViewer viewer,const char **name)
    645: {
    646:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;

    648:   *name = vascii->filename;
    649:   return 0;
    650: }

    652: PetscErrorCode  PetscViewerFileSetName_ASCII(PetscViewer viewer,const char name[])
    653: {
    654:   size_t            len;
    655:   char              fname[PETSC_MAX_PATH_LEN],*gz;
    656:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
    657:   PetscBool         isstderr,isstdout;
    658:   PetscMPIInt       rank;

    660:   PetscViewerFileClose_ASCII(viewer);
    661:   if (!name) return 0;
    662:   PetscStrallocpy(name,&vascii->filename);

    664:   /* Is this file to be compressed */
    665:   vascii->storecompressed = PETSC_FALSE;

    667:   PetscStrstr(vascii->filename,".gz",&gz);
    668:   if (gz) {
    669:     PetscStrlen(gz,&len);
    670:     if (len == 3) {
    672:       *gz = 0;
    673:       vascii->storecompressed = PETSC_TRUE;
    674:     }
    675:   }
    676:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
    677:   if (rank == 0) {
    678:     PetscStrcmp(name,"stderr",&isstderr);
    679:     PetscStrcmp(name,"stdout",&isstdout);
    680:     /* empty filename means stdout */
    681:     if (name[0] == 0)  isstdout = PETSC_TRUE;
    682:     if (isstderr)      vascii->fd = PETSC_STDERR;
    683:     else if (isstdout) vascii->fd = PETSC_STDOUT;
    684:     else {

    686:       PetscFixFilename(name,fname);
    687:       switch (vascii->mode) {
    688:       case FILE_MODE_READ:
    689:         vascii->fd = fopen(fname,"r");
    690:         break;
    691:       case FILE_MODE_WRITE:
    692:         vascii->fd = fopen(fname,"w");
    693:         break;
    694:       case FILE_MODE_APPEND:
    695:         vascii->fd = fopen(fname,"a");
    696:         break;
    697:       case FILE_MODE_UPDATE:
    698:         vascii->fd = fopen(fname,"r+");
    699:         if (!vascii->fd) vascii->fd = fopen(fname,"w+");
    700:         break;
    701:       case FILE_MODE_APPEND_UPDATE:
    702:         /* I really want a file which is opened at the end for updating,
    703:            not a+, which opens at the beginning, but makes writes at the end.
    704:         */
    705:         vascii->fd = fopen(fname,"r+");
    706:         if (!vascii->fd) vascii->fd = fopen(fname,"w+");
    707:         else {
    708:           fseek(vascii->fd, 0, SEEK_END);
    709:         }
    710:         break;
    711:       default:
    712:         SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[vascii->mode]);
    713:       }
    715:     }
    716:   }
    717: #if defined(PETSC_USE_LOG)
    718:   PetscLogObjectState((PetscObject)viewer,"File: %s",name);
    719: #endif
    720:   return 0;
    721: }

    723: PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer,MPI_Comm subcomm,PetscViewer *outviewer)
    724: {
    725:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data,*ovascii;

    727:   PetscViewerASCIIPushSynchronized(viewer);
    729:   /*
    730:      The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
    731:      because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
    732:      (since the count never gets to zero) in some examples this displays information that otherwise would be lost

    734:      This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
    735:      PCView_GASM().
    736:   */
    737:   PetscViewerASCIIPushSynchronized(viewer);
    738:   PetscViewerCreate(subcomm,outviewer);
    739:   PetscViewerSetType(*outviewer,PETSCVIEWERASCII);
    740:   PetscViewerASCIIPushSynchronized(*outviewer);
    741:   ovascii      = (PetscViewer_ASCII*)(*outviewer)->data;
    742:   ovascii->fd  = vascii->fd;
    743:   ovascii->tab = vascii->tab;
    744:   ovascii->closefile = PETSC_FALSE;

    746:   vascii->sviewer = *outviewer;
    747:   (*outviewer)->format  = viewer->format;
    748:   ((PetscViewer_ASCII*)((*outviewer)->data))->bviewer = viewer;
    749:   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer;
    750:   return 0;
    751: }

    753: PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
    754: {
    755:   PetscViewer_ASCII *ascii  = (PetscViewer_ASCII*)viewer->data;

    760:   PetscViewerASCIIPopSynchronized(*outviewer);
    761:   ascii->sviewer             = NULL;
    762:   (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
    763:   PetscViewerDestroy(outviewer);
    764:   PetscViewerASCIIPopSynchronized(viewer);
    765:   return 0;
    766: }

    768: PetscErrorCode  PetscViewerView_ASCII(PetscViewer v,PetscViewer viewer)
    769: {
    770:   PetscViewer_ASCII *ascii = (PetscViewer_ASCII*)v->data;

    772:   if (ascii->filename) {
    773:     PetscViewerASCIIPrintf(viewer,"Filename: %s\n",ascii->filename);
    774:   }
    775:   return 0;
    776: }

    778: /*MC
    779:    PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file

    781: .seealso:  PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD,PetscViewerCreate(), PetscViewerASCIIOpen(),
    782:            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERBINARY, PETSCVIEWERMATLAB,
    783:            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()

    785:   Level: beginner

    787: M*/
    788: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
    789: {
    790:   PetscViewer_ASCII *vascii;

    792:   PetscNewLog(viewer,&vascii);
    793:   viewer->data = (void*)vascii;

    795:   viewer->ops->destroy          = PetscViewerDestroy_ASCII;
    796:   viewer->ops->flush            = PetscViewerFlush_ASCII;
    797:   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_ASCII;
    798:   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
    799:   viewer->ops->view             = PetscViewerView_ASCII;
    800:   viewer->ops->read             = PetscViewerASCIIRead;

    802:   /* defaults to stdout unless set with PetscViewerFileSetName() */
    803:   vascii->fd        = PETSC_STDOUT;
    804:   vascii->mode      = FILE_MODE_WRITE;
    805:   vascii->bviewer   = NULL;
    806:   vascii->subviewer = NULL;
    807:   vascii->sviewer   = NULL;
    808:   vascii->tab       = 0;
    809:   vascii->tab_store = 0;
    810:   vascii->filename  = NULL;
    811:   vascii->closefile = PETSC_TRUE;

    813:   PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_ASCII);
    814:   PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",PetscViewerFileGetName_ASCII);
    815:   PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_ASCII);
    816:   PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_ASCII);
    817:   return 0;
    818: }

    820: /*@C
    821:     PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified file from
    822:     several processors.  Output of the first processor is followed by that of the
    823:     second, etc.

    825:     Not Collective, must call collective PetscViewerFlush() to get the results out

    827:     Input Parameters:
    828: +   viewer - the ASCII PetscViewer
    829: -   format - the usual printf() format string

    831:     Level: intermediate

    833:     Notes:
    834:     You must have previously called PetscViewerASCIIPushSynchronized() to allow this routine to be called.
    835:     Then you can do multiple independent calls to this routine.
    836:     The actual synchronized print is then done using PetscViewerFlush().
    837:     PetscViewerASCIIPopSynchronized() should be then called if we are already done with the synchronized output
    838:     to conclude the "synchronized session".
    839:     So the typical calling sequence looks like
    840: $ PetscViewerASCIIPushSynchronized(viewer);
    841: $ PetscViewerASCIISynchronizedPrintf(viewer, ...);
    842: $ PetscViewerASCIISynchronizedPrintf(viewer, ...);
    843: $ ...
    844: $ PetscViewerFlush(viewer);
    845: $ PetscViewerASCIISynchronizedPrintf(viewer, ...);
    846: $ PetscViewerASCIISynchronizedPrintf(viewer, ...);
    847: $ ...
    848: $ PetscViewerFlush(viewer);
    849: $ PetscViewerASCIIPopSynchronized(viewer);

    851:     Fortran Note:
    852:       Can only print a single character* string

    854: .seealso: PetscViewerASCIIPushSynchronized(), PetscViewerFlush(), PetscViewerASCIIPopSynchronized(),
    855:           PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIIOpen(),
    856:           PetscViewerCreate(), PetscViewerDestroy(), PetscViewerSetType()
    857: @*/
    858: PetscErrorCode  PetscViewerASCIISynchronizedPrintf(PetscViewer viewer,const char format[],...)
    859: {
    860:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
    861:   PetscMPIInt       rank;
    862:   PetscInt          tab = vascii->tab;
    863:   MPI_Comm          comm;
    864:   FILE              *fp;
    865:   PetscBool         iascii,hasbviewer = PETSC_FALSE;
    866:   int               err;

    870:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);

    874:   PetscObjectGetComm((PetscObject)viewer,&comm);
    875:   MPI_Comm_rank(comm,&rank);

    877:   if (vascii->bviewer) {
    878:     hasbviewer = PETSC_TRUE;
    879:     if (rank == 0) {
    880:       vascii = (PetscViewer_ASCII*)vascii->bviewer->data;
    881:       PetscObjectGetComm((PetscObject)viewer,&comm);
    882:       MPI_Comm_rank(comm,&rank);
    883:     }
    884:   }

    886:   fp   = vascii->fd;

    888:   if (rank == 0 && !hasbviewer) {   /* First processor prints immediately to fp */
    889:     va_list Argp;
    890:     /* flush my own messages that I may have queued up */
    891:     PrintfQueue next = vascii->petsc_printfqueuebase,previous;
    892:     PetscInt    i;
    893:     for (i=0; i<vascii->petsc_printfqueuelength; i++) {
    894:       PetscFPrintf(comm,fp,"%s",next->string);
    895:       previous = next;
    896:       next     = next->next;
    897:       PetscFree(previous->string);
    898:       PetscFree(previous);
    899:     }
    900:     vascii->petsc_printfqueue       = NULL;
    901:     vascii->petsc_printfqueuelength = 0;

    903:     while (tab--) {
    904:       PetscFPrintf(PETSC_COMM_SELF,fp,"  ");
    905:     }

    907:     va_start(Argp,format);
    908:     (*PetscVFPrintf)(fp,format,Argp);
    909:     err  = fflush(fp);
    911:     if (petsc_history) {
    912:       va_start(Argp,format);
    913:       (*PetscVFPrintf)(petsc_history,format,Argp);
    914:       err  = fflush(petsc_history);
    916:     }
    917:     va_end(Argp);
    918:   } else { /* other processors add to queue */
    919:     char        *string;
    920:     va_list     Argp;
    921:     size_t      fullLength;
    922:     PrintfQueue next;

    924:     PetscNew(&next);
    925:     if (vascii->petsc_printfqueue) {
    926:       vascii->petsc_printfqueue->next = next;
    927:       vascii->petsc_printfqueue       = next;
    928:     } else {
    929:       vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
    930:     }
    931:     vascii->petsc_printfqueuelength++;
    932:     next->size = QUEUESTRINGSIZE;
    933:     PetscCalloc1(next->size, &next->string);
    934:     string     = next->string;
    935:     tab       *= 2;
    936:     while (tab--) {
    937:       *string++ = ' ';
    938:     }
    939:     va_start(Argp,format);
    940:     PetscVSNPrintf(string,next->size-2*vascii->tab,format,&fullLength,Argp);
    941:     va_end(Argp);
    942:     if (fullLength > (size_t) (next->size-2*vascii->tab)) {
    943:       PetscFree(next->string);
    944:       next->size = fullLength + 2*vascii->tab;
    945:       PetscCalloc1(next->size, &next->string);
    946:       string     = next->string;
    947:       tab        = 2*vascii->tab;
    948:       while (tab--) {
    949:         *string++ = ' ';
    950:       }
    951:       va_start(Argp,format);
    952:       PetscVSNPrintf(string,next->size-2*vascii->tab,format,NULL,Argp);
    953:       va_end(Argp);
    954:     }
    955:   }
    956:   return 0;
    957: }

    959: /*@C
    960:    PetscViewerASCIIRead - Reads from a ASCII file

    962:    Only process 0 in the PetscViewer may call this

    964:    Input Parameters:
    965: +  viewer - the ascii viewer
    966: .  data - location to write the data
    967: .  num - number of items of data to read
    968: -  datatype - type of data to read

    970:    Output Parameters:
    971: .  count - number of items of data actually read, or NULL

    973:    Level: beginner

    975: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerFileSetMode(), PetscViewerFileSetName()
    976:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    977:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
    978: @*/
    979: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype)
    980: {
    981:   PetscViewer_ASCII *vascii = (PetscViewer_ASCII*)viewer->data;
    982:   FILE              *fd = vascii->fd;
    983:   PetscInt           i;
    984:   int                ret = 0;
    985:   PetscMPIInt        rank;

    988:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
    990:   for (i=0; i<num; i++) {
    991:     if (dtype == PETSC_CHAR)         ret = fscanf(fd, "%c",  &(((char*)data)[i]));
    992:     else if (dtype == PETSC_STRING)  ret = fscanf(fd, "%s",  &(((char*)data)[i]));
    993:     else if (dtype == PETSC_INT)     ret = fscanf(fd, "%" PetscInt_FMT,  &(((PetscInt*)data)[i]));
    994:     else if (dtype == PETSC_ENUM)    ret = fscanf(fd, "%d",  &(((int*)data)[i]));
    995:     else if (dtype == PETSC_INT64)   ret = fscanf(fd, "%" PetscInt64_FMT,  &(((PetscInt64*)data)[i]));
    996:     else if (dtype == PETSC_LONG)    ret = fscanf(fd, "%ld", &(((long*)data)[i]));
    997:     else if (dtype == PETSC_FLOAT)   ret = fscanf(fd, "%f",  &(((float*)data)[i]));
    998:     else if (dtype == PETSC_DOUBLE)  ret = fscanf(fd, "%lg", &(((double*)data)[i]));
    999: #if defined(PETSC_USE_REAL___FLOAT128)
    1000:     else if (dtype == PETSC___FLOAT128) {
    1001:       double tmp;
    1002:       ret = fscanf(fd, "%lg", &tmp);
    1003:       ((__float128*)data)[i] = tmp;
    1004:     }
    1005: #endif
    1006:     else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Data type %d not supported", (int) dtype);
    1008:     else if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
    1009:   }
    1010:   if (count) *count = i;
    1012:   return 0;
    1013: }