static char help[]= "Tests ISView() and ISLoad() \n\n";

#include <petscis.h>
#include <petscviewer.h>

int main(int argc,char **argv)
{
  PetscInt               n = 3, *izero, j, i;
  PetscInt               ix[3][3][3] = {{{3,5,4},{1,7,9},{0,2,8}},
                                        {{0,2,8},{3,5,4},{1,7,9}},
                                        {{1,7,9},{0,2,8},{3,5,4}}};
  IS                     isx[3],il;
  PetscMPIInt            size,rank;
  PetscViewer            vx,vl;
  PetscBool              equal;

  PetscCall(PetscInitialize(&argc,&argv,NULL,help));
  PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
  PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size));
  PetscCheck(size < 4,PETSC_COMM_WORLD,PETSC_ERR_WRONG_MPI_SIZE,"Example only works with up to three processes");

  PetscCall(PetscCalloc1(size*n,&izero));
  for (i = 0; i < 3; i++) {
    PetscCall(ISCreateGeneral(PETSC_COMM_WORLD,n,ix[i][rank],PETSC_COPY_VALUES,&isx[i]));
  }

  for (j = 0; j < 3; j++) {
    PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD,"testfile",FILE_MODE_WRITE,&vx));
    PetscCall(ISView(isx[0],vx));
    PetscCall(PetscViewerDestroy(&vx));

    PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD,"testfile",FILE_MODE_READ,&vl));
    PetscCall(ISCreate(PETSC_COMM_WORLD,&il));
    PetscCall(ISLoad(il,vl));
    PetscCall(ISEqual(il,isx[0],&equal));
    PetscCheck(equal,PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Iteration %" PetscInt_FMT " - Index set loaded from file does not match",j);
    PetscCall(ISDestroy(&il));
    PetscCall(PetscViewerDestroy(&vl));

    PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD,"testfile",FILE_MODE_APPEND,&vx));
    PetscCall(ISView(isx[1],vx));
    PetscCall(ISView(isx[2],vx));
    PetscCall(PetscViewerDestroy(&vx));

    PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD,"testfile",FILE_MODE_READ,&vl));
    for (i = 0; i < 3; i++) {
      PetscCall(ISCreate(PETSC_COMM_WORLD,&il));
      PetscCall(ISLoad(il,vl));
      PetscCall(ISEqual(il,isx[i],&equal));
      PetscCheck(equal,PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Iteration %" PetscInt_FMT " - Index set %" PetscInt_FMT " loaded from file does not match",j,i);
      PetscCall(ISDestroy(&il));
    }
    PetscCall(PetscViewerDestroy(&vl));

    PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD,"testfile",FILE_MODE_READ,&vl));
    for (i = 0; i < 3; i++) {
      PetscCall(ISCreateGeneral(PETSC_COMM_WORLD,n,izero,PETSC_COPY_VALUES,&il));
      PetscCall(ISLoad(il,vl));
      PetscCall(ISEqual(il,isx[i],&equal));
      PetscCheck(equal,PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Iteration %" PetscInt_FMT " - Index set %" PetscInt_FMT " loaded from file does not match",j,i);
      PetscCall(ISDestroy(&il));
    }
    PetscCall(PetscViewerDestroy(&vl));
  }

  for (j = 0; j < 3; j++) {
    PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD,"testfile_noheader",FILE_MODE_WRITE,&vx));
    PetscCall(PetscViewerBinarySetSkipHeader(vx,PETSC_TRUE));
    for (i = 0; i < 3; i++) {
      PetscCall(ISView(isx[i],vx));
    }
    PetscCall(PetscViewerDestroy(&vx));

    PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD,"testfile_noheader",FILE_MODE_READ,&vl));
    PetscCall(PetscViewerBinarySetSkipHeader(vl,PETSC_TRUE));
    for (i = 0; i < 3; i++) {
      PetscCall(ISCreateGeneral(PETSC_COMM_WORLD,n,izero,PETSC_COPY_VALUES,&il));
      PetscCall(ISLoad(il,vl));
      PetscCall(ISEqual(il,isx[i],&equal));
      PetscCheck(equal,PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Iteration %" PetscInt_FMT " - Index set %" PetscInt_FMT " loaded from file does not match",j,i);
      PetscCall(ISDestroy(&il));
    }
    PetscCall(PetscViewerDestroy(&vl));
  }

  for (i = 0; i < 3; i++) {
    PetscCall(ISDestroy(&isx[i]));
  }

  for (j = 0; j < 2; j++) {
    const char *filename  = (j == 0) ? "testfile_isstride" : "testfile_isblock";
    PetscInt    blocksize = (j == 0) ? 1 : size;
    PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,FILE_MODE_WRITE,&vx));
    for (i = 0; i < 3; i++) {
      if (j == 0) {
        PetscCall(ISCreateStride(PETSC_COMM_WORLD,n,rank,rank+1,&isx[i]));
      } else {
        PetscCall(ISCreateBlock(PETSC_COMM_WORLD,blocksize,n,ix[i][rank],PETSC_COPY_VALUES,&isx[i]));
      }
      PetscCall(ISView(isx[i],vx));
      PetscCall(ISToGeneral(isx[i]));
    }
    PetscCall(PetscViewerDestroy(&vx));
    PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,FILE_MODE_READ,&vl));
    for (i = 0; i < 3; i++) {
      PetscCall(ISCreateGeneral(PETSC_COMM_WORLD,blocksize*n,izero,PETSC_COPY_VALUES,&il));
      PetscCall(ISLoad(il,vl));
      PetscCall(ISEqual(il,isx[i],&equal));
      PetscCheck(equal,PETSC_COMM_WORLD,PETSC_ERR_PLIB,"Iteration %" PetscInt_FMT " - Index set %" PetscInt_FMT " loaded from file does not match",j,i);
      PetscCall(ISDestroy(&il));
    }
    PetscCall(PetscViewerDestroy(&vl));
    for (i = 0; i < 3; i++) {
      PetscCall(ISDestroy(&isx[i]));
    }
  }
  PetscCall(PetscFree(izero));

  PetscCall(PetscFinalize());
  return 0;
}

/*TEST

   testset:
      args: -viewer_binary_mpiio 0
      output_file: output/ex2_1.out
      test:
        suffix: stdio_1
        nsize: 1
      test:
        suffix: stdio_2
        nsize: 2
      test:
        suffix: stdio_3
        nsize: 3

   testset:
      requires: mpiio
      args: -viewer_binary_mpiio 1
      output_file: output/ex2_1.out
      test:
        suffix: mpiio_1
        nsize: 1
      test:
        suffix: mpiio_2
        nsize: 2
      test:
        suffix: mpiio_3
        nsize: 3

TEST*/
