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