Actual source code: gr2.c

petsc-3.5.4 2015-05-23
Report Typos and Errors
  2: /*
  3:    Plots vectors obtained with DMDACreate2d()
  4: */

  6: #include <petsc-private/dmdaimpl.h>      /*I  "petscdmda.h"   I*/
  7: #include <petsc-private/vecimpl.h>
  8: #include <petscdraw.h>
  9: #include <petscviewerhdf5.h>

 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;

 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: */
 29: PetscErrorCode VecView_MPI_Draw_DA2d_Zoom(PetscDraw draw,void *ctx)
 30: {
 31:   ZoomCtx        *zctx = (ZoomCtx*)ctx;
 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;

 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;

 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);

 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);

 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);

 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);

 90:       PetscDrawTriangle(draw,x1,y_1,x2,y2,x3,y3,c1,c2,c3);
 91:       PetscDrawTriangle(draw,x1,y_1,x3,y3,x4,y4,c1,c3,c4);
 92:       if (zctx->showgrid) {
 93:         PetscDrawLine(draw,x1,y_1,x2,y2,PETSC_DRAW_BLACK);
 94:         PetscDrawLine(draw,x2,y2,x3,y3,PETSC_DRAW_BLACK);
 95:         PetscDrawLine(draw,x3,y3,x4,y4,PETSC_DRAW_BLACK);
 96:         PetscDrawLine(draw,x4,y4,x1,y_1,PETSC_DRAW_BLACK);
 97:       }
 98:     }
 99:   }
100:   if (zctx->name0) {
101:     PetscReal xl,yl,xr,yr,x,y;
102:     PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);
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:     PetscDrawString(draw,x,yl,PETSC_DRAW_BLACK,zctx->name0);
108:     PetscDrawStringVertical(draw,xl,y,PETSC_DRAW_BLACK,zctx->name1);
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:   MPI_Allreduce(&xmin,&xminf,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)draw));
115:   MPI_Allreduce(&xmax,&xmaxf,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)draw));
116:   MPI_Allreduce(&ymin,&yminf,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)draw));
117:   MPI_Allreduce(&ymax,&ymaxf,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)draw));
118:   PetscSNPrintf(value,16,"%f",xminf);
119:   PetscDrawString(draw,xminf,yminf - .05*(ymaxf - yminf),PETSC_DRAW_BLACK,value);
120:   PetscSNPrintf(value,16,"%f",xmaxf);
121:   PetscStrlen(value,&len);
122:   PetscDrawStringGetSize(draw,&w,NULL);
123:   PetscDrawString(draw,xmaxf - len*w,yminf - .05*(ymaxf - yminf),PETSC_DRAW_BLACK,value);
124:   PetscSNPrintf(value,16,"%f",yminf);
125:   PetscDrawString(draw,xminf - .05*(xmaxf - xminf),yminf,PETSC_DRAW_BLACK,value);
126:   PetscSNPrintf(value,16,"%f",ymaxf);
127:   PetscDrawString(draw,xminf - .05*(xmaxf - xminf),ymaxf,PETSC_DRAW_BLACK,value);
128:   return(0);
129: }

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;

155:   zctx.showgrid = PETSC_FALSE;

157:   PetscViewerDrawGetDraw(viewer,0,&draw);
158:   PetscDrawIsNull(draw,&isnull); if (isnull) return(0);
159:   PetscViewerDrawGetBounds(viewer,&nbounds,&bounds);

161:   VecGetDM(xin,&da);
162:   if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA");

164:   PetscObjectGetComm((PetscObject)xin,&comm);
165:   MPI_Comm_rank(comm,&rank);

167:   DMDAGetInfo(da,0,&M,&N,0,&zctx.m,&zctx.n,0,&w,&s,&bx,&by,0,&st);
168:   DMDAGetOwnershipRanges(da,&lx,&ly,NULL);

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:   PetscObjectQuery((PetscObject)da,"GraphicsGhosted",(PetscObject*)&xlocal);
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:       DMDACreate2d(comm,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,M,N,zctx.m,zctx.n,w,1,lx,ly,&dac);
183:       PetscInfo(da,"Creating auxilary DMDA for managing graphics ghost points\n");
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:     DMCreateLocalVector(dac,&xlocal);
190:     if (dac != da) {
191:       /* don't keep any public reference of this DMDA, is is only available through xlocal */
192:       PetscObjectDereference((PetscObject)dac);
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:       PetscObjectRemoveReference((PetscObject)xlocal,"__PETSc_dm");
198:     }
199:     PetscObjectCompose((PetscObject)da,"GraphicsGhosted",(PetscObject)xlocal);
200:     PetscObjectDereference((PetscObject)xlocal);
201:   } else {
202:     if (bx !=  DM_BOUNDARY_NONE || by !=  DM_BOUNDARY_NONE || s != 1 || st != DMDA_STENCIL_BOX) {
203:       VecGetDM(xlocal, &dac);
204:     } else {
205:       dac = da;
206:     }
207:   }

