xref: /petsc/src/dm/impls/da/gr2.c (revision 7d310018ac4022c32c488e7ca2abff34f77ad2aa)
1 
2 /*
3    Plots vectors obtained with DMDACreate2d()
4 */
5 
6 #include <petsc-private/dmdaimpl.h>      /*I  "petscdmda.h"   I*/
7 #include <petsc-private/vecimpl.h>
8 #include <petscdraw.h>
9 #include <petscviewerhdf5.h>
10 
11 /*
12         The data that is passed into the graphics callback
13 */
14 typedef struct {
15   PetscInt    m,n,step,k;
16   PetscReal   min,max,scale;
17   PetscScalar *xy,*v;
18   PetscBool   showgrid;
19   const char  *name0,*name1;
20 } ZoomCtx;
21 
22 /*
23        This does the drawing for one particular field
24     in one particular set of coordinates. It is a callback
25     called from PetscDrawZoom()
26 */
27 #undef __FUNCT__
28 #define __FUNCT__ "VecView_MPI_Draw_DA2d_Zoom"
29 PetscErrorCode VecView_MPI_Draw_DA2d_Zoom(PetscDraw draw,void *ctx)
30 {
31   ZoomCtx        *zctx = (ZoomCtx*)ctx;
32   PetscErrorCode ierr;
33   PetscInt       m,n,i,j,k,step,id,c1,c2,c3,c4;
34   PetscReal      s,min,max,x1,x2,x3,x4,y_1,y2,y3,y4,xmin = PETSC_MAX_REAL,xmax = PETSC_MIN_REAL,ymin = PETSC_MAX_REAL,ymax = PETSC_MIN_REAL;
35   PetscReal      xminf,xmaxf,yminf,ymaxf,w;
36   PetscScalar    *v,*xy;
37   char           value[16];
38   size_t         len;
39 
40   PetscFunctionBegin;
41   m    = zctx->m;
42   n    = zctx->n;
43   step = zctx->step;
44   k    = zctx->k;
45   v    = zctx->v;
46   xy   = zctx->xy;
47   s    = zctx->scale;
48   min  = zctx->min;
49   max  = zctx->max;
50 
51   /* PetscDraw the contour plot patch */
52   for (j=0; j<n-1; j++) {
53     for (i=0; i<m-1; i++) {
54       id   = i+j*m;
55       x1   = PetscRealPart(xy[2*id]);
56       y_1  = PetscRealPart(xy[2*id+1]);
57       c1   = (int)(PETSC_DRAW_BASIC_COLORS+s*(PetscClipInterval(PetscRealPart(v[k+step*id]),min,max)-min));
58       xmin = PetscMin(xmin,x1);
59       ymin = PetscMin(ymin,y_1);
60       xmax = PetscMax(xmax,x1);
61       ymax = PetscMax(ymax,y_1);
62 
63       id   = i+j*m+1;
64       x2   = PetscRealPart(xy[2*id]);
65       y2   = PetscRealPart(xy[2*id+1]);
66       c2   = (int)(PETSC_DRAW_BASIC_COLORS+s*(PetscClipInterval(PetscRealPart(v[k+step*id]),min,max)-min));
67       xmin = PetscMin(xmin,x2);
68       ymin = PetscMin(ymin,y2);
69       xmax = PetscMax(xmax,x2);
70       ymax = PetscMax(ymax,y2);
71 
72       id   = i+j*m+1+m;
73       x3   = PetscRealPart(xy[2*id]);
74       y3   = PetscRealPart(xy[2*id+1]);
75       c3   = (int)(PETSC_DRAW_BASIC_COLORS+s*(PetscClipInterval(PetscRealPart(v[k+step*id]),min,max)-min));
76       xmin = PetscMin(xmin,x3);
77       ymin = PetscMin(ymin,y3);
78       xmax = PetscMax(xmax,x3);
79       ymax = PetscMax(ymax,y3);
80 
81       id = i+j*m+m;
82       x4 = PetscRealPart(xy[2*id]);
83       y4 = PetscRealPart(xy[2*id+1]);
84       c4 = (int)(PETSC_DRAW_BASIC_COLORS+s*(PetscClipInterval(PetscRealPart(v[k+step*id]),min,max)-min));
85       xmin = PetscMin(xmin,x4);
86       ymin = PetscMin(ymin,y4);
87       xmax = PetscMax(xmax,x4);
88       ymax = PetscMax(ymax,y4);
89 
90       ierr = PetscDrawTriangle(draw,x1,y_1,x2,y2,x3,y3,c1,c2,c3);CHKERRQ(ierr);
91       ierr = PetscDrawTriangle(draw,x1,y_1,x3,y3,x4,y4,c1,c3,c4);CHKERRQ(ierr);
92       if (zctx->showgrid) {
93         ierr = PetscDrawLine(draw,x1,y_1,x2,y2,PETSC_DRAW_BLACK);CHKERRQ(ierr);
94         ierr = PetscDrawLine(draw,x2,y2,x3,y3,PETSC_DRAW_BLACK);CHKERRQ(ierr);
95         ierr = PetscDrawLine(draw,x3,y3,x4,y4,PETSC_DRAW_BLACK);CHKERRQ(ierr);
96         ierr = PetscDrawLine(draw,x4,y4,x1,y_1,PETSC_DRAW_BLACK);CHKERRQ(ierr);
97       }
98     }
99   }
100   if (zctx->name0) {
101     PetscReal xl,yl,xr,yr,x,y;
102     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
103     x    = xl + .3*(xr - xl);
104     xl   = xl + .01*(xr - xl);
105     y    = yr - .3*(yr - yl);
106     yl   = yl + .01*(yr - yl);
107     ierr = PetscDrawString(draw,x,yl,PETSC_DRAW_BLACK,zctx->name0);CHKERRQ(ierr);
108     ierr = PetscDrawStringVertical(draw,xl,y,PETSC_DRAW_BLACK,zctx->name1);CHKERRQ(ierr);
109   }
110   /*
111      Ideally we would use the PetscDrawAxis object to manage displaying the coordinate limits
112      but that may require some refactoring.
113   */
114   ierr = MPI_Allreduce(&xmin,&xminf,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
115   ierr = MPI_Allreduce(&xmax,&xmaxf,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
116   ierr = MPI_Allreduce(&ymin,&yminf,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
117   ierr = MPI_Allreduce(&ymax,&ymaxf,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
118   ierr = PetscSNPrintf(value,16,"%f",xminf);CHKERRQ(ierr);
119   ierr = PetscDrawString(draw,xminf,yminf - .05*(ymaxf - yminf),PETSC_DRAW_BLACK,value);CHKERRQ(ierr);
120   ierr = PetscSNPrintf(value,16,"%f",xmaxf);CHKERRQ(ierr);
121   ierr = PetscStrlen(value,&len);CHKERRQ(ierr);
122   ierr = PetscDrawStringGetSize(draw,&w,NULL);CHKERRQ(ierr);
123   ierr = PetscDrawString(draw,xmaxf - len*w,yminf - .05*(ymaxf - yminf),PETSC_DRAW_BLACK,value);CHKERRQ(ierr);
124   ierr = PetscSNPrintf(value,16,"%f",yminf);CHKERRQ(ierr);
125   ierr = PetscDrawString(draw,xminf - .05*(xmaxf - xminf),yminf,PETSC_DRAW_BLACK,value);CHKERRQ(ierr);
126   ierr = PetscSNPrintf(value,16,"%f",ymaxf);CHKERRQ(ierr);
127   ierr = PetscDrawString(draw,xminf - .05*(xmaxf - xminf),ymaxf,PETSC_DRAW_BLACK,value);CHKERRQ(ierr);
128   PetscFunctionReturn(0);
129 }
130 
131 #undef __FUNCT__
132 #define __FUNCT__ "VecView_MPI_Draw_DA2d"
133 PetscErrorCode VecView_MPI_Draw_DA2d(Vec xin,PetscViewer viewer)
134 {
135   DM                 da,dac,dag;
136   PetscErrorCode     ierr;
137   PetscMPIInt        rank;
138   PetscInt           N,s,M,w,ncoors = 4;
139   const PetscInt     *lx,*ly;
140   PetscReal          coors[4],ymin,ymax,xmin,xmax;
141   PetscDraw          draw,popup;
142   PetscBool          isnull,useports = PETSC_FALSE;
143   MPI_Comm           comm;
144   Vec                xlocal,xcoor,xcoorl;
145   DMBoundaryType     bx,by;
146   DMDAStencilType    st;
147   ZoomCtx            zctx;
148   PetscDrawViewPorts *ports = NULL;
149   PetscViewerFormat  format;
150   PetscInt           *displayfields;
151   PetscInt           ndisplayfields,i,nbounds;
152   const PetscReal    *bounds;
153 
154   PetscFunctionBegin;
155   zctx.showgrid = PETSC_FALSE;
156 
157   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
158   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
159   ierr = PetscViewerDrawGetBounds(viewer,&nbounds,&bounds);CHKERRQ(ierr);
160 
161   ierr = VecGetDM(xin,&da);CHKERRQ(ierr);
162   if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA");
163 
164   ierr = PetscObjectGetComm((PetscObject)xin,&comm);CHKERRQ(ierr);
165   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
166 
167   ierr = DMDAGetInfo(da,0,&M,&N,0,&zctx.m,&zctx.n,0,&w,&s,&bx,&by,0,&st);CHKERRQ(ierr);
168   ierr = DMDAGetOwnershipRanges(da,&lx,&ly,NULL);CHKERRQ(ierr);
169 
170   /*
171         Obtain a sequential vector that is going to contain the local values plus ONE layer of
172      ghosted values to draw the graphics from. We also need its corresponding DMDA (dac) that will
173      update the local values pluse ONE layer of ghost values.
174   */
175   ierr = PetscObjectQuery((PetscObject)da,"GraphicsGhosted",(PetscObject*)&xlocal);CHKERRQ(ierr);
176   if (!xlocal) {
177     if (bx !=  DM_BOUNDARY_NONE || by !=  DM_BOUNDARY_NONE || s != 1 || st != DMDA_STENCIL_BOX) {
178       /*
179          if original da is not of stencil width one, or periodic or not a box stencil then
180          create a special DMDA to handle one level of ghost points for graphics
181       */
182       ierr = DMDACreate2d(comm,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,M,N,zctx.m,zctx.n,w,1,lx,ly,&dac);CHKERRQ(ierr);
183       ierr = PetscInfo(da,"Creating auxilary DMDA for managing graphics ghost points\n");CHKERRQ(ierr);
184     } else {
185       /* otherwise we can use the da we already have */
186       dac = da;
187     }
188     /* create local vector for holding ghosted values used in graphics */
189     ierr = DMCreateLocalVector(dac,&xlocal);CHKERRQ(ierr);
190     if (dac != da) {
191       /* don't keep any public reference of this DMDA, is is only available through xlocal */
192       ierr = PetscObjectDereference((PetscObject)dac);CHKERRQ(ierr);
193     } else {
194       /* remove association between xlocal and da, because below we compose in the opposite
195          direction and if we left this connect we'd get a loop, so the objects could
196          never be destroyed */
197       ierr = PetscObjectRemoveReference((PetscObject)xlocal,"__PETSc_dm");CHKERRQ(ierr);
198     }
199     ierr = PetscObjectCompose((PetscObject)da,"GraphicsGhosted",(PetscObject)xlocal);CHKERRQ(ierr);
200     ierr = PetscObjectDereference((PetscObject)xlocal);CHKERRQ(ierr);
201   } else {
202     if (bx !=  DM_BOUNDARY_NONE || by !=  DM_BOUNDARY_NONE || s != 1 || st != DMDA_STENCIL_BOX) {
203       ierr = VecGetDM(xlocal, &dac);CHKERRQ(ierr);
204     } else {
205       dac = da;
206     }
207   }
208 
209   /*
210       Get local (ghosted) values of vector
211   */
212   ierr = DMGlobalToLocalBegin(dac,xin,INSERT_VALUES,xlocal);CHKERRQ(ierr);
213   ierr = DMGlobalToLocalEnd(dac,xin,INSERT_VALUES,xlocal);CHKERRQ(ierr);
214   ierr = VecGetArray(xlocal,&zctx.v);CHKERRQ(ierr);
215 
216   /* get coordinates of nodes */
217   ierr = DMGetCoordinates(da,&xcoor);CHKERRQ(ierr);
218   if (!xcoor) {
219     ierr = DMDASetUniformCoordinates(da,0.0,1.0,0.0,1.0,0.0,0.0);CHKERRQ(ierr);
220     ierr = DMGetCoordinates(da,&xcoor);CHKERRQ(ierr);
221   }
222 
223   /*
224       Determine the min and max  coordinates in plot
225   */
226   ierr     = VecStrideMin(xcoor,0,NULL,&xmin);CHKERRQ(ierr);
227   ierr     = VecStrideMax(xcoor,0,NULL,&xmax);CHKERRQ(ierr);
228   ierr     = VecStrideMin(xcoor,1,NULL,&ymin);CHKERRQ(ierr);
229   ierr     = VecStrideMax(xcoor,1,NULL,&ymax);CHKERRQ(ierr);
230   coors[0] = xmin - .05*(xmax- xmin); coors[2] = xmax + .05*(xmax - xmin);
231   coors[1] = ymin - .05*(ymax- ymin); coors[3] = ymax + .05*(ymax - ymin);
232   ierr     = PetscInfo4(da,"Preparing DMDA 2d contour plot coordinates %g %g %g %g\n",(double)coors[0],(double)coors[1],(double)coors[2],(double)coors[3]);CHKERRQ(ierr);
233 
234   ierr = PetscOptionsGetRealArray(NULL,"-draw_coordinates",coors,&ncoors,NULL);CHKERRQ(ierr);
235 
236   /*
237        get local ghosted version of coordinates
238   */
239   ierr = PetscObjectQuery((PetscObject)da,"GraphicsCoordinateGhosted",(PetscObject*)&xcoorl);CHKERRQ(ierr);
240   if (!xcoorl) {
241     /* create DMDA to get local version of graphics */
242     ierr = DMDACreate2d(comm,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,M,N,zctx.m,zctx.n,2,1,lx,ly,&dag);CHKERRQ(ierr);
243     ierr = PetscInfo(dag,"Creating auxilary DMDA for managing graphics coordinates ghost points\n");CHKERRQ(ierr);
244     ierr = DMCreateLocalVector(dag,&xcoorl);CHKERRQ(ierr);
245     ierr = PetscObjectCompose((PetscObject)da,"GraphicsCoordinateGhosted",(PetscObject)xcoorl);CHKERRQ(ierr);
246     ierr = PetscObjectDereference((PetscObject)dag);CHKERRQ(ierr);
247     ierr = PetscObjectDereference((PetscObject)xcoorl);CHKERRQ(ierr);
248   } else {
249     ierr = VecGetDM(xcoorl,&dag);CHKERRQ(ierr);
250   }
251   ierr = DMGlobalToLocalBegin(dag,xcoor,INSERT_VALUES,xcoorl);CHKERRQ(ierr);
252   ierr = DMGlobalToLocalEnd(dag,xcoor,INSERT_VALUES,xcoorl);CHKERRQ(ierr);
253   ierr = VecGetArray(xcoorl,&zctx.xy);CHKERRQ(ierr);
254 
255   /*
256         Get information about size of area each processor must do graphics for
257   */
258   ierr = DMDAGetInfo(dac,0,&M,&N,0,0,0,0,&zctx.step,0,&bx,&by,0,0);CHKERRQ(ierr);
259   ierr = DMDAGetGhostCorners(dac,0,0,0,&zctx.m,&zctx.n,0);CHKERRQ(ierr);
260 
261   ierr = PetscOptionsGetBool(NULL,"-draw_contour_grid",&zctx.showgrid,NULL);CHKERRQ(ierr);
262 
263   ierr = DMDASelectFields(da,&ndisplayfields,&displayfields);CHKERRQ(ierr);
264 
265   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
266   ierr = PetscOptionsGetBool(NULL,"-draw_ports",&useports,NULL);CHKERRQ(ierr);
267   if (useports || format == PETSC_VIEWER_DRAW_PORTS) {
268     ierr       = PetscDrawSynchronizedClear(draw);CHKERRQ(ierr);
269     ierr       = PetscDrawViewPortsCreate(draw,ndisplayfields,&ports);CHKERRQ(ierr);
270     zctx.name0 = 0;
271     zctx.name1 = 0;
272   } else {
273     ierr = DMDAGetCoordinateName(da,0,&zctx.name0);CHKERRQ(ierr);
274     ierr = DMDAGetCoordinateName(da,1,&zctx.name1);CHKERRQ(ierr);
275   }
276 
277   /*
278      Loop over each field; drawing each in a different window
279   */
280   for (i=0; i<ndisplayfields; i++) {
281     zctx.k = displayfields[i];
282     if (useports) {
283       ierr = PetscDrawViewPortsSet(ports,i);CHKERRQ(ierr);
284     } else {
285       ierr = PetscViewerDrawGetDraw(viewer,i,&draw);CHKERRQ(ierr);
286     }
287 
288     /*
289         Determine the min and max color in plot
290     */
291     ierr = VecStrideMin(xin,zctx.k,NULL,&zctx.min);CHKERRQ(ierr);
292     ierr = VecStrideMax(xin,zctx.k,NULL,&zctx.max);CHKERRQ(ierr);
293     if (zctx.k < nbounds) {
294       zctx.min = bounds[2*zctx.k];
295       zctx.max = bounds[2*zctx.k+1];
296     }
297     if (zctx.min == zctx.max) {
298       zctx.min -= 1.e-12;
299       zctx.max += 1.e-12;
300     }
301 
302     if (!rank) {
303       const char *title;
304 
305       ierr = DMDAGetFieldName(da,zctx.k,&title);CHKERRQ(ierr);
306       if (title) {
307         ierr = PetscDrawSetTitle(draw,title);CHKERRQ(ierr);
308       }
309     }
310     ierr = PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);CHKERRQ(ierr);
311     ierr = PetscInfo2(da,"DMDA 2d contour plot min %g max %g\n",(double)zctx.min,(double)zctx.max);CHKERRQ(ierr);
312 
313     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
314     if (popup) {ierr = PetscDrawScalePopup(popup,zctx.min,zctx.max);CHKERRQ(ierr);}
315 
316     zctx.scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/(zctx.max - zctx.min);
317 
318     ierr = PetscDrawZoom(draw,VecView_MPI_Draw_DA2d_Zoom,&zctx);CHKERRQ(ierr);
319   }
320   ierr = PetscFree(displayfields);CHKERRQ(ierr);
321   ierr = PetscDrawViewPortsDestroy(ports);CHKERRQ(ierr);
322 
323   ierr = VecRestoreArray(xcoorl,&zctx.xy);CHKERRQ(ierr);
324   ierr = VecRestoreArray(xlocal,&zctx.v);CHKERRQ(ierr);
325   PetscFunctionReturn(0);
326 }
327 
328 #if defined(PETSC_HAVE_HDF5)
329 #undef __FUNCT__
330 #define __FUNCT__ "VecGetHDF5ChunkSize"
331 static PetscErrorCode VecGetHDF5ChunkSize(DM_DA *da, Vec xin, PetscInt timestep, hsize_t *chunkDims)
332 {
333   PetscMPIInt comm_size;
334   PetscErrorCode ierr;
335   hsize_t chunk_size, target_size, dim;
336   hsize_t vec_size = sizeof(PetscScalar)*da->M*da->N*da->P*da->w;
337   hsize_t avg_local_vec_size,KiB = 1024,MiB = KiB*KiB,GiB = MiB*KiB,min_size = MiB;
338   hsize_t max_chunks = 64*KiB;                                              /* HDF5 internal limitation */
339   hsize_t max_chunk_size = 4*GiB;                                           /* HDF5 internal limitation */
340   PetscInt zslices=da->p, yslices=da->n, xslices=da->m;
341 
342   PetscFunctionBegin;
343   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)xin), &comm_size);CHKERRQ(ierr);
344   avg_local_vec_size = (hsize_t) ceil(vec_size*1.0/comm_size);      /* we will attempt to use this as the chunk size */
345 
346   target_size = (hsize_t) ceil(PetscMin(vec_size,
347                                         PetscMin(max_chunk_size,
348                                                  PetscMax(avg_local_vec_size,
349                                                           PetscMax(ceil(vec_size*1.0/max_chunks),
350                                                                    min_size)))));
351   /* following line uses sizeof(PetscReal) instead of sizeof(PetscScalar) because the last dimension of chunkDims[] captures the 2* when complex numbers are being used */
352   chunk_size = (hsize_t) PetscMax(1,chunkDims[0])*PetscMax(1,chunkDims[1])*PetscMax(1,chunkDims[2])*PetscMax(1,chunkDims[3])*PetscMax(1,chunkDims[4])*PetscMax(1,chunkDims[5])*sizeof(PetscReal);
353 
354   /*
355    if size/rank > max_chunk_size, we need radical measures: even going down to
356    avg_local_vec_size is not enough, so we simply use chunk size of 4 GiB no matter
357    what, composed in the most efficient way possible.
358    N.B. this minimises the number of chunks, which may or may not be the optimal
359    solution. In a BG, for example, the optimal solution is probably to make # chunks = #
360    IO nodes involved, but this author has no access to a BG to figure out how to
361    reliably find the right number. And even then it may or may not be enough.
362    */
363   if (avg_local_vec_size > max_chunk_size) {
364     /* check if we can just split local z-axis: is that enough? */
365     zslices = (PetscInt)ceil(vec_size*1.0/(da->p*max_chunk_size))*zslices;
366     if (zslices > da->P) {
367       /* lattice is too large in xy-directions, splitting z only is not enough */
368       zslices = da->P;
369       yslices= (PetscInt)ceil(vec_size*1.0/(zslices*da->n*max_chunk_size))*yslices;
370       if (yslices > da->N) {
371 	/* lattice is too large in x-direction, splitting along z, y is not enough */
372 	yslices = da->N;
373 	xslices= (PetscInt)ceil(vec_size*1.0/(zslices*yslices*da->m*max_chunk_size))*xslices;
374       }
375     }
376     dim = 0;
377     if (timestep >= 0) {
378       ++dim;
379     }
380     /* prefer to split z-axis, even down to planar slices */
381     if (da->dim == 3) {
382       chunkDims[dim++] = (hsize_t) da->P/zslices;
383       chunkDims[dim++] = (hsize_t) da->N/yslices;
384       chunkDims[dim++] = (hsize_t) da->M/xslices;
385     } else {
386       /* This is a 2D world exceeding 4GiB in size; yes, I've seen them, even used myself */
387       chunkDims[dim++] = (hsize_t) da->N/yslices;
388       chunkDims[dim++] = (hsize_t) da->M/xslices;
389     }
390     chunk_size = (hsize_t) PetscMax(1,chunkDims[0])*PetscMax(1,chunkDims[1])*PetscMax(1,chunkDims[2])*PetscMax(1,chunkDims[3])*PetscMax(1,chunkDims[4])*PetscMax(1,chunkDims[5])*sizeof(double);
391   } else {
392     if (target_size < chunk_size) {
393       /* only change the defaults if target_size < chunk_size */
394       dim = 0;
395       if (timestep >= 0) {
396 	++dim;
397       }
398       /* prefer to split z-axis, even down to planar slices */
399       if (da->dim == 3) {
400 	/* try splitting the z-axis to core-size bits, i.e. divide chunk size by # comm_size in z-direction */
401 	if (target_size >= chunk_size/da->p) {
402 	  /* just make chunks the size of <local_z>x<whole_world_y>x<whole_world_x>x<dof> */
403 	  chunkDims[dim] = (hsize_t) ceil(da->P*1.0/da->p);
404 	} else {
405 	  /* oops, just splitting the z-axis is NOT ENOUGH, need to split more; let's be
406            radical and let everyone write all they've got */
407 	  chunkDims[dim++] = (hsize_t) ceil(da->P*1.0/da->p);
408 	  chunkDims[dim++] = (hsize_t) ceil(da->N*1.0/da->n);
409 	  chunkDims[dim++] = (hsize_t) ceil(da->M*1.0/da->m);
410 	}
411       } else {
412 	/* This is a 2D world exceeding 4GiB in size; yes, I've seen them, even used myself */
413 	if (target_size >= chunk_size/da->n) {
414 	  /* just make chunks the size of <local_z>x<whole_world_y>x<whole_world_x>x<dof> */
415 	  chunkDims[dim] = (hsize_t) ceil(da->N*1.0/da->n);
416 	} else {
417 	  /* oops, just splitting the z-axis is NOT ENOUGH, need to split more; let's be
418 	   radical and let everyone write all they've got */
419 	  chunkDims[dim++] = (hsize_t) ceil(da->N*1.0/da->n);
420 	  chunkDims[dim++] = (hsize_t) ceil(da->M*1.0/da->m);
421 	}
422 
423       }
424       chunk_size = (hsize_t) PetscMax(1,chunkDims[0])*PetscMax(1,chunkDims[1])*PetscMax(1,chunkDims[2])*PetscMax(1,chunkDims[3])*PetscMax(1,chunkDims[4])*PetscMax(1,chunkDims[5])*sizeof(double);
425     } else {
426       /* precomputed chunks are fine, we don't need to do anything */
427     }
428   }
429   PetscFunctionReturn(0);
430 }
431 #endif
432 
433 #if defined(PETSC_HAVE_HDF5)
434 #undef __FUNCT__
435 #define __FUNCT__ "VecView_MPI_HDF5_DA"
436 PetscErrorCode VecView_MPI_HDF5_DA(Vec xin,PetscViewer viewer)
437 {
438   DM             dm;
439   DM_DA          *da;
440   hid_t          filespace;  /* file dataspace identifier */
441   hid_t          chunkspace; /* chunk dataset property identifier */
442   hid_t          plist_id;   /* property list identifier */
443   hid_t          dset_id;    /* dataset identifier */
444   hid_t          memspace;   /* memory dataspace identifier */
445   hid_t          file_id;
446   hid_t          group;
447   hid_t          scalartype; /* scalar type (H5T_NATIVE_FLOAT or H5T_NATIVE_DOUBLE) */
448   herr_t         status;
449   hsize_t        dim;
450   hsize_t        maxDims[6]={0}, dims[6]={0}, chunkDims[6]={0}, count[6]={0}, offset[6]={0}; /* we depend on these being sane later on  */
451   PetscInt       timestep;
452   PetscScalar    *x;
453   const char     *vecname;
454   PetscErrorCode ierr;
455 
456   PetscFunctionBegin;
457   ierr = PetscViewerHDF5OpenGroup(viewer, &file_id, &group);CHKERRQ(ierr);
458   ierr = PetscViewerHDF5GetTimestep(viewer, &timestep);CHKERRQ(ierr);
459 
460   ierr = VecGetDM(xin,&dm);CHKERRQ(ierr);
461   if (!dm) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA");
462   da = (DM_DA*)dm->data;
463 
464   /* Create the dataspace for the dataset.
465    *
466    * dims - holds the current dimensions of the dataset
467    *
468    * maxDims - holds the maximum dimensions of the dataset (unlimited
469    * for the number of time steps with the current dimensions for the
470    * other dimensions; so only additional time steps can be added).
471    *
472    * chunkDims - holds the size of a single time step (required to
473    * permit extending dataset).
474    */
475   dim = 0;
476   if (timestep >= 0) {
477     dims[dim]      = timestep+1;
478     maxDims[dim]   = H5S_UNLIMITED;
479     chunkDims[dim] = 1;
480     ++dim;
481   }
482   if (da->dim == 3) {
483     ierr           = PetscHDF5IntCast(da->P,dims+dim);CHKERRQ(ierr);
484     maxDims[dim]   = dims[dim];
485     chunkDims[dim] = dims[dim];
486     ++dim;
487   }
488   if (da->dim > 1) {
489     ierr           = PetscHDF5IntCast(da->N,dims+dim);CHKERRQ(ierr);
490     maxDims[dim]   = dims[dim];
491     chunkDims[dim] = dims[dim];
492     ++dim;
493   }
494   ierr           = PetscHDF5IntCast(da->M,dims+dim);CHKERRQ(ierr);
495   maxDims[dim]   = dims[dim];
496   chunkDims[dim] = dims[dim];
497   ++dim;
498   if (da->w > 1) {
499     ierr           = PetscHDF5IntCast(da->w,dims+dim);CHKERRQ(ierr);
500     maxDims[dim]   = dims[dim];
501     chunkDims[dim] = dims[dim];
502     ++dim;
503   }
504 #if defined(PETSC_USE_COMPLEX)
505   dims[dim]      = 2;
506   maxDims[dim]   = dims[dim];
507   chunkDims[dim] = dims[dim];
508   ++dim;
509 #endif
510 
511   ierr = VecGetHDF5ChunkSize(da, xin, timestep, chunkDims); CHKERRQ(ierr);
512 
513   filespace = H5Screate_simple(dim, dims, maxDims);
514   if (filespace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Screate_simple()");
515 
516 #if defined(PETSC_USE_REAL_SINGLE)
517   scalartype = H5T_NATIVE_FLOAT;
518 #elif defined(PETSC_USE_REAL___FLOAT128)
519 #error "HDF5 output with 128 bit floats not supported."
520 #else
521   scalartype = H5T_NATIVE_DOUBLE;
522 #endif
523 
524   /* Create the dataset with default properties and close filespace */
525   ierr = PetscObjectGetName((PetscObject)xin,&vecname);CHKERRQ(ierr);
526   if (!H5Lexists(group, vecname, H5P_DEFAULT)) {
527     /* Create chunk */
528     chunkspace = H5Pcreate(H5P_DATASET_CREATE);
529     if (chunkspace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Pcreate()");
530     status = H5Pset_chunk(chunkspace, dim, chunkDims);CHKERRQ(status);
531 
532 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
533     dset_id = H5Dcreate2(group, vecname, scalartype, filespace, H5P_DEFAULT, chunkspace, H5P_DEFAULT);
534 #else
535     dset_id = H5Dcreate(group, vecname, scalartype, filespace, H5P_DEFAULT);
536 #endif
537     if (dset_id == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Dcreate2()");
538   } else {
539     dset_id = H5Dopen2(group, vecname, H5P_DEFAULT);
540     status  = H5Dset_extent(dset_id, dims);CHKERRQ(status);
541   }
542   status = H5Sclose(filespace);CHKERRQ(status);
543 
544   /* Each process defines a dataset and writes it to the hyperslab in the file */
545   dim = 0;
546   if (timestep >= 0) {
547     offset[dim] = timestep;
548     ++dim;
549   }
550   if (da->dim == 3) {ierr = PetscHDF5IntCast(da->zs,offset + dim++);CHKERRQ(ierr);}
551   if (da->dim > 1)  {ierr = PetscHDF5IntCast(da->ys,offset + dim++);CHKERRQ(ierr);}
552   ierr = PetscHDF5IntCast(da->xs/da->w,offset + dim++);CHKERRQ(ierr);
553   if (da->w > 1) offset[dim++] = 0;
554 #if defined(PETSC_USE_COMPLEX)
555   offset[dim++] = 0;
556 #endif
557   dim = 0;
558   if (timestep >= 0) {
559     count[dim] = 1;
560     ++dim;
561   }
562   if (da->dim == 3) {ierr = PetscHDF5IntCast(da->ze - da->zs,count + dim++);CHKERRQ(ierr);}
563   if (da->dim > 1)  {ierr = PetscHDF5IntCast(da->ye - da->ys,count + dim++);CHKERRQ(ierr);}
564   ierr = PetscHDF5IntCast((da->xe - da->xs)/da->w,count + dim++);CHKERRQ(ierr);
565   if (da->w > 1) {ierr = PetscHDF5IntCast(da->w,count + dim++);CHKERRQ(ierr);}
566 #if defined(PETSC_USE_COMPLEX)
567   count[dim++] = 2;
568 #endif
569   memspace = H5Screate_simple(dim, count, NULL);
570   if (memspace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Screate_simple()");
571 
572   filespace = H5Dget_space(dset_id);
573   if (filespace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Dget_space()");
574   status = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset, NULL, count, NULL);CHKERRQ(status);
575 
576   /* Create property list for collective dataset write */
577   plist_id = H5Pcreate(H5P_DATASET_XFER);
578   if (plist_id == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Pcreate()");
579 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
580   status = H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);CHKERRQ(status);
581 #endif
582   /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */
583 
584   ierr   = VecGetArray(xin, &x);CHKERRQ(ierr);
585   status = H5Dwrite(dset_id, scalartype, memspace, filespace, plist_id, x);CHKERRQ(status);
586   status = H5Fflush(file_id, H5F_SCOPE_GLOBAL);CHKERRQ(status);
587   ierr   = VecRestoreArray(xin, &x);CHKERRQ(ierr);
588 
589   /* Close/release resources */
590   if (group != file_id) {
591     status = H5Gclose(group);CHKERRQ(status);
592   }
593   status = H5Pclose(plist_id);CHKERRQ(status);
594   status = H5Sclose(filespace);CHKERRQ(status);
595   status = H5Sclose(memspace);CHKERRQ(status);
596   status = H5Dclose(dset_id);CHKERRQ(status);
597   ierr   = PetscInfo1(xin,"Wrote Vec object with name %s\n",vecname);CHKERRQ(ierr);
598   PetscFunctionReturn(0);
599 }
600 #endif
601 
602 extern PetscErrorCode VecView_MPI_Draw_DA1d(Vec,PetscViewer);
603 
604 #if defined(PETSC_HAVE_MPIIO)
605 #undef __FUNCT__
606 #define __FUNCT__ "DMDAArrayMPIIO"
607 static PetscErrorCode DMDAArrayMPIIO(DM da,PetscViewer viewer,Vec xin,PetscBool write)
608 {
609   PetscErrorCode    ierr;
610   MPI_File          mfdes;
611   PetscMPIInt       gsizes[4],lsizes[4],lstarts[4],asiz,dof;
612   MPI_Datatype      view;
613   const PetscScalar *array;
614   MPI_Offset        off;
615   MPI_Aint          ub,ul;
616   PetscInt          type,rows,vecrows,tr[2];
617   DM_DA             *dd = (DM_DA*)da->data;
618 
619   PetscFunctionBegin;
620   ierr = VecGetSize(xin,&vecrows);CHKERRQ(ierr);
621   if (!write) {
622     /* Read vector header. */
623     ierr = PetscViewerBinaryRead(viewer,tr,2,PETSC_INT);CHKERRQ(ierr);
624     type = tr[0];
625     rows = tr[1];
626     if (type != VEC_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONG,"Not vector next in file");
627     if (rows != vecrows) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_SIZ,"Vector in file not same size as DMDA vector");
628   } else {
629     tr[0] = VEC_FILE_CLASSID;
630     tr[1] = vecrows;
631     ierr  = PetscViewerBinaryWrite(viewer,tr,2,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
632   }
633 
634   ierr       = PetscMPIIntCast(dd->w,&dof);CHKERRQ(ierr);
635   gsizes[0]  = dof;
636   ierr       = PetscMPIIntCast(dd->M,gsizes+1);CHKERRQ(ierr);
637   ierr       = PetscMPIIntCast(dd->N,gsizes+2);CHKERRQ(ierr);
638   ierr       = PetscMPIIntCast(dd->P,gsizes+3);CHKERRQ(ierr);
639   lsizes[0]  = dof;
640   ierr       = PetscMPIIntCast((dd->xe-dd->xs)/dof,lsizes+1);CHKERRQ(ierr);
641   ierr       = PetscMPIIntCast(dd->ye-dd->ys,lsizes+2);CHKERRQ(ierr);
642   ierr       = PetscMPIIntCast(dd->ze-dd->zs,lsizes+3);CHKERRQ(ierr);
643   lstarts[0] = 0;
644   ierr       = PetscMPIIntCast(dd->xs/dof,lstarts+1);CHKERRQ(ierr);
645   ierr       = PetscMPIIntCast(dd->ys,lstarts+2);CHKERRQ(ierr);
646   ierr       = PetscMPIIntCast(dd->zs,lstarts+3);CHKERRQ(ierr);
647   ierr       = MPI_Type_create_subarray(dd->dim+1,gsizes,lsizes,lstarts,MPI_ORDER_FORTRAN,MPIU_SCALAR,&view);CHKERRQ(ierr);
648   ierr       = MPI_Type_commit(&view);CHKERRQ(ierr);
649 
650   ierr = PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);CHKERRQ(ierr);
651   ierr = PetscViewerBinaryGetMPIIOOffset(viewer,&off);CHKERRQ(ierr);
652   ierr = MPI_File_set_view(mfdes,off,MPIU_SCALAR,view,(char*)"native",MPI_INFO_NULL);CHKERRQ(ierr);
653   ierr = VecGetArrayRead(xin,&array);CHKERRQ(ierr);
654   asiz = lsizes[1]*(lsizes[2] > 0 ? lsizes[2] : 1)*(lsizes[3] > 0 ? lsizes[3] : 1)*dof;
655   if (write) {
656     ierr = MPIU_File_write_all(mfdes,(PetscScalar*)array,asiz,MPIU_SCALAR,MPI_STATUS_IGNORE);CHKERRQ(ierr);
657   } else {
658     ierr = MPIU_File_read_all(mfdes,(PetscScalar*)array,asiz,MPIU_SCALAR,MPI_STATUS_IGNORE);CHKERRQ(ierr);
659   }
660   ierr = MPI_Type_get_extent(view,&ul,&ub);CHKERRQ(ierr);
661   ierr = PetscViewerBinaryAddMPIIOOffset(viewer,ub);CHKERRQ(ierr);
662   ierr = VecRestoreArrayRead(xin,&array);CHKERRQ(ierr);
663   ierr = MPI_Type_free(&view);CHKERRQ(ierr);
664   PetscFunctionReturn(0);
665 }
666 #endif
667 
668 #undef __FUNCT__
669 #define __FUNCT__ "VecView_MPI_DA"
670 PetscErrorCode  VecView_MPI_DA(Vec xin,PetscViewer viewer)
671 {
672   DM                da;
673   PetscErrorCode    ierr;
674   PetscInt          dim;
675   Vec               natural;
676   PetscBool         isdraw,isvtk;
677 #if defined(PETSC_HAVE_HDF5)
678   PetscBool         ishdf5;
679 #endif
680   const char        *prefix,*name;
681   PetscViewerFormat format;
682 
683   PetscFunctionBegin;
684   ierr = VecGetDM(xin,&da);CHKERRQ(ierr);
685   if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA");
686   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
687   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERVTK,&isvtk);CHKERRQ(ierr);
688 #if defined(PETSC_HAVE_HDF5)
689   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
690 #endif
691   if (isdraw) {
692     ierr = DMDAGetInfo(da,&dim,0,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
693     if (dim == 1) {
694       ierr = VecView_MPI_Draw_DA1d(xin,viewer);CHKERRQ(ierr);
695     } else if (dim == 2) {
696       ierr = VecView_MPI_Draw_DA2d(xin,viewer);CHKERRQ(ierr);
697     } else SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Cannot graphically view vector associated with this dimensional DMDA %D",dim);
698   } else if (isvtk) {           /* Duplicate the Vec and hold a reference to the DM */
699     Vec Y;
700     ierr = PetscObjectReference((PetscObject)da);CHKERRQ(ierr);
701     ierr = VecDuplicate(xin,&Y);CHKERRQ(ierr);
702     if (((PetscObject)xin)->name) {
703       /* If xin was named, copy the name over to Y. The duplicate names are safe because nobody else will ever see Y. */
704       ierr = PetscObjectSetName((PetscObject)Y,((PetscObject)xin)->name);CHKERRQ(ierr);
705     }
706     ierr = VecCopy(xin,Y);CHKERRQ(ierr);
707     ierr = PetscViewerVTKAddField(viewer,(PetscObject)da,DMDAVTKWriteAll,PETSC_VTK_POINT_FIELD,(PetscObject)Y);CHKERRQ(ierr);
708 #if defined(PETSC_HAVE_HDF5)
709   } else if (ishdf5) {
710     ierr = VecView_MPI_HDF5_DA(xin,viewer);CHKERRQ(ierr);
711 #endif
712   } else {
713 #if defined(PETSC_HAVE_MPIIO)
714     PetscBool isbinary,isMPIIO;
715 
716     ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
717     if (isbinary) {
718       ierr = PetscViewerBinaryGetMPIIO(viewer,&isMPIIO);CHKERRQ(ierr);
719       if (isMPIIO) {
720         ierr = DMDAArrayMPIIO(da,viewer,xin,PETSC_TRUE);CHKERRQ(ierr);
721         PetscFunctionReturn(0);
722       }
723     }
724 #endif
725 
726     /* call viewer on natural ordering */
727     ierr = PetscObjectGetOptionsPrefix((PetscObject)xin,&prefix);CHKERRQ(ierr);
728     ierr = DMDACreateNaturalVector(da,&natural);CHKERRQ(ierr);
729     ierr = PetscObjectSetOptionsPrefix((PetscObject)natural,prefix);CHKERRQ(ierr);
730     ierr = DMDAGlobalToNaturalBegin(da,xin,INSERT_VALUES,natural);CHKERRQ(ierr);
731     ierr = DMDAGlobalToNaturalEnd(da,xin,INSERT_VALUES,natural);CHKERRQ(ierr);
732     ierr = PetscObjectGetName((PetscObject)xin,&name);CHKERRQ(ierr);
733     ierr = PetscObjectSetName((PetscObject)natural,name);CHKERRQ(ierr);
734 
735     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
736     if (format == PETSC_VIEWER_BINARY_MATLAB) {
737       /* temporarily remove viewer format so it won't trigger in the VecView() */
738       ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_DEFAULT);CHKERRQ(ierr);
739     }
740 
741     ierr = VecView(natural,viewer);CHKERRQ(ierr);
742 
743     if (format == PETSC_VIEWER_BINARY_MATLAB) {
744       MPI_Comm    comm;
745       FILE        *info;
746       const char  *fieldname;
747       char        fieldbuf[256];
748       PetscInt    dim,ni,nj,nk,pi,pj,pk,dof,n;
749 
750       /* set the viewer format back into the viewer */
751       ierr = PetscViewerSetFormat(viewer,format);CHKERRQ(ierr);
752       ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
753       ierr = PetscViewerBinaryGetInfoPointer(viewer,&info);CHKERRQ(ierr);
754       ierr = DMDAGetInfo(da,&dim,&ni,&nj,&nk,&pi,&pj,&pk,&dof,0,0,0,0,0);CHKERRQ(ierr);
755       ierr = PetscFPrintf(comm,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");CHKERRQ(ierr);
756       ierr = PetscFPrintf(comm,info,"#$$ tmp = PetscBinaryRead(fd); \n");CHKERRQ(ierr);
757       if (dim == 1) { ierr = PetscFPrintf(comm,info,"#$$ tmp = reshape(tmp,%d,%d);\n",dof,ni);CHKERRQ(ierr); }
758       if (dim == 2) { ierr = PetscFPrintf(comm,info,"#$$ tmp = reshape(tmp,%d,%d,%d);\n",dof,ni,nj);CHKERRQ(ierr); }
759       if (dim == 3) { ierr = PetscFPrintf(comm,info,"#$$ tmp = reshape(tmp,%d,%d,%d,%d);\n",dof,ni,nj,nk);CHKERRQ(ierr); }
760 
761       for (n=0; n<dof; n++) {
762         ierr = DMDAGetFieldName(da,n,&fieldname);CHKERRQ(ierr);
763         if (!fieldname || !fieldname[0]) {
764           ierr = PetscSNPrintf(fieldbuf,sizeof fieldbuf,"field%D",n);CHKERRQ(ierr);
765           fieldname = fieldbuf;
766         }
767         if (dim == 1) { ierr = PetscFPrintf(comm,info,"#$$ Set.%s.%s = squeeze(tmp(%d,:))';\n",name,fieldname,n+1);CHKERRQ(ierr); }
768         if (dim == 2) { ierr = PetscFPrintf(comm,info,"#$$ Set.%s.%s = squeeze(tmp(%d,:,:))';\n",name,fieldname,n+1);CHKERRQ(ierr); }
769         if (dim == 3) { ierr = PetscFPrintf(comm,info,"#$$ Set.%s.%s = permute(squeeze(tmp(%d,:,:,:)),[2 1 3]);\n",name,fieldname,n+1);CHKERRQ(ierr);}
770       }
771       ierr = PetscFPrintf(comm,info,"#$$ clear tmp; \n");CHKERRQ(ierr);
772       ierr = PetscFPrintf(comm,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");CHKERRQ(ierr);
773     }
774 
775     ierr = VecDestroy(&natural);CHKERRQ(ierr);
776   }
777   PetscFunctionReturn(0);
778 }
779 
780 #if defined(PETSC_HAVE_HDF5)
781 #undef __FUNCT__
782 #define __FUNCT__ "VecLoad_HDF5_DA"
783 PetscErrorCode VecLoad_HDF5_DA(Vec xin, PetscViewer viewer)
784 {
785   DM             da;
786   PetscErrorCode ierr;
787   hsize_t        dim;
788   hsize_t        count[5];
789   hsize_t        offset[5];
790   PetscInt       cnt = 0;
791   PetscScalar    *x;
792   const char     *vecname;
793   hid_t          filespace; /* file dataspace identifier */
794   hid_t          plist_id;  /* property list identifier */
795   hid_t          dset_id;   /* dataset identifier */
796   hid_t          memspace;  /* memory dataspace identifier */
797   hid_t          file_id,group;
798   herr_t         status;
799   DM_DA          *dd;
800 
801   PetscFunctionBegin;
802   ierr = PetscViewerHDF5OpenGroup(viewer, &file_id, &group);CHKERRQ(ierr);
803   ierr = VecGetDM(xin,&da);CHKERRQ(ierr);
804   dd   = (DM_DA*)da->data;
805 
806   /* Create the dataspace for the dataset */
807   ierr = PetscHDF5IntCast(dd->dim + ((dd->w == 1) ? 0 : 1),&dim);CHKERRQ(ierr);
808 #if defined(PETSC_USE_COMPLEX)
809   dim++;
810 #endif
811 
812   /* Create the dataset with default properties and close filespace */
813   ierr = PetscObjectGetName((PetscObject)xin,&vecname);CHKERRQ(ierr);
814 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
815   dset_id = H5Dopen2(group, vecname, H5P_DEFAULT);
816 #else
817   dset_id = H5Dopen(group, vecname);
818 #endif
819   if (dset_id == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Dopen2() with Vec named %s",vecname);
820   filespace = H5Dget_space(dset_id);
821 
822   /* Each process defines a dataset and reads it from the hyperslab in the file */
823   cnt = 0;
824   if (dd->dim == 3) {ierr = PetscHDF5IntCast(dd->zs,offset + cnt++);CHKERRQ(ierr);}
825   if (dd->dim > 1)  {ierr = PetscHDF5IntCast(dd->ys,offset + cnt++);CHKERRQ(ierr);}
826   ierr = PetscHDF5IntCast(dd->xs/dd->w,offset + cnt++);CHKERRQ(ierr);
827   if (dd->w > 1) offset[cnt++] = 0;
828 #if defined(PETSC_USE_COMPLEX)
829   offset[cnt++] = 0;
830 #endif
831   cnt = 0;
832   if (dd->dim == 3) {ierr = PetscHDF5IntCast(dd->ze - dd->zs,count + cnt++);CHKERRQ(ierr);}
833   if (dd->dim > 1)  {ierr = PetscHDF5IntCast(dd->ye - dd->ys,count + cnt++);CHKERRQ(ierr);}
834   ierr = PetscHDF5IntCast((dd->xe - dd->xs)/dd->w,count + cnt++);CHKERRQ(ierr);
835   if (dd->w > 1) {ierr = PetscHDF5IntCast(dd->w,count + cnt++);CHKERRQ(ierr);}
836 #if defined(PETSC_USE_COMPLEX)
837   count[cnt++] = 2;
838 #endif
839   memspace = H5Screate_simple(dim, count, NULL);
840   if (memspace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Screate_simple()");
841 
842   status = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset, NULL, count, NULL);CHKERRQ(status);
843 
844   /* Create property list for collective dataset write */
845   plist_id = H5Pcreate(H5P_DATASET_XFER);
846   if (plist_id == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Pcreate()");
847 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
848   status = H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);CHKERRQ(status);
849 #endif
850   /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */
851 
852   ierr   = VecGetArray(xin, &x);CHKERRQ(ierr);
853   status = H5Dread(dset_id, H5T_NATIVE_DOUBLE, memspace, filespace, plist_id, x);CHKERRQ(status);
854   ierr   = VecRestoreArray(xin, &x);CHKERRQ(ierr);
855 
856   /* Close/release resources */
857   if (group != file_id) {
858     status = H5Gclose(group);CHKERRQ(status);
859   }
860   status = H5Pclose(plist_id);CHKERRQ(status);
861   status = H5Sclose(filespace);CHKERRQ(status);
862   status = H5Sclose(memspace);CHKERRQ(status);
863   status = H5Dclose(dset_id);CHKERRQ(status);
864   PetscFunctionReturn(0);
865 }
866 #endif
867 
868 #undef __FUNCT__
869 #define __FUNCT__ "VecLoad_Binary_DA"
870 PetscErrorCode VecLoad_Binary_DA(Vec xin, PetscViewer viewer)
871 {
872   DM             da;
873   PetscErrorCode ierr;
874   Vec            natural;
875   const char     *prefix;
876   PetscInt       bs;
877   PetscBool      flag;
878   DM_DA          *dd;
879 #if defined(PETSC_HAVE_MPIIO)
880   PetscBool isMPIIO;
881 #endif
882 
883   PetscFunctionBegin;
884   ierr = VecGetDM(xin,&da);CHKERRQ(ierr);
885   dd   = (DM_DA*)da->data;
886 #if defined(PETSC_HAVE_MPIIO)
887   ierr = PetscViewerBinaryGetMPIIO(viewer,&isMPIIO);CHKERRQ(ierr);
888   if (isMPIIO) {
889     ierr = DMDAArrayMPIIO(da,viewer,xin,PETSC_FALSE);CHKERRQ(ierr);
890     PetscFunctionReturn(0);
891   }
892 #endif
893 
894   ierr = PetscObjectGetOptionsPrefix((PetscObject)xin,&prefix);CHKERRQ(ierr);
895   ierr = DMDACreateNaturalVector(da,&natural);CHKERRQ(ierr);
896   ierr = PetscObjectSetName((PetscObject)natural,((PetscObject)xin)->name);CHKERRQ(ierr);
897   ierr = PetscObjectSetOptionsPrefix((PetscObject)natural,prefix);CHKERRQ(ierr);
898   ierr = VecLoad(natural,viewer);CHKERRQ(ierr);
899   ierr = DMDANaturalToGlobalBegin(da,natural,INSERT_VALUES,xin);CHKERRQ(ierr);
900   ierr = DMDANaturalToGlobalEnd(da,natural,INSERT_VALUES,xin);CHKERRQ(ierr);
901   ierr = VecDestroy(&natural);CHKERRQ(ierr);
902   ierr = PetscInfo(xin,"Loading vector from natural ordering into DMDA\n");CHKERRQ(ierr);
903   ierr = PetscOptionsGetInt(((PetscObject)xin)->prefix,"-vecload_block_size",&bs,&flag);CHKERRQ(ierr);
904   if (flag && bs != dd->w) {
905     ierr = PetscInfo2(xin,"Block size in file %D not equal to DMDA's dof %D\n",bs,dd->w);CHKERRQ(ierr);
906   }
907   PetscFunctionReturn(0);
908 }
909 
910 #undef __FUNCT__
911 #define __FUNCT__ "VecLoad_Default_DA"
912 PetscErrorCode  VecLoad_Default_DA(Vec xin, PetscViewer viewer)
913 {
914   PetscErrorCode ierr;
915   DM             da;
916   PetscBool      isbinary;
917 #if defined(PETSC_HAVE_HDF5)
918   PetscBool ishdf5;
919 #endif
920 
921   PetscFunctionBegin;
922   ierr = VecGetDM(xin,&da);CHKERRQ(ierr);
923   if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA");
924 
925 #if defined(PETSC_HAVE_HDF5)
926   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
927 #endif
928   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
929 
930   if (isbinary) {
931     ierr = VecLoad_Binary_DA(xin,viewer);CHKERRQ(ierr);
932 #if defined(PETSC_HAVE_HDF5)
933   } else if (ishdf5) {
934     ierr = VecLoad_HDF5_DA(xin,viewer);CHKERRQ(ierr);
935 #endif
936   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for vector loading", ((PetscObject)viewer)->type_name);
937   PetscFunctionReturn(0);
938 }
939