1*7d26aeb3SVaclav Hapla static char help[] = "Demonstrate HDF5/XDMF load-save-reload cycle\n\n"; 2*7d26aeb3SVaclav Hapla 3*7d26aeb3SVaclav Hapla #include <petscdmplex.h> 4*7d26aeb3SVaclav Hapla #include <petscviewerhdf5.h> 5*7d26aeb3SVaclav Hapla #define EX "ex5.c" 6*7d26aeb3SVaclav Hapla 7*7d26aeb3SVaclav Hapla typedef struct { 8*7d26aeb3SVaclav Hapla char infile[PETSC_MAX_PATH_LEN]; /* Input mesh filename */ 9*7d26aeb3SVaclav Hapla char outfile[PETSC_MAX_PATH_LEN]; /* Dump/reload mesh filename */ 10*7d26aeb3SVaclav Hapla PetscViewerFormat informat; /* Input mesh format */ 11*7d26aeb3SVaclav Hapla PetscViewerFormat outformat; /* Dump/reload mesh format */ 12*7d26aeb3SVaclav Hapla PetscBool redistribute; /* Redistribute the mesh */ 13*7d26aeb3SVaclav Hapla PetscInt ntimes; /* How many times do the cycle */ 14*7d26aeb3SVaclav Hapla } AppCtx; 15*7d26aeb3SVaclav Hapla 16*7d26aeb3SVaclav Hapla static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options) 17*7d26aeb3SVaclav Hapla { 18*7d26aeb3SVaclav Hapla PetscBool flg; 19*7d26aeb3SVaclav Hapla PetscErrorCode ierr; 20*7d26aeb3SVaclav Hapla 21*7d26aeb3SVaclav Hapla PetscFunctionBeginUser; 22*7d26aeb3SVaclav Hapla options->infile[0] = '\0'; 23*7d26aeb3SVaclav Hapla options->outfile[0] = '\0'; 24*7d26aeb3SVaclav Hapla options->informat = PETSC_VIEWER_HDF5_XDMF; 25*7d26aeb3SVaclav Hapla options->outformat = PETSC_VIEWER_HDF5_XDMF; 26*7d26aeb3SVaclav Hapla options->redistribute = PETSC_TRUE; 27*7d26aeb3SVaclav Hapla options->ntimes = 2; 28*7d26aeb3SVaclav Hapla ierr = PetscOptionsBegin(comm, "", "Meshing Problem Options", "DMPLEX");CHKERRQ(ierr); 29*7d26aeb3SVaclav Hapla ierr = PetscOptionsString("-infile", "The input mesh file", EX, options->infile, options->infile, sizeof(options->infile), &flg);CHKERRQ(ierr); 30*7d26aeb3SVaclav Hapla if (!flg) SETERRQ(comm, PETSC_ERR_USER_INPUT, "-infile needs to be specified"); 31*7d26aeb3SVaclav Hapla ierr = PetscOptionsString("-outfile", "The output mesh file (by default it's the same as infile)", EX, options->outfile, options->outfile, sizeof(options->outfile), &flg);CHKERRQ(ierr); 32*7d26aeb3SVaclav Hapla if (!flg) SETERRQ(comm, PETSC_ERR_USER_INPUT, "-outfile needs to be specified"); 33*7d26aeb3SVaclav Hapla ierr = PetscOptionsEnum("-informat", "Input mesh format", EX, PetscViewerFormats, (PetscEnum)options->informat, (PetscEnum*)&options->informat, NULL);CHKERRQ(ierr); 34*7d26aeb3SVaclav Hapla ierr = PetscOptionsEnum("-outformat", "Dump/reload mesh format", EX, PetscViewerFormats, (PetscEnum)options->outformat, (PetscEnum*)&options->outformat, NULL);CHKERRQ(ierr); 35*7d26aeb3SVaclav Hapla ierr = PetscOptionsBool("-redistribute", "Redistribute the mesh", EX, options->redistribute, &options->redistribute, NULL);CHKERRQ(ierr); 36*7d26aeb3SVaclav Hapla ierr = PetscOptionsInt("-ntimes", "How many times do the cycle", EX, options->ntimes, &options->ntimes, NULL);CHKERRQ(ierr); 37*7d26aeb3SVaclav Hapla ierr = PetscOptionsEnd(); 38*7d26aeb3SVaclav Hapla PetscFunctionReturn(0); 39*7d26aeb3SVaclav Hapla }; 40*7d26aeb3SVaclav Hapla 41*7d26aeb3SVaclav Hapla //TODO test DMLabel I/O (not yet working for PETSC_VIEWER_HDF5_XDMF) 42*7d26aeb3SVaclav Hapla int main(int argc, char **argv) 43*7d26aeb3SVaclav Hapla { 44*7d26aeb3SVaclav Hapla AppCtx user; 45*7d26aeb3SVaclav Hapla PetscInt i; 46*7d26aeb3SVaclav Hapla PetscBool flg; 47*7d26aeb3SVaclav Hapla MPI_Comm comm; 48*7d26aeb3SVaclav Hapla PetscMPIInt size; 49*7d26aeb3SVaclav Hapla PetscErrorCode ierr; 50*7d26aeb3SVaclav Hapla const char *filename; 51*7d26aeb3SVaclav Hapla PetscViewerFormat format; 52*7d26aeb3SVaclav Hapla 53*7d26aeb3SVaclav Hapla ierr = PetscInitialize(&argc, &argv, NULL,help);if (ierr) return ierr; 54*7d26aeb3SVaclav Hapla comm = PETSC_COMM_WORLD; 55*7d26aeb3SVaclav Hapla ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 56*7d26aeb3SVaclav Hapla ierr = ProcessOptions(comm, &user);CHKERRQ(ierr); 57*7d26aeb3SVaclav Hapla 58*7d26aeb3SVaclav Hapla /* Use infile for the initial load */ 59*7d26aeb3SVaclav Hapla filename = user.infile; 60*7d26aeb3SVaclav Hapla format = user.informat; 61*7d26aeb3SVaclav Hapla 62*7d26aeb3SVaclav Hapla for (i=0; i<user.ntimes; i++) { 63*7d26aeb3SVaclav Hapla DM dm; 64*7d26aeb3SVaclav Hapla PetscPartitioner part; 65*7d26aeb3SVaclav Hapla PetscViewer v; 66*7d26aeb3SVaclav Hapla 67*7d26aeb3SVaclav Hapla ierr = PetscPrintf(comm, "Begin cycle %D\n",i);CHKERRQ(ierr); 68*7d26aeb3SVaclav Hapla 69*7d26aeb3SVaclav Hapla /* Load data from XDMF into dm in parallel */ 70*7d26aeb3SVaclav Hapla /* We could also use 71*7d26aeb3SVaclav Hapla ierr = DMPlexCreateFromFile(PETSC_COMM_WORLD, user.filename, PETSC_TRUE, &dm);CHKERRQ(ierr); 72*7d26aeb3SVaclav Hapla This currently support a few more formats than DMLoad(). 73*7d26aeb3SVaclav Hapla */ 74*7d26aeb3SVaclav Hapla ierr = PetscViewerHDF5Open(comm, filename, FILE_MODE_READ, &v);CHKERRQ(ierr); 75*7d26aeb3SVaclav Hapla ierr = PetscViewerPushFormat(v, format);CHKERRQ(ierr); 76*7d26aeb3SVaclav Hapla ierr = DMCreate(comm, &dm);CHKERRQ(ierr); 77*7d26aeb3SVaclav Hapla ierr = DMSetType(dm, DMPLEX);CHKERRQ(ierr); 78*7d26aeb3SVaclav Hapla ierr = DMSetOptionsPrefix(dm,"loaded_");CHKERRQ(ierr); 79*7d26aeb3SVaclav Hapla ierr = DMLoad(dm, v);CHKERRQ(ierr); 80*7d26aeb3SVaclav Hapla ierr = DMSetFromOptions(dm);CHKERRQ(ierr); 81*7d26aeb3SVaclav Hapla ierr = DMViewFromOptions(dm, NULL, "-dm_view");CHKERRQ(ierr); 82*7d26aeb3SVaclav Hapla ierr = PetscViewerPopFormat(v);CHKERRQ(ierr); 83*7d26aeb3SVaclav Hapla ierr = PetscViewerDestroy(&v);CHKERRQ(ierr); 84*7d26aeb3SVaclav Hapla 85*7d26aeb3SVaclav Hapla /* Use outfile for all I/O except the very initial load */ 86*7d26aeb3SVaclav Hapla filename = user.outfile; 87*7d26aeb3SVaclav Hapla format = user.outformat; 88*7d26aeb3SVaclav Hapla 89*7d26aeb3SVaclav Hapla /* We just test/demonstrate DM is indeed distributed - unneeded in the application code */ 90*7d26aeb3SVaclav Hapla ierr = DMPlexIsDistributed(dm, &flg);CHKERRQ(ierr); 91*7d26aeb3SVaclav Hapla ierr = PetscPrintf(comm, "Loaded mesh distributed? %s\n", PetscBools[flg]); 92*7d26aeb3SVaclav Hapla 93*7d26aeb3SVaclav Hapla /* Interpolate */ 94*7d26aeb3SVaclav Hapla //TODO we want to be able to do this from options in DMSetFromOptions() probably 95*7d26aeb3SVaclav Hapla //TODO we want to be able to do this in-place 96*7d26aeb3SVaclav Hapla { 97*7d26aeb3SVaclav Hapla DM idm; 98*7d26aeb3SVaclav Hapla 99*7d26aeb3SVaclav Hapla ierr = DMPlexInterpolate(dm, &idm);CHKERRQ(ierr); 100*7d26aeb3SVaclav Hapla ierr = DMDestroy(&dm);CHKERRQ(ierr); 101*7d26aeb3SVaclav Hapla dm = idm; 102*7d26aeb3SVaclav Hapla ierr = DMSetOptionsPrefix(dm,"interpolated_");CHKERRQ(ierr); 103*7d26aeb3SVaclav Hapla ierr = DMSetFromOptions(dm);CHKERRQ(ierr); 104*7d26aeb3SVaclav Hapla ierr = DMViewFromOptions(dm, NULL, "-dm_view");CHKERRQ(ierr); 105*7d26aeb3SVaclav Hapla } 106*7d26aeb3SVaclav Hapla 107*7d26aeb3SVaclav Hapla /* Redistribute */ 108*7d26aeb3SVaclav Hapla //TODO we want to be able to do this from options in DMSetFromOptions() probably 109*7d26aeb3SVaclav Hapla if (user.redistribute) { 110*7d26aeb3SVaclav Hapla DM dmdist; 111*7d26aeb3SVaclav Hapla 112*7d26aeb3SVaclav Hapla ierr = DMPlexGetPartitioner(dm, &part);CHKERRQ(ierr); 113*7d26aeb3SVaclav Hapla ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr); 114*7d26aeb3SVaclav Hapla ierr = DMPlexDistribute(dm, 0, NULL, &dmdist);CHKERRQ(ierr); 115*7d26aeb3SVaclav Hapla //TODO we want to be able to do this in-place 116*7d26aeb3SVaclav Hapla if (dmdist) { 117*7d26aeb3SVaclav Hapla ierr = DMDestroy(&dm);CHKERRQ(ierr); 118*7d26aeb3SVaclav Hapla dm = dmdist; 119*7d26aeb3SVaclav Hapla ierr = DMSetOptionsPrefix(dm,"redistributed_");CHKERRQ(ierr); 120*7d26aeb3SVaclav Hapla ierr = DMSetFromOptions(dm);CHKERRQ(ierr); 121*7d26aeb3SVaclav Hapla ierr = DMViewFromOptions(dm, NULL, "-dm_view");CHKERRQ(ierr); 122*7d26aeb3SVaclav Hapla } 123*7d26aeb3SVaclav Hapla } 124*7d26aeb3SVaclav Hapla 125*7d26aeb3SVaclav Hapla /* Save redistributed dm to XDMF in parallel and destroy it */ 126*7d26aeb3SVaclav Hapla ierr = PetscViewerHDF5Open(comm, user.outfile, FILE_MODE_WRITE, &v);CHKERRQ(ierr); 127*7d26aeb3SVaclav Hapla ierr = PetscViewerPushFormat(v, format);CHKERRQ(ierr); 128*7d26aeb3SVaclav Hapla ierr = DMView(dm, v);CHKERRQ(ierr); 129*7d26aeb3SVaclav Hapla ierr = PetscViewerPopFormat(v);CHKERRQ(ierr); 130*7d26aeb3SVaclav Hapla ierr = PetscViewerDestroy(&v);CHKERRQ(ierr); 131*7d26aeb3SVaclav Hapla ierr = DMDestroy(&dm);CHKERRQ(ierr); 132*7d26aeb3SVaclav Hapla 133*7d26aeb3SVaclav Hapla ierr = PetscPrintf(comm, "End cycle %D\n--------\n",i);CHKERRQ(ierr); 134*7d26aeb3SVaclav Hapla } 135*7d26aeb3SVaclav Hapla 136*7d26aeb3SVaclav Hapla /* Final clean-up */ 137*7d26aeb3SVaclav Hapla ierr = PetscFinalize(); 138*7d26aeb3SVaclav Hapla return ierr; 139*7d26aeb3SVaclav Hapla } 140*7d26aeb3SVaclav Hapla 141*7d26aeb3SVaclav Hapla /*TEST 142*7d26aeb3SVaclav Hapla build: 143*7d26aeb3SVaclav Hapla requires: hdf5 144*7d26aeb3SVaclav Hapla testset: 145*7d26aeb3SVaclav Hapla suffix: 0 146*7d26aeb3SVaclav Hapla requires: !complex 147*7d26aeb3SVaclav Hapla nsize: {{2 4}} 148*7d26aeb3SVaclav Hapla args: -infile ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.h5 -informat hdf5_xdmf 149*7d26aeb3SVaclav Hapla args: -outfile ex5_dump.h5 -outformat {{hdf5_xdmf hdf5_petsc}separate output} 150*7d26aeb3SVaclav Hapla args: -ntimes 3 151*7d26aeb3SVaclav Hapla test: 152*7d26aeb3SVaclav Hapla # this partitioner should not shuffle anything, it should yield the same partititioning as the XDMF reader - added just for testing 153*7d26aeb3SVaclav Hapla suffix: simple 154*7d26aeb3SVaclav Hapla args: -petscpartitioner_type simple 155*7d26aeb3SVaclav Hapla test: 156*7d26aeb3SVaclav Hapla suffix: parmetis 157*7d26aeb3SVaclav Hapla requires: parmetis 158*7d26aeb3SVaclav Hapla args: -petscpartitioner_type parmetis 159*7d26aeb3SVaclav Hapla test: 160*7d26aeb3SVaclav Hapla suffix: ptscotch 161*7d26aeb3SVaclav Hapla requires: ptscotch 162*7d26aeb3SVaclav Hapla args: -petscpartitioner_type ptscotch 163*7d26aeb3SVaclav Hapla TEST*/ 164