209:   /*
210:       Get local (ghosted) values of vector
211:   */
212:   DMGlobalToLocalBegin(dac,xin,INSERT_VALUES,xlocal);
213:   DMGlobalToLocalEnd(dac,xin,INSERT_VALUES,xlocal);
214:   VecGetArray(xlocal,&zctx.v);

216:   /* get coordinates of nodes */
217:   DMGetCoordinates(da,&xcoor);
218:   if (!xcoor) {
219:     DMDASetUniformCoordinates(da,0.0,1.0,0.0,1.0,0.0,0.0);
220:     DMGetCoordinates(da,&xcoor);
221:   }

223:   /*
224:       Determine the min and max  coordinates in plot
225:   */
226:   VecStrideMin(xcoor,0,NULL,&xmin);
227:   VecStrideMax(xcoor,0,NULL,&xmax);
228:   VecStrideMin(xcoor,1,NULL,&ymin);
229:   VecStrideMax(xcoor,1,NULL,&ymax);
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:   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]);

234:   PetscOptionsGetRealArray(NULL,"-draw_coordinates",coors,&ncoors,NULL);

236:   /*
237:        get local ghosted version of coordinates
238:   */
239:   PetscObjectQuery((PetscObject)da,"GraphicsCoordinateGhosted",(PetscObject*)&xcoorl);
240:   if (!xcoorl) {
241:     /* create DMDA to get local version of graphics */
242:     DMDACreate2d(comm,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,M,N,zctx.m,zctx.n,2,1,lx,ly,&dag);
243:     PetscInfo(dag,"Creating auxilary DMDA for managing graphics coordinates ghost points\n");
244:     DMCreateLocalVector(dag,&xcoorl);
245:     PetscObjectCompose((PetscObject)da,"GraphicsCoordinateGhosted",(PetscObject)xcoorl);
246:     PetscObjectDereference((PetscObject)dag);
247:     PetscObjectDereference((PetscObject)xcoorl);
248:   } else {
249:     VecGetDM(xcoorl,&dag);
250:   }
251:   DMGlobalToLocalBegin(dag,xcoor,INSERT_VALUES,xcoorl);
252:   DMGlobalToLocalEnd(dag,xcoor,INSERT_VALUES,xcoorl);
253:   VecGetArray(xcoorl,&zctx.xy);

255:   /*
256:         Get information about size of area each processor must do graphics for
257:   */
258:   DMDAGetInfo(dac,0,&M,&N,0,0,0,0,&zctx.step,0,&bx,&by,0,0);
259:   DMDAGetGhostCorners(dac,0,0,0,&zctx.m,&zctx.n,0);

261:   PetscOptionsGetBool(NULL,"-draw_contour_grid",&zctx.showgrid,NULL);

263:   DMDASelectFields(da,&ndisplayfields,&displayfields);

265:   PetscViewerGetFormat(viewer,&format);
266:   PetscOptionsGetBool(NULL,"-draw_ports",&useports,NULL);
267:   if (useports || format == PETSC_VIEWER_DRAW_PORTS) {
268:     PetscDrawSynchronizedClear(draw);
269:     PetscDrawViewPortsCreate(draw,ndisplayfields,&ports);
270:     zctx.name0 = 0;
271:     zctx.name1 = 0;
272:   } else {
273:     DMDAGetCoordinateName(da,0,&zctx.name0);
274:     DMDAGetCoordinateName(da,1,&zctx.name1);
275:   }

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:       PetscDrawViewPortsSet(ports,i);
284:     } else {
285:       PetscViewerDrawGetDraw(viewer,i,&draw);
286:     }

288:     /*
289:         Determine the min and max color in plot
290:     */
291:     VecStrideMin(xin,zctx.k,NULL,&zctx.min);
292:     VecStrideMax(xin,zctx.k,NULL,&zctx.max);
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:     }

302:     if (!rank) {
303:       const char *title;

305:       DMDAGetFieldName(da,zctx.k,&title);
306:       if (title) {
307:         PetscDrawSetTitle(draw,title);
308:       }
309:     }
310:     PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);
311:     PetscInfo2(da,"DMDA 2d contour plot min %g max %g\n",(double)zctx.min,(double)zctx.max);

313:     PetscDrawGetPopup(draw,&popup);
314:     if (popup) {PetscDrawScalePopup(popup,zctx.min,zctx.max);}

316:     zctx.scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/(zctx.max - zctx.min);

318:     PetscDrawZoom(draw,VecView_MPI_Draw_DA2d_Zoom,&zctx);
319:   }
320:   PetscFree(displayfields);
321:   PetscDrawViewPortsDestroy(ports);

