xref: /petsc/src/dm/impls/plex/tutorials/ex5.c (revision 7d26aeb39ec76845dd6b7d47f31fd5cebc6b3db9)
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