xref: /petsc/src/dm/impls/da/gr2.c (revision b2bbaf76f4dd33c9042d329b49dbc66b9ef10f10)
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   const 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   const 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 = VecGetArrayRead(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 = VecGetArrayRead(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 = VecRestoreArrayRead(xcoorl,&zctx.xy);CHKERRQ(ierr);
324   ierr = VecRestoreArrayRead(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 dimension, 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,PetscMin(max_chunk_size,PetscMax(avg_local_vec_size,PetscMax(ceil(vec_size*1.0/max_chunks),min_size)))));
347   /* following line uses sizeof(PetscReal) instead of sizeof(PetscScalar) because the last dimension of chunkDims[] captures the 2* when complex numbers are being used */
348   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);
349 
350   /*
351    if size/rank > max_chunk_size, we need radical measures: even going down to
352    avg_local_vec_size is not enough, so we simply use chunk size of 4 GiB no matter
353    what, composed in the most efficient way possible.
354    N.B. this minimises the number of chunks, which may or may not be the optimal
355    solution. In a BG, for example, the optimal solution is probably to make # chunks = #
356    IO nodes involved, but this author has no access to a BG to figure out how to
357    reliably find the right number. And even then it may or may not be enough.
358    */
359   if (avg_local_vec_size > max_chunk_size) {
360     /* check if we can just split local z-axis: is that enough? */
361     zslices = (PetscInt)ceil(vec_size*1.0/(da->p*max_chunk_size))*zslices;
362     if (zslices > da->P) {
363       /* lattice is too large in xy-directions, splitting z only is not enough */
364       zslices = da->P;
365       yslices= (PetscInt)ceil(vec_size*1.0/(zslices*da->n*max_chunk_size))*yslices;
366       if (yslices > da->N) {
367 	/* lattice is too large in x-direction, splitting along z, y is not enough */
368 	yslices = da->N;
369 	xslices= (PetscInt)ceil(vec_size*1.0/(zslices*yslices*da->m*max_chunk_size))*xslices;
370       }
371     }
372     dim = 0;
373     if (timestep >= 0) {
374       ++dim;
375     }
376     /* prefer to split z-axis, even down to planar slices */
377     if (dimension == 3) {
378       chunkDims[dim++] = (hsize_t) da->P/zslices;
379       chunkDims[dim++] = (hsize_t) da->N/yslices;
380       chunkDims[dim++] = (hsize_t) da->M/xslices;
381     } else {
382       /* This is a 2D world exceeding 4GiB in size; yes, I've seen them, even used myself */
383       chunkDims[dim++] = (hsize_t) da->N/yslices;
384       chunkDims[dim++] = (hsize_t) da->M/xslices;
385     }
386     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);
387   } else {
388     if (target_size < chunk_size) {
389       /* only change the defaults if target_size < chunk_size */
390       dim = 0;
391       if (timestep >= 0) {
392 	++dim;
393       }
394       /* prefer to split z-axis, even down to planar slices */
395       if (dimension == 3) {
396 	/* try splitting the z-axis to core-size bits, i.e. divide chunk size by # comm_size in z-direction */
397 	if (target_size >= chunk_size/da->p) {
398 	  /* just make chunks the size of <local_z>x<whole_world_y>x<whole_world_x>x<dof> */
399 	  chunkDims[dim] = (hsize_t) ceil(da->P*1.0/da->p);
400 	} else {
401 	  /* oops, just splitting the z-axis is NOT ENOUGH, need to split more; let's be
402            radical and let everyone write all they've got */
403 	  chunkDims[dim++] = (hsize_t) ceil(da->P*1.0/da->p);
404 	  chunkDims[dim++] = (hsize_t) ceil(da->N*1.0/da->n);
405 	  chunkDims[dim++] = (hsize_t) ceil(da->M*1.0/da->m);
406 	}
407       } else {
408 	/* This is a 2D world exceeding 4GiB in size; yes, I've seen them, even used myself */
409 	if (target_size >= chunk_size/da->n) {
410 	  /* just make chunks the size of <local_z>x<whole_world_y>x<whole_world_x>x<dof> */
411 	  chunkDims[dim] = (hsize_t) ceil(da->N*1.0/da->n);
412 	} else {
413 	  /* oops, just splitting the z-axis is NOT ENOUGH, need to split more; let's be
414 	   radical and let everyone write all they've got */
415 	  chunkDims[dim++] = (hsize_t) ceil(da->N*1.0/da->n);
416 	  chunkDims[dim++] = (hsize_t) ceil(da->M*1.0/da->m);
417 	}
418 
419       }
420       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);
421     } else {
422       /* precomputed chunks are fine, we don't need to do anything */
423     }
424   }
425   PetscFunctionReturn(0);
426 }
427 #endif
428 
429 #if defined(PETSC_HAVE_HDF5)
430 #undef __FUNCT__
431 #define __FUNCT__ "VecView_MPI_HDF5_DA"
432 PetscErrorCode VecView_MPI_HDF5_DA(Vec xin,PetscViewer viewer)
433 {
434   DM                dm;
435   DM_DA             *da;
436   hid_t             filespace;  /* file dataspace identifier */
437   hid_t             chunkspace; /* chunk dataset property identifier */
438   hid_t             plist_id;   /* property list identifier */
439   hid_t             dset_id;    /* dataset identifier */
440   hid_t             memspace;   /* memory dataspace identifier */
441   hid_t             file_id;
442   hid_t             group;
443   hid_t             scalartype; /* scalar type (H5T_NATIVE_FLOAT or H5T_NATIVE_DOUBLE) */
444   hsize_t           dim;
445   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  */
446   PetscInt          timestep, dimension;
447   const PetscScalar *x;
448   const char        *vecname;
449   PetscErrorCode    ierr;
450 
451   PetscFunctionBegin;
452   ierr = PetscViewerHDF5OpenGroup(viewer, &file_id, &group);CHKERRQ(ierr);
453   ierr = PetscViewerHDF5GetTimestep(viewer, &timestep);CHKERRQ(ierr);
454 
455   ierr = VecGetDM(xin,&dm);CHKERRQ(ierr);
456   if (!dm) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA");
457   da = (DM_DA*)dm->data;
458   ierr = DMGetDimension(dm, &dimension);CHKERRQ(ierr);
459 
460   /* Create the dataspace for the dataset.
461    *
462    * dims - holds the current dimensions of the dataset
463    *
464    * maxDims - holds the maximum dimensions of the dataset (unlimited
465    * for the number of time steps with the current dimensions for the
466    * other dimensions; so only additional time steps can be added).
467    *
468    * chunkDims - holds the size of a single time step (required to
469    * permit extending dataset).
470    */
471   dim = 0;
472   if (timestep >= 0) {
473     dims[dim]      = timestep+1;
474     maxDims[dim]   = H5S_UNLIMITED;
475     chunkDims[dim] = 1;
476     ++dim;
477   }
478   if (dimension == 3) {
479     ierr           = PetscHDF5IntCast(da->P,dims+dim);CHKERRQ(ierr);
480     maxDims[dim]   = dims[dim];
481     chunkDims[dim] = dims[dim];
482     ++dim;
483   }
484   if (dimension > 1) {
485     ierr           = PetscHDF5IntCast(da->N,dims+dim);CHKERRQ(ierr);
486     maxDims[dim]   = dims[dim];
487     chunkDims[dim] = dims[dim];
488     ++dim;
489   }
490   ierr           = PetscHDF5IntCast(da->M,dims+dim);CHKERRQ(ierr);
491   maxDims[dim]   = dims[dim];
492   chunkDims[dim] = dims[dim];
493   ++dim;
494   if (da->w > 1) {
495     ierr           = PetscHDF5IntCast(da->w,dims+dim);CHKERRQ(ierr);
496     maxDims[dim]   = dims[dim];
497     chunkDims[dim] = dims[dim];
498     ++dim;
499   }
500 #if defined(PETSC_USE_COMPLEX)
501   dims[dim]      = 2;
502   maxDims[dim]   = dims[dim];
503   chunkDims[dim] = dims[dim];
504   ++dim;
505 #endif
506 
507   ierr = VecGetHDF5ChunkSize(da, xin, dimension, timestep, chunkDims); CHKERRQ(ierr);
508 
509   PetscStackCallHDF5Return(filespace,H5Screate_simple,(dim, dims, maxDims));
510 
511 #if defined(PETSC_USE_REAL_SINGLE)
512   scalartype = H5T_NATIVE_FLOAT;
513 #elif defined(PETSC_USE_REAL___FLOAT128)
514 #error "HDF5 output with 128 bit floats not supported."
515 #else
516   scalartype = H5T_NATIVE_DOUBLE;
517 #endif
518 
519   /* Create the dataset with default properties and close filespace */
520   ierr = PetscObjectGetName((PetscObject)xin,&vecname);CHKERRQ(ierr);
521   if (!H5Lexists(group, vecname, H5P_DEFAULT)) {
522     /* Create chunk */
523     PetscStackCallHDF5Return(chunkspace,H5Pcreate,(H5P_DATASET_CREATE));
524     PetscStackCallHDF5(H5Pset_chunk,(chunkspace, dim, chunkDims));
525 
526 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
527     PetscStackCallHDF5Return(dset_id,H5Dcreate2,(group, vecname, scalartype, filespace, H5P_DEFAULT, chunkspace, H5P_DEFAULT));
528 #else
529     PetscStackCallHDF5Return(dset_id,H5Dcreate,(group, vecname, scalartype, filespace, H5P_DEFAULT));
530 #endif
531   } else {
532     PetscStackCallHDF5Return(dset_id,H5Dopen2,(group, vecname, H5P_DEFAULT));
533     PetscStackCallHDF5(H5Dset_extent,(dset_id, dims));
534   }
535   PetscStackCallHDF5(H5Sclose,(filespace));
536 
537   /* Each process defines a dataset and writes it to the hyperslab in the file */
538   dim = 0;
539   if (timestep >= 0) {
540     offset[dim] = timestep;
541     ++dim;
542   }
543   if (dimension == 3) {ierr = PetscHDF5IntCast(da->zs,offset + dim++);CHKERRQ(ierr);}
544   if (dimension > 1)  {ierr = PetscHDF5IntCast(da->ys,offset + dim++);CHKERRQ(ierr);}
545   ierr = PetscHDF5IntCast(da->xs/da->w,offset + dim++);CHKERRQ(ierr);
546   if (da->w > 1) offset[dim++] = 0;
547 #if defined(PETSC_USE_COMPLEX)
548   offset[dim++] = 0;
549 #endif
550   dim = 0;
551   if (timestep >= 0) {
552     count[dim] = 1;
553     ++dim;
554   }
555   if (dimension == 3) {ierr = PetscHDF5IntCast(da->ze - da->zs,count + dim++);CHKERRQ(ierr);}
556   if (dimension > 1)  {ierr = PetscHDF5IntCast(da->ye - da->ys,count + dim++);CHKERRQ(ierr);}
557   ierr = PetscHDF5IntCast((da->xe - da->xs)/da->w,count + dim++);CHKERRQ(ierr);
558   if (da->w > 1) {ierr = PetscHDF5IntCast(da->w,count + dim++);CHKERRQ(ierr);}
559 #if defined(PETSC_USE_COMPLEX)
560   count[dim++] = 2;
561 #endif
562   PetscStackCallHDF5Return(memspace,H5Screate_simple,(dim, count, NULL));
563   PetscStackCallHDF5Return(filespace,H5Dget_space,(dset_id));
564   PetscStackCallHDF5(H5Sselect_hyperslab,(filespace, H5S_SELECT_SET, offset, NULL, count, NULL));
565 
566   /* Create property list for collective dataset write */
567   PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_DATASET_XFER));
568 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
569   PetscStackCallHDF5(H5Pset_dxpl_mpio,(plist_id, H5FD_MPIO_COLLECTIVE));
570 #endif
571   /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */
572 
573   ierr   = VecGetArrayRead(xin, &x);CHKERRQ(ierr);
574   PetscStackCallHDF5(H5Dwrite,(dset_id, scalartype, memspace, filespace, plist_id, x));
575   PetscStackCallHDF5(H5Fflush,(file_id, H5F_SCOPE_GLOBAL));
576   ierr   = VecRestoreArrayRead(xin, &x);CHKERRQ(ierr);
577 
578   /* Close/release resources */
579   if (group != file_id) {
580     PetscStackCallHDF5(H5Gclose,(group));
581   }
582   PetscStackCallHDF5(H5Pclose,(plist_id));
583   PetscStackCallHDF5(H5Sclose,(filespace));
584   PetscStackCallHDF5(H5Sclose,(memspace));
585   PetscStackCallHDF5(H5Dclose,(dset_id));
586   ierr   = PetscInfo1(xin,"Wrote Vec object with name %s\n",vecname);CHKERRQ(ierr);
587   PetscFunctionReturn(0);
588 }
589 #endif
590 
591 extern PetscErrorCode VecView_MPI_Draw_DA1d(Vec,PetscViewer);
592 
593 #if defined(PETSC_HAVE_MPIIO)
594 #undef __FUNCT__
595 #define __FUNCT__ "DMDAArrayMPIIO"
596 static PetscErrorCode DMDAArrayMPIIO(DM da,PetscViewer viewer,Vec xin,PetscBool write)
597 {
598   PetscErrorCode    ierr;
599   MPI_File          mfdes;
600   PetscMPIInt       gsizes[4],lsizes[4],lstarts[4],asiz,dof;
601   MPI_Datatype      view;
602   const PetscScalar *array;
603   MPI_Offset        off;
604   MPI_Aint          ub,ul;
605   PetscInt          type,rows,vecrows,tr[2];
606   DM_DA             *dd = (DM_DA*)da->data;
607   PetscBool         skipheader;
608 
609   PetscFunctionBegin;
610   ierr = VecGetSize(xin,&vecrows);CHKERRQ(ierr);
611   ierr = PetscViewerBinaryGetSkipHeader(viewer,&skipheader);CHKERRQ(ierr);
612   if (!write) {
613     /* Read vector header. */
614     if (!skipheader) {
615       ierr = PetscViewerBinaryRead(viewer,tr,2,PETSC_INT);CHKERRQ(ierr);
616       type = tr[0];
617       rows = tr[1];
618       if (type != VEC_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONG,"Not vector next in file");
619       if (rows != vecrows) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_SIZ,"Vector in file not same size as DMDA vector");
620     }
621   } else {
622     tr[0] = VEC_FILE_CLASSID;
623     tr[1] = vecrows;
624     if (!skipheader) {
625       ierr  = PetscViewerBinaryWrite(viewer,tr,2,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
626     }
627   }
628 
629   ierr       = PetscMPIIntCast(dd->w,&dof);CHKERRQ(ierr);
630   gsizes[0]  = dof;
631   ierr       = PetscMPIIntCast(dd->M,gsizes+1);CHKERRQ(ierr);
632   ierr       = PetscMPIIntCast(dd->N,gsizes+2);CHKERRQ(ierr);
633   ierr       = PetscMPIIntCast(dd->P,gsizes+3);CHKERRQ(ierr);
634   lsizes[0]  = dof;
635   ierr       = PetscMPIIntCast((dd->xe-dd->xs)/dof,lsizes+1);CHKERRQ(ierr);
636   ierr       = PetscMPIIntCast(dd->ye-dd->ys,lsizes+2);CHKERRQ(ierr);
637   ierr       = PetscMPIIntCast(dd->ze-dd->zs,lsizes+3);CHKERRQ(ierr);
638   lstarts[0] = 0;
639   ierr       = PetscMPIIntCast(dd->xs/dof,lstarts+1);CHKERRQ(ierr);
640   ierr       = PetscMPIIntCast(dd->ys,lstarts+2);CHKERRQ(ierr);
641   ierr       = PetscMPIIntCast(dd->zs,lstarts+3);CHKERRQ(ierr);
642   ierr       = MPI_Type_create_subarray(da->dim+1,gsizes,lsizes,lstarts,MPI_ORDER_FORTRAN,MPIU_SCALAR,&view);CHKERRQ(ierr);
643   ierr       = MPI_Type_commit(&view);CHKERRQ(ierr);
644 
645   ierr = PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);CHKERRQ(ierr);
646   ierr = PetscViewerBinaryGetMPIIOOffset(viewer,&off);CHKERRQ(ierr);
647   ierr = MPI_File_set_view(mfdes,off,MPIU_SCALAR,view,(char*)"native",MPI_INFO_NULL);CHKERRQ(ierr);
648   ierr = VecGetArrayRead(xin,&array);CHKERRQ(ierr);
649   asiz = lsizes[1]*(lsizes[2] > 0 ? lsizes[2] : 1)*(lsizes[3] > 0 ? lsizes[3] : 1)*dof;
650   if (write) {
651     ierr = MPIU_File_write_all(mfdes,(PetscScalar*)array,asiz,MPIU_SCALAR,MPI_STATUS_IGNORE);CHKERRQ(ierr);
652   } else {
653     ierr = MPIU_File_read_all(mfdes,(PetscScalar*)array,asiz,MPIU_SCALAR,MPI_STATUS_IGNORE);CHKERRQ(ierr);
654   }
655   ierr = MPI_Type_get_extent(view,&ul,&ub);CHKERRQ(ierr);
656   ierr = PetscViewerBinaryAddMPIIOOffset(viewer,ub);CHKERRQ(ierr);
657   ierr = VecRestoreArrayRead(xin,&array);CHKERRQ(ierr);
658   ierr = MPI_Type_free(&view);CHKERRQ(ierr);
659   PetscFunctionReturn(0);
660 }
661 #endif
662 
663 #undef __FUNCT__
664 #define __FUNCT__ "VecView_MPI_DA"
665 PetscErrorCode  VecView_MPI_DA(Vec xin,PetscViewer viewer)
666 {
667   DM                da;
668   PetscErrorCode    ierr;
669   PetscInt          dim;
670   Vec               natural;
671   PetscBool         isdraw,isvtk;
672 #if defined(PETSC_HAVE_HDF5)
673   PetscBool         ishdf5;
674 #endif
675   const char        *prefix,*name;
676   PetscViewerFormat format;
677 
678   PetscFunctionBegin;
679   ierr = VecGetDM(xin,&da);CHKERRQ(ierr);
680   if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA");
681   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
682   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERVTK,&isvtk);CHKERRQ(ierr);
683 #if defined(PETSC_HAVE_HDF5)
684   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
685 #endif
686   if (isdraw) {
687     ierr = DMDAGetInfo(da,&dim,0,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr);
688     if (dim == 1) {
689       ierr = VecView_MPI_Draw_DA1d(xin,viewer);CHKERRQ(ierr);
690     } else if (dim == 2) {
691       ierr = VecView_MPI_Draw_DA2d(xin,viewer);CHKERRQ(ierr);
692     } else SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Cannot graphically view vector associated with this dimensional DMDA %D",dim);
693   } else if (isvtk) {           /* Duplicate the Vec and hold a reference to the DM */
694     Vec Y;
695     ierr = PetscObjectReference((PetscObject)da);CHKERRQ(ierr);
696     ierr = VecDuplicate(xin,&Y);CHKERRQ(ierr);
697     if (((PetscObject)xin)->name) {
698       /* If xin was named, copy the name over to Y. The duplicate names are safe because nobody else will ever see Y. */
699       ierr = PetscObjectSetName((PetscObject)Y,((PetscObject)xin)->name);CHKERRQ(ierr);
700     }
701     ierr = VecCopy(xin,Y);CHKERRQ(ierr);
702     ierr = PetscViewerVTKAddField(viewer,(PetscObject)da,DMDAVTKWriteAll,PETSC_VTK_POINT_FIELD,(PetscObject)Y);CHKERRQ(ierr);
703 #if defined(PETSC_HAVE_HDF5)
704   } else if (ishdf5) {
705     ierr = VecView_MPI_HDF5_DA(xin,viewer);CHKERRQ(ierr);
706 #endif
707   } else {
708 #if defined(PETSC_HAVE_MPIIO)
709     PetscBool isbinary,isMPIIO;
710 
711     ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
712     if (isbinary) {
713       ierr = PetscViewerBinaryGetUseMPIIO(viewer,&isMPIIO);CHKERRQ(ierr);
714       if (isMPIIO) {
715         ierr = DMDAArrayMPIIO(da,viewer,xin,PETSC_TRUE);CHKERRQ(ierr);
716         PetscFunctionReturn(0);
717       }
718     }
719 #endif
720 
721     /* call viewer on natural ordering */
722     ierr = PetscObjectGetOptionsPrefix((PetscObject)xin,&prefix);CHKERRQ(ierr);
723     ierr = DMDACreateNaturalVector(da,&natural);CHKERRQ(ierr);
724     ierr = PetscObjectSetOptionsPrefix((PetscObject)natural,prefix);CHKERRQ(ierr);
725     ierr = DMDAGlobalToNaturalBegin(da,xin,INSERT_VALUES,natural);CHKERRQ(ierr);
726     ierr = DMDAGlobalToNaturalEnd(da,xin,INSERT_VALUES,natural);CHKERRQ(ierr);
727     ierr = PetscObjectGetName((PetscObject)xin,&name);CHKERRQ(ierr);
728     ierr = PetscObjectSetName((PetscObject)natural,name);CHKERRQ(ierr);
729 
730     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
731     if (format == PETSC_VIEWER_BINARY_MATLAB) {
732       /* temporarily remove viewer format so it won't trigger in the VecView() */
733       ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_DEFAULT);CHKERRQ(ierr);
734     }
735 
736     ierr = VecView(natural,viewer);CHKERRQ(ierr);
737 
738     if (format == PETSC_VIEWER_BINARY_MATLAB) {
739       MPI_Comm    comm;
740       FILE        *info;
741       const char  *fieldname;
742       char        fieldbuf[256];
743       PetscInt    dim,ni,nj,nk,pi,pj,pk,dof,n;
744 
745       /* set the viewer format back into the viewer */
746       ierr = PetscViewerSetFormat(viewer,format);CHKERRQ(ierr);
747       ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
748       ierr = PetscViewerBinaryGetInfoPointer(viewer,&info);CHKERRQ(ierr);
749       ierr = DMDAGetInfo(da,&dim,&ni,&nj,&nk,&pi,&pj,&pk,&dof,0,0,0,0,0);CHKERRQ(ierr);
750       ierr = PetscFPrintf(comm,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");CHKERRQ(ierr);
751       ierr = PetscFPrintf(comm,info,"#$$ tmp = PetscBinaryRead(fd); \n");CHKERRQ(ierr);
752       if (dim == 1) { ierr = PetscFPrintf(comm,info,"#$$ tmp = reshape(tmp,%d,%d);\n",dof,ni);CHKERRQ(ierr); }
753       if (dim == 2) { ierr = PetscFPrintf(comm,info,"#$$ tmp = reshape(tmp,%d,%d,%d);\n",dof,ni,nj);CHKERRQ(ierr); }
754       if (dim == 3) { ierr = PetscFPrintf(comm,info,"#$$ tmp = reshape(tmp,%d,%d,%d,%d);\n",dof,ni,nj,nk);CHKERRQ(ierr); }
755 
756       for (n=0; n<dof; n++) {
757         ierr = DMDAGetFieldName(da,n,&fieldname);CHKERRQ(ierr);
758         if (!fieldname || !fieldname[0]) {
759           ierr = PetscSNPrintf(fieldbuf,sizeof fieldbuf,"field%D",n);CHKERRQ(ierr);
760           fieldname = fieldbuf;
761         }
762         if (dim == 1) { ierr = PetscFPrintf(comm,info,"#$$ Set.%s.%s = squeeze(tmp(%d,:))';\n",name,fieldname,n+1);CHKERRQ(ierr); }
763         if (dim == 2) { ierr = PetscFPrintf(comm,info,"#$$ Set.%s.%s = squeeze(tmp(%d,:,:))';\n",name,fieldname,n+1);CHKERRQ(ierr); }
764         if (dim == 3) { ierr = PetscFPrintf(comm,info,"#$$ Set.%s.%s = permute(squeeze(tmp(%d,:,:,:)),[2 1 3]);\n",name,fieldname,n+1);CHKERRQ(ierr);}
765       }
766       ierr = PetscFPrintf(comm,info,"#$$ clear tmp; \n");CHKERRQ(ierr);
767       ierr = PetscFPrintf(comm,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");CHKERRQ(ierr);
768     }
769 
770     ierr = VecDestroy(&natural);CHKERRQ(ierr);
771   }
772   PetscFunctionReturn(0);
773 }
774 
775 #if defined(PETSC_HAVE_HDF5)
776 #undef __FUNCT__
777 #define __FUNCT__ "VecLoad_HDF5_DA"
778 PetscErrorCode VecLoad_HDF5_DA(Vec xin, PetscViewer viewer)
779 {
780   DM             da;
781   PetscErrorCode ierr;
782   hsize_t        dim;
783   hsize_t        count[5];
784   hsize_t        offset[5];
785   PetscInt       cnt = 0, dimension;
786   PetscScalar    *x;
787   const char     *vecname;
788   hid_t          filespace; /* file dataspace identifier */
789   hid_t          plist_id;  /* property list identifier */
790   hid_t          dset_id;   /* dataset identifier */
791   hid_t          memspace;  /* memory dataspace identifier */
792   hid_t          file_id,group;
793   hid_t          scalartype; /* scalar type (H5T_NATIVE_FLOAT or H5T_NATIVE_DOUBLE) */
794   DM_DA          *dd;
795 
796   PetscFunctionBegin;
797 #if defined(PETSC_USE_REAL_SINGLE)
798   scalartype = H5T_NATIVE_FLOAT;
799 #elif defined(PETSC_USE_REAL___FLOAT128)
800 #error "HDF5 output with 128 bit floats not supported."
801 #else
802   scalartype = H5T_NATIVE_DOUBLE;
803 #endif
804 
805   ierr = PetscViewerHDF5OpenGroup(viewer, &file_id, &group);CHKERRQ(ierr);
806   ierr = VecGetDM(xin,&da);CHKERRQ(ierr);
807   dd   = (DM_DA*)da->data;
808   ierr = DMGetDimension(da, &dimension);CHKERRQ(ierr);
809 
810   /* Create the dataspace for the dataset */
811   ierr = PetscHDF5IntCast(dimension + ((dd->w == 1) ? 0 : 1),&dim);CHKERRQ(ierr);
812 #if defined(PETSC_USE_COMPLEX)
813   dim++;
814 #endif
815 
816   /* Create the dataset with default properties and close filespace */
817   ierr = PetscObjectGetName((PetscObject)xin,&vecname);CHKERRQ(ierr);
818 #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
819   PetscStackCallHDF5Return(dset_id,H5Dopen2,(group, vecname, H5P_DEFAULT));
820 #else
821   PetscStackCallHDF5Return(dset_id,H5Dopen,(group, vecname));
822 #endif
823   PetscStackCallHDF5Return(filespace,H5Dget_space,(dset_id));
824 
825   /* Each process defines a dataset and reads it from the hyperslab in the file */
826   cnt = 0;
827   if (dimension == 3) {ierr = PetscHDF5IntCast(dd->zs,offset + cnt++);CHKERRQ(ierr);}
828   if (dimension > 1)  {ierr = PetscHDF5IntCast(dd->ys,offset + cnt++);CHKERRQ(ierr);}
829   ierr = PetscHDF5IntCast(dd->xs/dd->w,offset + cnt++);CHKERRQ(ierr);
830   if (dd->w > 1) offset[cnt++] = 0;
831 #if defined(PETSC_USE_COMPLEX)
832   offset[cnt++] = 0;
833 #endif
834   cnt = 0;
835   if (dimension == 3) {ierr = PetscHDF5IntCast(dd->ze - dd->zs,count + cnt++);CHKERRQ(ierr);}
836   if (dimension > 1)  {ierr = PetscHDF5IntCast(dd->ye - dd->ys,count + cnt++);CHKERRQ(ierr);}
837   ierr = PetscHDF5IntCast((dd->xe - dd->xs)/dd->w,count + cnt++);CHKERRQ(ierr);
838   if (dd->w > 1) {ierr = PetscHDF5IntCast(dd->w,count + cnt++);CHKERRQ(ierr);}
839 #if defined(PETSC_USE_COMPLEX)
840   count[cnt++] = 2;
841 #endif
842   PetscStackCallHDF5Return(memspace,H5Screate_simple,(dim, count, NULL));
843   PetscStackCallHDF5(H5Sselect_hyperslab,(filespace, H5S_SELECT_SET, offset, NULL, count, NULL));
844 
845   /* Create property list for collective dataset write */
846   PetscStackCallHDF5Return(plist_id,H5Pcreate,(H5P_DATASET_XFER));
847 #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
848   PetscStackCallHDF5(H5Pset_dxpl_mpio,(plist_id, H5FD_MPIO_COLLECTIVE));
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   PetscStackCallHDF5(H5Dread,(dset_id, scalartype, memspace, filespace, plist_id, x));
854   ierr   = VecRestoreArray(xin, &x);CHKERRQ(ierr);
855 
856   /* Close/release resources */
857   if (group != file_id) {
858     PetscStackCallHDF5(H5Gclose,(group));
859   }
860   PetscStackCallHDF5(H5Pclose,(plist_id));
861   PetscStackCallHDF5(H5Sclose,(filespace));
862   PetscStackCallHDF5(H5Sclose,(memspace));
863   PetscStackCallHDF5(H5Dclose,(dset_id));
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 = PetscViewerBinaryGetUseMPIIO(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