323:   VecRestoreArray(xcoorl,&zctx.xy);
324:   VecRestoreArray(xlocal,&zctx.v);
325:   return(0);
326: }

328: #if defined(PETSC_HAVE_HDF5)
331: static PetscErrorCode VecGetHDF5ChunkSize(DM_DA *da, Vec xin, PetscInt timestep, hsize_t *chunkDims)
332: {
333:   PetscMPIInt comm_size;
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;

343:   MPI_Comm_size(PetscObjectComm((PetscObject)xin), &comm_size);
344:   avg_local_vec_size = (hsize_t) ceil(vec_size*1.0/comm_size);      /* we will attempt to use this as the chunk size */

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:   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(PetscScalar);

353:   /*
354:    if size/rank > max_chunk_size, we need radical measures: even going down to
355:    avg_local_vec_size is not enough, so we simply use chunk size of 4 GiB no matter
356:    what, composed in the most efficient way possible.
357:    N.B. this minimises the number of chunks, which may or may not be the optimal
358:    solution. In a BG, for example, the optimal solution is probably to make # chunks = #
359:    IO nodes involved, but this author has no access to a BG to figure out how to
360:    reliably find the right number. And even then it may or may not be enough.
361:    */
362:   if (avg_local_vec_size > max_chunk_size) {
363:     /* check if we can just split local z-axis: is that enough? */
364:     zslices = (PetscInt)ceil(vec_size*1.0/(da->p*max_chunk_size))*zslices;
365:     if (zslices > da->P) {
366:       /* lattice is too large in xy-directions, splitting z only is not enough */
367:       zslices = da->P;
368:       yslices= (PetscInt)ceil(vec_size*1.0/(zslices*da->n*max_chunk_size))*yslices;
369:       if (yslices > da->N) {
370:         /* lattice is too large in x-direction, splitting along z, y is not enough */
371:         yslices = da->N;
372:         xslices= (PetscInt)ceil(vec_size*1.0/(zslices*yslices*da->m*max_chunk_size))*xslices;
373:       }
374:     }
375:     dim = 0;
376:     if (timestep >= 0) {
377:       ++dim;
378:     }
379:     /* prefer to split z-axis, even down to planar slices */
380:     if (da->dim == 3) {
381:       chunkDims[dim++] = (hsize_t) da->P/zslices;
382:       chunkDims[dim++] = (hsize_t) da->N/yslices;
383:       chunkDims[dim++] = (hsize_t) da->M/xslices;
384:     } else {
385:       /* This is a 2D world exceeding 4GiB in size; yes, I've seen them, even used myself */
386:       chunkDims[dim++] = (hsize_t) da->N/yslices;
387:       chunkDims[dim++] = (hsize_t) da->M/xslices;
388:     }
389:     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);
390:   } else {
391:     if (target_size < chunk_size) {
392:       /* only change the defaults if target_size < chunk_size */
393:       dim = 0;
394:       if (timestep >= 0) {
395:         ++dim;
396:       }
397:       /* prefer to split z-axis, even down to planar slices */
398:       if (da->dim == 3) {
399:         /* try splitting the z-axis to core-size bits, i.e. divide chunk size by # comm_size in z-direction */
400:         if (target_size >= chunk_size/da->p) {
401:           /* just make chunks the size of <local_z>x<whole_world_y>x<whole_world_x>x<dof> */
402:           chunkDims[dim] = (hsize_t) ceil(da->P*1.0/da->p);
403:         } else {
404:           /* oops, just splitting the z-axis is NOT ENOUGH, need to split more; let's be
405:            radical and let everyone write all they've got */
406:           chunkDims[dim++] = (hsize_t) ceil(da->P*1.0/da->p);
407:           chunkDims[dim++] = (hsize_t) ceil(da->N*1.0/da->n);
408:           chunkDims[dim++] = (hsize_t) ceil(da->M*1.0/da->m);
409:         }
410:       } else {
411:         /* This is a 2D world exceeding 4GiB in size; yes, I've seen them, even used myself */
412:         if (target_size >= chunk_size/da->n) {
413:           /* just make chunks the size of <local_z>x<whole_world_y>x<whole_world_x>x<dof> */
414:           chunkDims[dim] = (hsize_t) ceil(da->N*1.0/da->n);
415:         } else {
416:           /* oops, just splitting the z-axis is NOT ENOUGH, need to split more; let's be
417:            radical and let everyone write all they've got */
418:           chunkDims[dim++] = (hsize_t) ceil(da->N*1.0/da->n);
419:           chunkDims[dim++] = (hsize_t) ceil(da->M*1.0/da->m);
420:         }

422:       }
423:       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);
424:     } else {
425:       /* precomputed chunks are fine, we don't need to do anything */
426:     }
427:   }
428:   return(0);
429: }
430: #endif

