#include <petsc.h>

int main(int argc, char** argv) {
    PetscInitialize(&argc, &argv, NULL, NULL);
    int rank, size;
    MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
    MPI_Comm_size(PETSC_COMM_WORLD, &size);
    if(size != 3) {
        if(rank == 0)
            printf("Three processes only\n");
        PetscFinalize();
        return 1;
    }
    Vec local;
    Vec global;
    const PetscInt N = 8;
    MPI_Comm subcomm;
    int color;
    int key;
    PetscInt n;
    PetscInt start;
    if(rank == 0) {
        color = key = 0;
        MPI_Comm_split(PETSC_COMM_WORLD, color, key, &subcomm);
        VecCreateMPI(PETSC_COMM_WORLD, N / 2, N, &global);
        VecCreateMPI(subcomm, N / 2, N / 2, &local);
        n = N / 2;
        start = 0;
    }
    else {
        color = 1;
        key = rank - 1;
        MPI_Comm_split(PETSC_COMM_WORLD, color, key, &subcomm);
        VecCreateMPI(PETSC_COMM_WORLD, N / 4, N, &global);
        VecCreateMPI(subcomm, N / 4, N / 2, &local);
        n = N / 4;
        start = color + (rank == 2) * N / 2;
    }
    IS is;
    ISCreateStride(PETSC_COMM_SELF, n, start, 2, &is);
    VecScatter scatter;
    PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO);
    VecView(global, PETSC_VIEWER_STDOUT_WORLD);
    PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);
    PetscViewerPushFormat(PETSC_VIEWER_STDOUT_(subcomm), PETSC_VIEWER_ASCII_INFO);
    PetscInt i;
    for(i = 0; i < 2; ++i) {
        MPI_Barrier(MPI_COMM_WORLD);
        if(i == color)
            VecView(local, PETSC_VIEWER_STDOUT_(subcomm));
        MPI_Barrier(MPI_COMM_WORLD);
    }
    PetscViewerPopFormat(PETSC_VIEWER_STDOUT_(subcomm));
    PetscViewerPushFormat(PETSC_VIEWER_STDOUT_(PETSC_COMM_SELF), PETSC_VIEWER_ASCII_INFO);
    for(i = 0; i < 3; ++i) {
        MPI_Barrier(MPI_COMM_WORLD);
        if(i == rank)
            ISView(is, PETSC_VIEWER_STDOUT_(PETSC_COMM_SELF));
        MPI_Barrier(MPI_COMM_WORLD);
    }
    PetscViewerPopFormat(PETSC_VIEWER_STDOUT_(PETSC_COMM_SELF));
    VecScatterCreate(local, NULL, global, is, &scatter);
    VecScatterDestroy(&scatter);
    ISDestroy(&is);
    VecDestroy(&local);
    VecDestroy(&global);
    PetscFinalize();
    return 0;
}