432: #if defined(PETSC_HAVE_HDF5)
435: PetscErrorCode VecView_MPI_HDF5_DA(Vec xin,PetscViewer viewer)
436: {
437:   DM             dm;
438:   DM_DA          *da;
439:   hid_t          filespace;  /* file dataspace identifier */
440:   hid_t          chunkspace; /* chunk dataset property identifier */
441:   hid_t          plist_id;   /* property list identifier */
442:   hid_t          dset_id;    /* dataset identifier */
443:   hid_t          memspace;   /* memory dataspace identifier */
444:   hid_t          file_id;
445:   hid_t          group;
446:   hid_t          scalartype; /* scalar type (H5T_NATIVE_FLOAT or H5T_NATIVE_DOUBLE) */
447:   herr_t         status;
448:   hsize_t        dim;
449:   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  */
450:   PetscInt       timestep;
451:   PetscScalar    *x;
452:   const char     *vecname;

456:   PetscViewerHDF5OpenGroup(viewer, &file_id, &group);
457:   PetscViewerHDF5GetTimestep(viewer, &timestep);

459:   VecGetDM(xin,&dm);
460:   if (!dm) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA");
461:   da = (DM_DA*)dm->data;

463:   /* Create the dataspace for the dataset.
464:    *
465:    * dims - holds the current dimensions of the dataset
466:    *
467:    * maxDims - holds the maximum dimensions of the dataset (unlimited
468:    * for the number of time steps with the current dimensions for the
469:    * other dimensions; so only additional time steps can be added).
470:    *
471:    * chunkDims - holds the size of a single time step (required to
472:    * permit extending dataset).
473:    */
474:   dim = 0;
475:   if (timestep >= 0) {
476:     dims[dim]      = timestep+1;
477:     maxDims[dim]   = H5S_UNLIMITED;
478:     chunkDims[dim] = 1;
479:     ++dim;
480:   }
481:   if (da->dim == 3) {
482:     PetscHDF5IntCast(da->P,dims+dim);
483:     maxDims[dim]   = dims[dim];
484:     chunkDims[dim] = dims[dim];
485:     ++dim;
486:   }
487:   if (da->dim > 1) {
488:     PetscHDF5IntCast(da->N,dims+dim);
489:     maxDims[dim]   = dims[dim];
490:     chunkDims[dim] = dims[dim];
491:     ++dim;
492:   }
493:   PetscHDF5IntCast(da->M,dims+dim);
494:   maxDims[dim]   = dims[dim];
495:   chunkDims[dim] = dims[dim];
496:   ++dim;
497:   if (da->w > 1) {
498:     PetscHDF5IntCast(da->w,dims+dim);
499:     maxDims[dim]   = dims[dim];
500:     chunkDims[dim] = dims[dim];
501:     ++dim;
502:   }
503: #if defined(PETSC_USE_COMPLEX)
504:   dims[dim]      = 2;
505:   maxDims[dim]   = dims[dim];
506:   chunkDims[dim] = dims[dim];
507:   ++dim;
508: #endif

510:   VecGetHDF5ChunkSize(da, xin, timestep, chunkDims);

512:   filespace = H5Screate_simple(dim, dims, maxDims);
513:   if (filespace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Screate_simple()");

515: #if defined(PETSC_USE_REAL_SINGLE)
516:   scalartype = H5T_NATIVE_FLOAT;
517: #elif defined(PETSC_USE_REAL___FLOAT128)
518: #error "HDF5 output with 128 bit floats not supported."
519: #else
520:   scalartype = H5T_NATIVE_DOUBLE;
521: #endif

523:   /* Create the dataset with default properties and close filespace */
524:   PetscObjectGetName((PetscObject)xin,&vecname);
525:   if (!H5Lexists(group, vecname, H5P_DEFAULT)) {
526:     /* Create chunk */
527:     chunkspace = H5Pcreate(H5P_DATASET_CREATE);
528:     if (chunkspace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Pcreate()");
529:     status = H5Pset_chunk(chunkspace, dim, chunkDims);CHKERRQ(status);

531: #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
532:     dset_id = H5Dcreate2(group, vecname, scalartype, filespace, H5P_DEFAULT, chunkspace, H5P_DEFAULT);
533: #else
534:     dset_id = H5Dcreate(group, vecname, scalartype, filespace, H5P_DEFAULT);
535: #endif
536:     if (dset_id == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Dcreate2()");
537:   } else {
538:     dset_id = H5Dopen2(group, vecname, H5P_DEFAULT);
539:     status  = H5Dset_extent(dset_id, dims);CHKERRQ(status);
540:   }
541:   status = H5Sclose(filespace);CHKERRQ(status);

543:   /* Each process defines a dataset and writes it to the hyperslab in the file */
544:   dim = 0;
545:   if (timestep >= 0) {
546:     offset[dim] = timestep;
547:     ++dim;
548:   }
549:   if (da->dim == 3) {PetscHDF5IntCast(da->zs,offset + dim++);}
550:   if (da->dim > 1)  {PetscHDF5IntCast(da->ys,offset + dim++);}
551:   PetscHDF5IntCast(da->xs/da->w,offset + dim++);
552:   if (da->w > 1) offset[dim++] = 0;
553: #if defined(PETSC_USE_COMPLEX)
554:   offset[dim++] = 0;
555: #endif
556:   dim = 0;
557:   if (timestep >= 0) {
558:     count[dim] = 1;
559:     ++dim;
560:   }
561:   if (da->dim == 3) {PetscHDF5IntCast(da->ze - da->zs,count + dim++);}
562:   if (da->dim > 1)  {PetscHDF5IntCast(da->ye - da->ys,count + dim++);}
563:   PetscHDF5IntCast((da->xe - da->xs)/da->w,count + dim++);
564:   if (da->w > 1) {PetscHDF5IntCast(da->w,count + dim++);}
565: #if defined(PETSC_USE_COMPLEX)
566:   count[dim++] = 2;
567: #endif
568:   memspace = H5Screate_simple(dim, count, NULL);
569:   if (memspace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Screate_simple()");

571:   filespace = H5Dget_space(dset_id);
572:   if (filespace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Dget_space()");
573:   status = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset, NULL, count, NULL);CHKERRQ(status);

575:   /* Create property list for collective dataset write */
576:   plist_id = H5Pcreate(H5P_DATASET_XFER);
577:   if (plist_id == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Pcreate()");
578: #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
579:   status = H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);CHKERRQ(status);
580: #endif
581:   /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */

583:   VecGetArray(xin, &x);
584:   status = H5Dwrite(dset_id, scalartype, memspace, filespace, plist_id, x);CHKERRQ(status);
585:   status = H5Fflush(file_id, H5F_SCOPE_GLOBAL);CHKERRQ(status);
586:   VecRestoreArray(xin, &x);

588:   /* Close/release resources */
589:   if (group != file_id) {
590:     status = H5Gclose(group);CHKERRQ(status);
591:   }
592:   status = H5Pclose(plist_id);CHKERRQ(status);
593:   status = H5Sclose(filespace);CHKERRQ(status);
594:   status = H5Sclose(memspace);CHKERRQ(status);
595:   status = H5Dclose(dset_id);CHKERRQ(status);
596:   PetscInfo1(xin,"Wrote Vec object with name %s\n",vecname);
597:   return(0);
598: }
599: #endif

601: extern PetscErrorCode VecView_MPI_Draw_DA1d(Vec,PetscViewer);

603: #if defined(PETSC_HAVE_MPIIO)
606: static PetscErrorCode DMDAArrayMPIIO(DM da,PetscViewer viewer,Vec xin,PetscBool write)
607: {
608:   PetscErrorCode    ierr;
609:   MPI_File          mfdes;
610:   PetscMPIInt       gsizes[4],lsizes[4],lstarts[4],asiz,dof;
611:   MPI_Datatype      view;
612:   const PetscScalar *array;
613:   MPI_Offset        off;
614:   MPI_Aint          ub,ul;
615:   PetscInt          type,rows,vecrows,tr[2];
616:   DM_DA             *dd = (DM_DA*)da->data;
617:   PetscBool         skipheader;

620:   VecGetSize(xin,&vecrows);
621:   PetscViewerBinaryGetSkipHeader(viewer,&skipheader);
622:   if (!write) {
623:     /* Read vector header. */
624:     if (!skipheader) {
625:       PetscViewerBinaryRead(viewer,tr,2,PETSC_INT);
626:       type = tr[0];
627:       rows = tr[1];
628:       if (type != VEC_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONG,"Not vector next in file");
629:       if (rows != vecrows) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_SIZ,"Vector in file not same size as DMDA vector");
630:     }
631:   } else {
632:     tr[0] = VEC_FILE_CLASSID;
633:     tr[1] = vecrows;
634:     if (!skipheader) {
635:       PetscViewerBinaryWrite(viewer,tr,2,PETSC_INT,PETSC_TRUE);
636:     }
637:   }

639:   PetscMPIIntCast(dd->w,&dof);
640:   gsizes[0]  = dof;
641:   PetscMPIIntCast(dd->M,gsizes+1);
642:   PetscMPIIntCast(dd->N,gsizes+2);
643:   PetscMPIIntCast(dd->P,gsizes+3);
644:   lsizes[0]  = dof;
645:   PetscMPIIntCast((dd->xe-dd->xs)/dof,lsizes+1);
646:   PetscMPIIntCast(dd->ye-dd->ys,lsizes+2);
647:   PetscMPIIntCast(dd->ze-dd->zs,lsizes+3);
648:   lstarts[0] = 0;
649:   PetscMPIIntCast(dd->xs/dof,lstarts+1);
650:   PetscMPIIntCast(dd->ys,lstarts+2);
651:   PetscMPIIntCast(dd->zs,lstarts+3);
652:   MPI_Type_create_subarray(dd->dim+1,gsizes,lsizes,lstarts,MPI_ORDER_FORTRAN,MPIU_SCALAR,&view);
653:   MPI_Type_commit(&view);

655:   PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);
656:   PetscViewerBinaryGetMPIIOOffset(viewer,&off);
657:   MPI_File_set_view(mfdes,off,MPIU_SCALAR,view,(char*)"native",MPI_INFO_NULL);
658:   VecGetArrayRead(xin,&array);
659:   asiz = lsizes[1]*(lsizes[2] > 0 ? lsizes[2] : 1)*(lsizes[3] > 0 ? lsizes[3] : 1)*dof;
660:   if (write) {
661:     MPIU_File_write_all(mfdes,(PetscScalar*)array,asiz,MPIU_SCALAR,MPI_STATUS_IGNORE);
662:   } else {
663:     MPIU_File_read_all(mfdes,(PetscScalar*)array,asiz,MPIU_SCALAR,MPI_STATUS_IGNORE);
664:   }
665:   MPI_Type_get_extent(view,&ul,&ub);
666:   PetscViewerBinaryAddMPIIOOffset(viewer,ub);
667:   VecRestoreArrayRead(xin,&array);
668:   MPI_Type_free(&view);
669:   return(0);
670: }
671: #endif

675: PetscErrorCode  VecView_MPI_DA(Vec xin,PetscViewer viewer)
676: {
677:   DM                da;
678:   PetscErrorCode    ierr;
679:   PetscInt          dim;
680:   Vec               natural;
681:   PetscBool         isdraw,isvtk;
682: #if defined(PETSC_HAVE_HDF5)
683:   PetscBool         ishdf5;
684: #endif
685:   const char        *prefix,*name;
686:   PetscViewerFormat format;

689:   VecGetDM(xin,&da);
690:   if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA");
691:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
692:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERVTK,&isvtk);
693: #if defined(PETSC_HAVE_HDF5)
694:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
695: #endif
696:   if (isdraw) {
697:     DMDAGetInfo(da,&dim,0,0,0,0,0,0,0,0,0,0,0,0);
698:     if (dim == 1) {
699:       VecView_MPI_Draw_DA1d(xin,viewer);
700:     } else if (dim == 2) {
701:       VecView_MPI_Draw_DA2d(xin,viewer);
702:     } else SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Cannot graphically view vector associated with this dimensional DMDA %D",dim);
703:   } else if (isvtk) {           /* Duplicate the Vec and hold a reference to the DM */
704:     Vec Y;
705:     PetscObjectReference((PetscObject)da);
706:     VecDuplicate(xin,&Y);
707:     if (((PetscObject)xin)->name) {
708:       /* If xin was named, copy the name over to Y. The duplicate names are safe because nobody else will ever see Y. */
709:       PetscObjectSetName((PetscObject)Y,((PetscObject)xin)->name);
710:     }
711:     VecCopy(xin,Y);
712:     PetscViewerVTKAddField(viewer,(PetscObject)da,DMDAVTKWriteAll,PETSC_VTK_POINT_FIELD,(PetscObject)Y);
713: #if defined(PETSC_HAVE_HDF5)
714:   } else if (ishdf5) {
715:     VecView_MPI_HDF5_DA(xin,viewer);
716: #endif
717:   } else {
718: #if defined(PETSC_HAVE_MPIIO)
719:     PetscBool isbinary,isMPIIO;

721:     PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
722:     if (isbinary) {
723:       PetscViewerBinaryGetMPIIO(viewer,&isMPIIO);
724:       if (isMPIIO) {
725:         DMDAArrayMPIIO(da,viewer,xin,PETSC_TRUE);
726:         return(0);
727:       }
728:     }
729: #endif

731:     /* call viewer on natural ordering */
732:     PetscObjectGetOptionsPrefix((PetscObject)xin,&prefix);
733:     DMDACreateNaturalVector(da,&natural);
734:     PetscObjectSetOptionsPrefix((PetscObject)natural,prefix);
735:     DMDAGlobalToNaturalBegin(da,xin,INSERT_VALUES,natural);
736:     DMDAGlobalToNaturalEnd(da,xin,INSERT_VALUES,natural);
737:     PetscObjectGetName((PetscObject)xin,&name);
738:     PetscObjectSetName((PetscObject)natural,name);

740:     PetscViewerGetFormat(viewer,&format);
741:     if (format == PETSC_VIEWER_BINARY_MATLAB) {
742:       /* temporarily remove viewer format so it won't trigger in the VecView() */
743:       PetscViewerSetFormat(viewer,PETSC_VIEWER_DEFAULT);
744:     }

746:     VecView(natural,viewer);

748:     if (format == PETSC_VIEWER_BINARY_MATLAB) {
749:       MPI_Comm    comm;
750:       FILE        *info;
751:       const char  *fieldname;
752:       char        fieldbuf[256];
753:       PetscInt    dim,ni,nj,nk,pi,pj,pk,dof,n;

755:       /* set the viewer format back into the viewer */
756:       PetscViewerSetFormat(viewer,format);
757:       PetscObjectGetComm((PetscObject)viewer,&comm);
758:       PetscViewerBinaryGetInfoPointer(viewer,&info);
759:       DMDAGetInfo(da,&dim,&ni,&nj,&nk,&pi,&pj,&pk,&dof,0,0,0,0,0);
760:       PetscFPrintf(comm,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
761:       PetscFPrintf(comm,info,"#$$ tmp = PetscBinaryRead(fd); \n");
762:       if (dim == 1) { PetscFPrintf(comm,info,"#$$ tmp = reshape(tmp,%d,%d);\n",dof,ni); }
763:       if (dim == 2) { PetscFPrintf(comm,info,"#$$ tmp = reshape(tmp,%d,%d,%d);\n",dof,ni,nj); }
764:       if (dim == 3) { PetscFPrintf(comm,info,"#$$ tmp = reshape(tmp,%d,%d,%d,%d);\n",dof,ni,nj,nk); }

766:       for (n=0; n<dof; n++) {
767:         DMDAGetFieldName(da,n,&fieldname);
768:         if (!fieldname || !fieldname[0]) {
769:           PetscSNPrintf(fieldbuf,sizeof fieldbuf,"field%D",n);
770:           fieldname = fieldbuf;
771:         }
772:         if (dim == 1) { PetscFPrintf(comm,info,"#$$ Set.%s.%s = squeeze(tmp(%d,:))';\n",name,fieldname,n+1); }
773:         if (dim == 2) { PetscFPrintf(comm,info,"#$$ Set.%s.%s = squeeze(tmp(%d,:,:))';\n",name,fieldname,n+1); }
774:         if (dim == 3) { PetscFPrintf(comm,info,"#$$ Set.%s.%s = permute(squeeze(tmp(%d,:,:,:)),[2 1 3]);\n",name,fieldname,n+1);}
775:       }
776:       PetscFPrintf(comm,info,"#$$ clear tmp; \n");
777:       PetscFPrintf(comm,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
778:     }

780:     VecDestroy(&natural);
781:   }
782:   return(0);
783: }

785: #if defined(PETSC_HAVE_HDF5)
788: PetscErrorCode VecLoad_HDF5_DA(Vec xin, PetscViewer viewer)
789: {
790:   DM             da;
792:   hsize_t        dim;
793:   hsize_t        count[5];
794:   hsize_t        offset[5];
795:   PetscInt       cnt = 0;
796:   PetscScalar    *x;
797:   const char     *vecname;
798:   hid_t          filespace; /* file dataspace identifier */
799:   hid_t          plist_id;  /* property list identifier */
800:   hid_t          dset_id;   /* dataset identifier */
801:   hid_t          memspace;  /* memory dataspace identifier */
802:   hid_t          file_id,group;
803:   hid_t          scalartype; /* scalar type (H5T_NATIVE_FLOAT or H5T_NATIVE_DOUBLE) */
804:   herr_t         status;
805:   DM_DA          *dd;

808: #if defined(PETSC_USE_REAL_SINGLE)
809:   scalartype = H5T_NATIVE_FLOAT;
810: #elif defined(PETSC_USE_REAL___FLOAT128)
811: #error "HDF5 output with 128 bit floats not supported."
812: #else
813:   scalartype = H5T_NATIVE_DOUBLE;
814: #endif
815: 
816:   PetscViewerHDF5OpenGroup(viewer, &file_id, &group);
817:   VecGetDM(xin,&da);
818:   dd   = (DM_DA*)da->data;

820:   /* Create the dataspace for the dataset */
821:   PetscHDF5IntCast(dd->dim + ((dd->w == 1) ? 0 : 1),&dim);
822: #if defined(PETSC_USE_COMPLEX)
823:   dim++;
824: #endif

826:   /* Create the dataset with default properties and close filespace */
827:   PetscObjectGetName((PetscObject)xin,&vecname);
828: #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
829:   dset_id = H5Dopen2(group, vecname, H5P_DEFAULT);
830: #else
831:   dset_id = H5Dopen(group, vecname);
832: #endif
833:   if (dset_id == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Dopen2() with Vec named %s",vecname);
834:   filespace = H5Dget_space(dset_id);

836:   /* Each process defines a dataset and reads it from the hyperslab in the file */
837:   cnt = 0;
838:   if (dd->dim == 3) {PetscHDF5IntCast(dd->zs,offset + cnt++);}
839:   if (dd->dim > 1)  {PetscHDF5IntCast(dd->ys,offset + cnt++);}
840:   PetscHDF5IntCast(dd->xs/dd->w,offset + cnt++);
841:   if (dd->w > 1) offset[cnt++] = 0;
842: #if defined(PETSC_USE_COMPLEX)
843:   offset[cnt++] = 0;
844: #endif
845:   cnt = 0;
846:   if (dd->dim == 3) {PetscHDF5IntCast(dd->ze - dd->zs,count + cnt++);}
847:   if (dd->dim > 1)  {PetscHDF5IntCast(dd->ye - dd->ys,count + cnt++);}
848:   PetscHDF5IntCast((dd->xe - dd->xs)/dd->w,count + cnt++);
849:   if (dd->w > 1) {PetscHDF5IntCast(dd->w,count + cnt++);}
850: #if defined(PETSC_USE_COMPLEX)
851:   count[cnt++] = 2;
852: #endif
853:   memspace = H5Screate_simple(dim, count, NULL);
854:   if (memspace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Screate_simple()");

856:   status = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset, NULL, count, NULL);CHKERRQ(status);

858:   /* Create property list for collective dataset write */
859:   plist_id = H5Pcreate(H5P_DATASET_XFER);
860:   if (plist_id == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Pcreate()");
861: #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
862:   status = H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);CHKERRQ(status);
863: #endif
864:   /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */

866:   VecGetArray(xin, &x);
867:   status = H5Dread(dset_id, scalartype, memspace, filespace, plist_id, x);CHKERRQ(status);
868:   VecRestoreArray(xin, &x);

870:   /* Close/release resources */
871:   if (group != file_id) {
872:     status = H5Gclose(group);CHKERRQ(status);
873:   }
874:   status = H5Pclose(plist_id);CHKERRQ(status);
875:   status = H5Sclose(filespace);CHKERRQ(status);
876:   status = H5Sclose(memspace);CHKERRQ(status);
877:   status = H5Dclose(dset_id);CHKERRQ(status);
878:   return(0);
879: }
880: #endif

884: PetscErrorCode VecLoad_Binary_DA(Vec xin, PetscViewer viewer)
885: {
886:   DM             da;
888:   Vec            natural;
889:   const char     *prefix;
890:   PetscInt       bs;
891:   PetscBool      flag;
892:   DM_DA          *dd;
893: #if defined(PETSC_HAVE_MPIIO)
894:   PetscBool isMPIIO;
895: #endif

898:   VecGetDM(xin,&da);
899:   dd   = (DM_DA*)da->data;
900: #if defined(PETSC_HAVE_MPIIO)
901:   PetscViewerBinaryGetMPIIO(viewer,&isMPIIO);
902:   if (isMPIIO) {
903:     DMDAArrayMPIIO(da,viewer,xin,PETSC_FALSE);
904:     return(0);
905:   }
906: #endif

908:   PetscObjectGetOptionsPrefix((PetscObject)xin,&prefix);
909:   DMDACreateNaturalVector(da,&natural);
910:   PetscObjectSetName((PetscObject)natural,((PetscObject)xin)->name);
911:   PetscObjectSetOptionsPrefix((PetscObject)natural,prefix);
912:   VecLoad(natural,viewer);
913:   DMDANaturalToGlobalBegin(da,natural,INSERT_VALUES,xin);
914:   DMDANaturalToGlobalEnd(da,natural,INSERT_VALUES,xin);
915:   VecDestroy(&natural);
916:   PetscInfo(xin,"Loading vector from natural ordering into DMDA\n");
917:   PetscOptionsGetInt(((PetscObject)xin)->prefix,"-vecload_block_size",&bs,&flag);
918:   if (flag && bs != dd->w) {
919:     PetscInfo2(xin,"Block size in file %D not equal to DMDA's dof %D\n",bs,dd->w);
920:   }
921:   return(0);
922: }

926: PetscErrorCode  VecLoad_Default_DA(Vec xin, PetscViewer viewer)
927: {
929:   DM             da;
930:   PetscBool      isbinary;
931: #if defined(PETSC_HAVE_HDF5)
932:   PetscBool ishdf5;
933: #endif

936:   VecGetDM(xin,&da);
937:   if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA");

939: #if defined(PETSC_HAVE_HDF5)
940:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
941: #endif
942:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);

944:   if (isbinary) {
945:     VecLoad_Binary_DA(xin,viewer);
946: #if defined(PETSC_HAVE_HDF5)
947:   } else if (ishdf5) {
948:     VecLoad_HDF5_DA(xin,viewer);
949: #endif
950:   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for vector loading", ((PetscObject)viewer)->type_name);
951:   return(0);
952: }