Date: 2013-07-02T14:45:01+00:00

Actual source code: gr2.c
petsc-3.4.2 2013-07-02

      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   = y_1;
     66:       c2   = (int)(PETSC_DRAW_BASIC_COLORS+s*(PetscClipInterval(PetscRealPart(v[k+step*id]),min,max)-min));
     67:       xmin = PetscMin(xmin,x2);
     68:       xmax = PetscMax(xmax,x2);

     70:       id   = i+j*m+1+m;
     71:       x3   = x2;
     72:       y3   = PetscRealPart(xy[2*id+1]);
     73:       c3   = (int)(PETSC_DRAW_BASIC_COLORS+s*(PetscClipInterval(PetscRealPart(v[k+step*id]),min,max)-min));
     74:       ymin = PetscMin(ymin,y3);
     75:       ymax = PetscMax(ymax,y3);

     77:       id = i+j*m+m;
     78:       x4 = x1;
     79:       y4 = y3;
     80:       c4 = (int)(PETSC_DRAW_BASIC_COLORS+s*(PetscClipInterval(PetscRealPart(v[k+step*id]),min,max)-min));

     82:       PetscDrawTriangle(draw,x1,y_1,x2,y2,x3,y3,c1,c2,c3);
     83:       PetscDrawTriangle(draw,x1,y_1,x3,y3,x4,y4,c1,c3,c4);
     84:       if (zctx->showgrid) {
     85:         PetscDrawLine(draw,x1,y_1,x2,y2,PETSC_DRAW_BLACK);
     86:         PetscDrawLine(draw,x2,y2,x3,y3,PETSC_DRAW_BLACK);
     87:         PetscDrawLine(draw,x3,y3,x4,y4,PETSC_DRAW_BLACK);
     88:         PetscDrawLine(draw,x4,y4,x1,y_1,PETSC_DRAW_BLACK);
     89:       }
     90:     }
     91:   }
     92:   if (zctx->name0) {
     93:     PetscReal xl,yl,xr,yr,x,y;
     94:     PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);
     95:     x    = xl + .3*(xr - xl);
     96:     xl   = xl + .01*(xr - xl);
     97:     y    = yr - .3*(yr - yl);
     98:     yl   = yl + .01*(yr - yl);
     99:     PetscDrawString(draw,x,yl,PETSC_DRAW_BLACK,zctx->name0);
    100:     PetscDrawStringVertical(draw,xl,y,PETSC_DRAW_BLACK,zctx->name1);
    101:   }
    102:   /*
    103:      Ideally we would use the PetscDrawAxis object to manage displaying the coordinate limits
    104:      but that may require some refactoring.
    105:   */
    106:   MPI_Allreduce(&xmin,&xminf,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)draw));
    107:   MPI_Allreduce(&xmax,&xmaxf,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)draw));
    108:   MPI_Allreduce(&ymin,&yminf,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)draw));
    109:   MPI_Allreduce(&ymax,&ymaxf,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)draw));
    110:   PetscSNPrintf(value,16,"%f",xminf);
    111:   PetscDrawString(draw,xminf,yminf - .05*(ymaxf - yminf),PETSC_DRAW_BLACK,value);
    112:   PetscSNPrintf(value,16,"%f",xmaxf);
    113:   PetscStrlen(value,&len);
    114:   PetscDrawStringGetSize(draw,&w,NULL);
    115:   PetscDrawString(draw,xmaxf - len*w,yminf - .05*(ymaxf - yminf),PETSC_DRAW_BLACK,value);
    116:   PetscSNPrintf(value,16,"%f",yminf);
    117:   PetscDrawString(draw,xminf - .05*(xmaxf - xminf),yminf,PETSC_DRAW_BLACK,value);
    118:   PetscSNPrintf(value,16,"%f",ymaxf);
    119:   PetscDrawString(draw,xminf - .05*(xmaxf - xminf),ymaxf,PETSC_DRAW_BLACK,value);
    120:   return(0);
    121: }

    125: PetscErrorCode VecView_MPI_Draw_DA2d(Vec xin,PetscViewer viewer)
    126: {
    127:   DM                 da,dac,dag;
    128:   PetscErrorCode     ierr;
    129:   PetscMPIInt        rank;
    130:   PetscInt           N,s,M,w,ncoors = 4;
    131:   const PetscInt     *lx,*ly;
    132:   PetscReal          coors[4],ymin,ymax,xmin,xmax;
    133:   PetscDraw          draw,popup;
    134:   PetscBool          isnull,useports = PETSC_FALSE;
    135:   MPI_Comm           comm;
    136:   Vec                xlocal,xcoor,xcoorl;
    137:   DMDABoundaryType   bx,by;
    138:   DMDAStencilType    st;
    139:   ZoomCtx            zctx;
    140:   PetscDrawViewPorts *ports = NULL;
    141:   PetscViewerFormat  format;
    142:   PetscInt           *displayfields;
    143:   PetscInt           ndisplayfields,i,nbounds;
    144:   const PetscReal    *bounds;

    147:   zctx.showgrid = PETSC_FALSE;

    149:   PetscViewerDrawGetDraw(viewer,0,&draw);
    150:   PetscDrawIsNull(draw,&isnull); if (isnull) return(0);
    151:   PetscViewerDrawGetBounds(viewer,&nbounds,&bounds);

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

    156:   PetscObjectGetComm((PetscObject)xin,&comm);
    157:   MPI_Comm_rank(comm,&rank);

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

    162:   /*
    163:         Obtain a sequential vector that is going to contain the local values plus ONE layer of
    164:      ghosted values to draw the graphics from. We also need its corresponding DMDA (dac) that will
    165:      update the local values pluse ONE layer of ghost values.
    166:   */
    167:   PetscObjectQuery((PetscObject)da,"GraphicsGhosted",(PetscObject*)&xlocal);
    168:   if (!xlocal) {
    169:     if (bx !=  DMDA_BOUNDARY_NONE || by !=  DMDA_BOUNDARY_NONE || s != 1 || st != DMDA_STENCIL_BOX) {
    170:       /*
    171:          if original da is not of stencil width one, or periodic or not a box stencil then
    172:          create a special DMDA to handle one level of ghost points for graphics
    173:       */
    174:       DMDACreate2d(comm,DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE,DMDA_STENCIL_BOX,M,N,zctx.m,zctx.n,w,1,lx,ly,&dac);
    175:       PetscInfo(da,"Creating auxilary DMDA for managing graphics ghost points\n");
    176:     } else {
    177:       /* otherwise we can use the da we already have */
    178:       dac = da;
    179:     }
    180:     /* create local vector for holding ghosted values used in graphics */
    181:     DMCreateLocalVector(dac,&xlocal);
    182:     if (dac != da) {
    183:       /* don't keep any public reference of this DMDA, is is only available through xlocal */
    184:       PetscObjectDereference((PetscObject)dac);
    185:     } else {
    186:       /* remove association between xlocal and da, because below we compose in the opposite
    187:          direction and if we left this connect we'd get a loop, so the objects could
    188:          never be destroyed */
    189:       PetscObjectRemoveReference((PetscObject)xlocal,"__PETSc_dm");
    190:     }
    191:     PetscObjectCompose((PetscObject)da,"GraphicsGhosted",(PetscObject)xlocal);
    192:     PetscObjectDereference((PetscObject)xlocal);
    193:   } else {
    194:     if (bx !=  DMDA_BOUNDARY_NONE || by !=  DMDA_BOUNDARY_NONE || s != 1 || st != DMDA_STENCIL_BOX) {
    195:       VecGetDM(xlocal, &dac);
    196:     } else {
    197:       dac = da;
    198:     }
    199:   }

    201:   /*
    202:       Get local (ghosted) values of vector
    203:   */
    204:   DMGlobalToLocalBegin(dac,xin,INSERT_VALUES,xlocal);
    205:   DMGlobalToLocalEnd(dac,xin,INSERT_VALUES,xlocal);
    206:   VecGetArray(xlocal,&zctx.v);

    208:   /* get coordinates of nodes */
    209:   DMGetCoordinates(da,&xcoor);
    210:   if (!xcoor) {
    211:     DMDASetUniformCoordinates(da,0.0,1.0,0.0,1.0,0.0,0.0);
    212:     DMGetCoordinates(da,&xcoor);
    213:   }

    215:   /*
    216:       Determine the min and max  coordinates in plot
    217:   */
    218:   VecStrideMin(xcoor,0,NULL,&xmin);
    219:   VecStrideMax(xcoor,0,NULL,&xmax);
    220:   VecStrideMin(xcoor,1,NULL,&ymin);
    221:   VecStrideMax(xcoor,1,NULL,&ymax);
    222:   coors[0] = xmin - .05*(xmax- xmin); coors[2] = xmax + .05*(xmax - xmin);
    223:   coors[1] = ymin - .05*(ymax- ymin); coors[3] = ymax + .05*(ymax - ymin);
    224:   PetscInfo4(da,"Preparing DMDA 2d contour plot coordinates %G %G %G %G\n",coors[0],coors[1],coors[2],coors[3]);

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

    228:   /*
    229:        get local ghosted version of coordinates
    230:   */
    231:   PetscObjectQuery((PetscObject)da,"GraphicsCoordinateGhosted",(PetscObject*)&xcoorl);
    232:   if (!xcoorl) {
    233:     /* create DMDA to get local version of graphics */
    234:     DMDACreate2d(comm,DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE,DMDA_STENCIL_BOX,M,N,zctx.m,zctx.n,2,1,lx,ly,&dag);
    235:     PetscInfo(dag,"Creating auxilary DMDA for managing graphics coordinates ghost points\n");
    236:     DMCreateLocalVector(dag,&xcoorl);
    237:     PetscObjectCompose((PetscObject)da,"GraphicsCoordinateGhosted",(PetscObject)xcoorl);
    238:     PetscObjectDereference((PetscObject)dag);
    239:     PetscObjectDereference((PetscObject)xcoorl);
    240:   } else {
    241:     VecGetDM(xcoorl,&dag);
    242:   }
    243:   DMGlobalToLocalBegin(dag,xcoor,INSERT_VALUES,xcoorl);
    244:   DMGlobalToLocalEnd(dag,xcoor,INSERT_VALUES,xcoorl);
    245:   VecGetArray(xcoorl,&zctx.xy);

    247:   /*
    248:         Get information about size of area each processor must do graphics for
    249:   */
    250:   DMDAGetInfo(dac,0,&M,&N,0,0,0,0,&zctx.step,0,&bx,&by,0,0);
    251:   DMDAGetGhostCorners(dac,0,0,0,&zctx.m,&zctx.n,0);

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

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

    257:   PetscViewerGetFormat(viewer,&format);
    258:   PetscOptionsGetBool(NULL,"-draw_ports",&useports,NULL);
    259:   if (useports || format == PETSC_VIEWER_DRAW_PORTS) {
    260:     PetscDrawSynchronizedClear(draw);
    261:     PetscDrawViewPortsCreate(draw,ndisplayfields,&ports);
    262:     zctx.name0 = 0;
    263:     zctx.name1 = 0;
    264:   } else {
    265:     DMDAGetCoordinateName(da,0,&zctx.name0);
    266:     DMDAGetCoordinateName(da,1,&zctx.name1);
    267:   }

    269:   /*
    270:      Loop over each field; drawing each in a different window
    271:   */
    272:   for (i=0; i<ndisplayfields; i++) {
    273:     zctx.k = displayfields[i];
    274:     if (useports) {
    275:       PetscDrawViewPortsSet(ports,i);
    276:     } else {
    277:       PetscViewerDrawGetDraw(viewer,i,&draw);
    278:     }

    280:     /*
    281:         Determine the min and max color in plot
    282:     */
    283:     VecStrideMin(xin,zctx.k,NULL,&zctx.min);
    284:     VecStrideMax(xin,zctx.k,NULL,&zctx.max);
    285:     if (zctx.k < nbounds) {
    286:       zctx.min = bounds[2*zctx.k];
    287:       zctx.max = bounds[2*zctx.k+1];
    288:     }
    289:     if (zctx.min == zctx.max) {
    290:       zctx.min -= 1.e-12;
    291:       zctx.max += 1.e-12;
    292:     }

    294:     if (!rank) {
    295:       const char *title;

    297:       DMDAGetFieldName(da,zctx.k,&title);
    298:       if (title) {
    299:         PetscDrawSetTitle(draw,title);
    300:       }
    301:     }
    302:     PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);
    303:     PetscInfo2(da,"DMDA 2d contour plot min %G max %G\n",zctx.min,zctx.max);

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

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

    310:     PetscDrawZoom(draw,VecView_MPI_Draw_DA2d_Zoom,&zctx);
    311:   }
    312:   PetscFree(displayfields);
    313:   PetscDrawViewPortsDestroy(ports);

    315:   VecRestoreArray(xcoorl,&zctx.xy);
    316:   VecRestoreArray(xlocal,&zctx.v);
    317:   return(0);
    318: }

    321: #if defined(PETSC_HAVE_HDF5)
    324: PetscErrorCode VecView_MPI_HDF5_DA(Vec xin,PetscViewer viewer)
    325: {
    326:   DM             dm;
    327:   DM_DA          *da;
    328:   hid_t          filespace;  /* file dataspace identifier */
    329:   hid_t          chunkspace; /* chunk dataset property identifier */
    330:   hid_t          plist_id;   /* property list identifier */
    331:   hid_t          dset_id;    /* dataset identifier */
    332:   hid_t          memspace;   /* memory dataspace identifier */
    333:   hid_t          file_id;
    334:   hid_t          group;
    335:   hid_t          scalartype; /* scalar type (H5T_NATIVE_FLOAT or H5T_NATIVE_DOUBLE) */
    336:   herr_t         status;
    337:   hsize_t        dim;
    338:   hsize_t        maxDims[6], dims[6], chunkDims[6], count[6], offset[6];
    339:   PetscInt       timestep;
    340:   PetscScalar    *x;
    341:   const char     *vecname;

    345:   PetscViewerHDF5OpenGroup(viewer, &file_id, &group);
    346:   PetscViewerHDF5GetTimestep(viewer, &timestep);

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

    352:   /* Create the dataspace for the dataset.
    353:    *
    354:    * dims - holds the current dimensions of the dataset
    355:    *
    356:    * maxDims - holds the maximum dimensions of the dataset (unlimited
    357:    * for the number of time steps with the current dimensions for the
    358:    * other dimensions; so only additional time steps can be added).
    359:    *
    360:    * chunkDims - holds the size of a single time step (required to
    361:    * permit extending dataset).
    362:    */
    363:   dim = 0;
    364:   if (timestep >= 0) {
    365:     dims[dim]      = timestep+1;
    366:     maxDims[dim]   = H5S_UNLIMITED;
    367:     chunkDims[dim] = 1;
    368:     ++dim;
    369:   }
    370:   if (da->dim == 3) {
    371:     PetscHDF5IntCast(da->P,dims+dim);
    372:     maxDims[dim]   = dims[dim];
    373:     chunkDims[dim] = dims[dim];
    374:     ++dim;
    375:   }
    376:   if (da->dim > 1) {
    377:     PetscHDF5IntCast(da->N,dims+dim);
    378:     maxDims[dim]   = dims[dim];
    379:     chunkDims[dim] = dims[dim];
    380:     ++dim;
    381:   }
    382:   PetscHDF5IntCast(da->M,dims+dim);
    383:   maxDims[dim]   = dims[dim];
    384:   chunkDims[dim] = dims[dim];
    385:   ++dim;
    386:   if (da->w > 1) {
    387:     PetscHDF5IntCast(da->w,dims+dim);
    388:     maxDims[dim]   = dims[dim];
    389:     chunkDims[dim] = dims[dim];
    390:     ++dim;
    391:   }
    392: #if defined(PETSC_USE_COMPLEX)
    393:   dims[dim]      = 2;
    394:   maxDims[dim]   = dims[dim];
    395:   chunkDims[dim] = dims[dim];
    396:   ++dim;
    397: #endif
    398:   filespace = H5Screate_simple(dim, dims, maxDims);
    399:   if (filespace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Screate_simple()");

    401: #if defined(PETSC_USE_REAL_SINGLE)
    402:   scalartype = H5T_NATIVE_FLOAT;
    403: #elif defined(PETSC_USE_REAL___FLOAT128)
    404: #error "HDF5 output with 128 bit floats not supported."
    405: #else
    406:   scalartype = H5T_NATIVE_DOUBLE;
    407: #endif

    409:   /* Create the dataset with default properties and close filespace */
    410:   PetscObjectGetName((PetscObject)xin,&vecname);
    411:   if (!H5Lexists(group, vecname, H5P_DEFAULT)) {
    412:     /* Create chunk */
    413:     chunkspace = H5Pcreate(H5P_DATASET_CREATE);
    414:     if (chunkspace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Pcreate()");
    415:     status = H5Pset_chunk(chunkspace, dim, chunkDims);CHKERRQ(status);

    417: #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
    418:     dset_id = H5Dcreate2(group, vecname, scalartype, filespace, H5P_DEFAULT, chunkspace, H5P_DEFAULT);
    419: #else
    420:     dset_id = H5Dcreate(group, vecname, scalartype, filespace, H5P_DEFAULT);
    421: #endif
    422:     if (dset_id == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Dcreate2()");
    423:   } else {
    424:     dset_id = H5Dopen2(group, vecname, H5P_DEFAULT);
    425:     status  = H5Dset_extent(dset_id, dims);CHKERRQ(status);
    426:   }
    427:   status = H5Sclose(filespace);CHKERRQ(status);

    429:   /* Each process defines a dataset and writes it to the hyperslab in the file */
    430:   dim = 0;
    431:   if (timestep >= 0) {
    432:     offset[dim] = timestep;
    433:     ++dim;
    434:   }
    435:   if (da->dim == 3) {PetscHDF5IntCast(da->zs,offset + dim++);}
    436:   if (da->dim > 1)  {PetscHDF5IntCast(da->ys,offset + dim++);}
    437:   PetscHDF5IntCast(da->xs/da->w,offset + dim++);
    438:   if (da->w > 1) offset[dim++] = 0;
    439: #if defined(PETSC_USE_COMPLEX)
    440:   offset[dim++] = 0;
    441: #endif
    442:   dim = 0;
    443:   if (timestep >= 0) {
    444:     count[dim] = 1;
    445:     ++dim;
    446:   }
    447:   if (da->dim == 3) {PetscHDF5IntCast(da->ze - da->zs,count + dim++);}
    448:   if (da->dim > 1)  {PetscHDF5IntCast(da->ye - da->ys,count + dim++);}
    449:   PetscHDF5IntCast((da->xe - da->xs)/da->w,count + dim++);
    450:   if (da->w > 1) {PetscHDF5IntCast(da->w,count + dim++);}
    451: #if defined(PETSC_USE_COMPLEX)
    452:   count[dim++] = 2;
    453: #endif
    454:   memspace = H5Screate_simple(dim, count, NULL);
    455:   if (memspace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Screate_simple()");

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

    461:   /* Create property list for collective dataset write */
    462:   plist_id = H5Pcreate(H5P_DATASET_XFER);
    463:   if (plist_id == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Pcreate()");
    464: #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
    465:   status = H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);CHKERRQ(status);
    466: #endif
    467:   /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */

    469:   VecGetArray(xin, &x);
    470:   status = H5Dwrite(dset_id, scalartype, memspace, filespace, plist_id, x);CHKERRQ(status);
    471:   status = H5Fflush(file_id, H5F_SCOPE_GLOBAL);CHKERRQ(status);
    472:   VecRestoreArray(xin, &x);

    474:   /* Close/release resources */
    475:   if (group != file_id) {
    476:     status = H5Gclose(group);CHKERRQ(status);
    477:   }
    478:   status = H5Pclose(plist_id);CHKERRQ(status);
    479:   status = H5Sclose(filespace);CHKERRQ(status);
    480:   status = H5Sclose(memspace);CHKERRQ(status);
    481:   status = H5Dclose(dset_id);CHKERRQ(status);
    482:   PetscInfo1(xin,"Wrote Vec object with name %s\n",vecname);
    483:   return(0);
    484: }
    485: #endif

    487: extern PetscErrorCode VecView_MPI_Draw_DA1d(Vec,PetscViewer);

    489: #if defined(PETSC_HAVE_MPIIO)
    492: static PetscErrorCode DMDAArrayMPIIO(DM da,PetscViewer viewer,Vec xin,PetscBool write)
    493: {
    494:   PetscErrorCode    ierr;
    495:   MPI_File          mfdes;
    496:   PetscMPIInt       gsizes[4],lsizes[4],lstarts[4],asiz,dof;
    497:   MPI_Datatype      view;
    498:   const PetscScalar *array;
    499:   MPI_Offset        off;
    500:   MPI_Aint          ub,ul;
    501:   PetscInt          type,rows,vecrows,tr[2];
    502:   DM_DA             *dd = (DM_DA*)da->data;

    505:   VecGetSize(xin,&vecrows);
    506:   if (!write) {
    507:     /* Read vector header. */
    508:     PetscViewerBinaryRead(viewer,tr,2,PETSC_INT);
    509:     type = tr[0];
    510:     rows = tr[1];
    511:     if (type != VEC_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_WRONG,"Not vector next in file");
    512:     if (rows != vecrows) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_SIZ,"Vector in file not same size as DMDA vector");
    513:   } else {
    514:     tr[0] = VEC_FILE_CLASSID;
    515:     tr[1] = vecrows;
    516:     PetscViewerBinaryWrite(viewer,tr,2,PETSC_INT,PETSC_TRUE);
    517:   }

    519:   PetscMPIIntCast(dd->w,&dof);
    520:   gsizes[0]  = dof;
    521:   PetscMPIIntCast(dd->M,gsizes+1);
    522:   PetscMPIIntCast(dd->N,gsizes+2);
    523:   PetscMPIIntCast(dd->P,gsizes+1);
    524:   lsizes[0]  = dof;
    525:   PetscMPIIntCast((dd->xe-dd->xs)/dof,lsizes+1);
    526:   PetscMPIIntCast(dd->ye-dd->ys,lsizes+2);
    527:   PetscMPIIntCast(dd->ze-dd->zs,lsizes+3);
    528:   lstarts[0] = 0;
    529:   PetscMPIIntCast(dd->xs/dof,lstarts+1);
    530:   PetscMPIIntCast(dd->ys,lstarts+2);
    531:   PetscMPIIntCast(dd->zs,lstarts+3);
    532:   MPI_Type_create_subarray(dd->dim+1,gsizes,lsizes,lstarts,MPI_ORDER_FORTRAN,MPIU_SCALAR,&view);
    533:   MPI_Type_commit(&view);

    535:   PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);
    536:   PetscViewerBinaryGetMPIIOOffset(viewer,&off);
    537:   MPI_File_set_view(mfdes,off,MPIU_SCALAR,view,(char*)"native",MPI_INFO_NULL);
    538:   VecGetArrayRead(xin,&array);
    539:   asiz = lsizes[1]*(lsizes[2] > 0 ? lsizes[2] : 1)*(lsizes[3] > 0 ? lsizes[3] : 1)*dof;
    540:   if (write) {
    541:     MPIU_File_write_all(mfdes,(PetscScalar*)array,asiz,MPIU_SCALAR,MPI_STATUS_IGNORE);
    542:   } else {
    543:     MPIU_File_read_all(mfdes,(PetscScalar*)array,asiz,MPIU_SCALAR,MPI_STATUS_IGNORE);
    544:   }
    545:   MPI_Type_get_extent(view,&ul,&ub);
    546:   PetscViewerBinaryAddMPIIOOffset(viewer,ub);
    547:   VecRestoreArrayRead(xin,&array);
    548:   MPI_Type_free(&view);
    549:   return(0);
    550: }
    551: #endif

    555: PetscErrorCode  VecView_MPI_DA(Vec xin,PetscViewer viewer)
    556: {
    557:   DM                da;
    558:   PetscErrorCode    ierr;
    559:   PetscInt          dim;
    560:   Vec               natural;
    561:   PetscBool         isdraw,isvtk;
    562: #if defined(PETSC_HAVE_HDF5)
    563:   PetscBool         ishdf5;
    564: #endif
    565:   const char        *prefix,*name;
    566:   PetscViewerFormat format;

    569:   VecGetDM(xin,&da);
    570:   if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA");
    571:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    572:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERVTK,&isvtk);
    573: #if defined(PETSC_HAVE_HDF5)
    574:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
    575: #endif
    576:   if (isdraw) {
    577:     DMDAGetInfo(da,&dim,0,0,0,0,0,0,0,0,0,0,0,0);
    578:     if (dim == 1) {
    579:       VecView_MPI_Draw_DA1d(xin,viewer);
    580:     } else if (dim == 2) {
    581:       VecView_MPI_Draw_DA2d(xin,viewer);
    582:     } else SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Cannot graphically view vector associated with this dimensional DMDA %D",dim);
    583:   } else if (isvtk) {           /* Duplicate the Vec and hold a reference to the DM */
    584:     Vec Y;
    585:     PetscObjectReference((PetscObject)da);
    586:     VecDuplicate(xin,&Y);
    587:     if (((PetscObject)xin)->name) {
    588:       /* If xin was named, copy the name over to Y. The duplicate names are safe because nobody else will ever see Y. */
    589:       PetscObjectSetName((PetscObject)Y,((PetscObject)xin)->name);
    590:     }
    591:     VecCopy(xin,Y);
    592:     PetscViewerVTKAddField(viewer,(PetscObject)da,DMDAVTKWriteAll,PETSC_VTK_POINT_FIELD,(PetscObject)Y);
    593: #if defined(PETSC_HAVE_HDF5)
    594:   } else if (ishdf5) {
    595:     VecView_MPI_HDF5_DA(xin,viewer);
    596: #endif
    597:   } else {
    598: #if defined(PETSC_HAVE_MPIIO)
    599:     PetscBool isbinary,isMPIIO;

    601:     PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
    602:     if (isbinary) {
    603:       PetscViewerBinaryGetMPIIO(viewer,&isMPIIO);
    604:       if (isMPIIO) {
    605:         DMDAArrayMPIIO(da,viewer,xin,PETSC_TRUE);
    606:         return(0);
    607:       }
    608:     }
    609: #endif

    611:     /* call viewer on natural ordering */
    612:     PetscObjectGetOptionsPrefix((PetscObject)xin,&prefix);
    613:     DMDACreateNaturalVector(da,&natural);
    614:     PetscObjectSetOptionsPrefix((PetscObject)natural,prefix);
    615:     DMDAGlobalToNaturalBegin(da,xin,INSERT_VALUES,natural);
    616:     DMDAGlobalToNaturalEnd(da,xin,INSERT_VALUES,natural);
    617:     PetscObjectGetName((PetscObject)xin,&name);
    618:     PetscObjectSetName((PetscObject)natural,name);

    620:     PetscViewerGetFormat(viewer,&format);
    621:     if (format == PETSC_VIEWER_BINARY_MATLAB) {
    622:       /* temporarily remove viewer format so it won't trigger in the VecView() */
    623:       PetscViewerSetFormat(viewer,PETSC_VIEWER_DEFAULT);
    624:     }

    626:     VecView(natural,viewer);

    628:     if (format == PETSC_VIEWER_BINARY_MATLAB) {
    629:       MPI_Comm    comm;
    630:       FILE        *info;
    631:       const char  *fieldname;
    632:       PetscInt    dim,ni,nj,nk,pi,pj,pk,dof,n;
    633:       PetscBool   flg;

    635:       /* set the viewer format back into the viewer */
    636:       PetscViewerSetFormat(viewer,format);
    637:       PetscObjectGetComm((PetscObject)viewer,&comm);
    638:       PetscViewerBinaryGetInfoPointer(viewer,&info);
    639:       DMDAGetInfo(da,&dim,&ni,&nj,&nk,&pi,&pj,&pk,&dof,0,0,0,0,0);
    640:       PetscFPrintf(comm,info,"%%--- begin code written by PetscViewerBinary for MATLAB format ---%\n");
    641:       PetscFPrintf(comm,info,"%%$$ tmp = PetscBinaryRead(fd); \n");
    642:       if (dim == 1) { PetscFPrintf(comm,info,"%%$$ tmp = reshape(tmp,%d,%d);\n",dof,ni); }
    643:       if (dim == 2) { PetscFPrintf(comm,info,"%%$$ tmp = reshape(tmp,%d,%d,%d);\n",dof,ni,nj); }
    644:       if (dim == 3) { PetscFPrintf(comm,info,"%%$$ tmp = reshape(tmp,%d,%d,%d,%d);\n",dof,ni,nj,nk); }

    646:       for (n=0; n<dof; n++) {
    647:         DMDAGetFieldName(da,n,&fieldname);
    648:         PetscStrcmp(fieldname,"",&flg);
    649:         if (!flg) {
    650:           if (dim == 1) { PetscFPrintf(comm,info,"%%$$ Set.%s.%s = squeeze(tmp(%d,:))';\n",name,fieldname,n+1); }
    651:           if (dim == 2) { PetscFPrintf(comm,info,"%%$$ Set.%s.%s = squeeze(tmp(%d,:,:))';\n",name,fieldname,n+1); }
    652:           if (dim == 3) { PetscFPrintf(comm,info,"%%$$ Set.%s.%s = permute(squeeze(tmp(%d,:,:,:)),[2 1 3]);\n",name,fieldname,n+1);}
    653:         }
    654:       }
    655:       PetscFPrintf(comm,info,"%%$$ clear tmp; \n");
    656:       PetscFPrintf(comm,info,"%%--- end code written by PetscViewerBinary for MATLAB format ---%\n\n");
    657:     }

    659:     VecDestroy(&natural);
    660:   }
    661:   return(0);
    662: }

    664: #if defined(PETSC_HAVE_HDF5)
    667: PetscErrorCode VecLoad_HDF5_DA(Vec xin, PetscViewer viewer)
    668: {
    669:   DM             da;
    671:   hsize_t        dim;
    672:   hsize_t        count[5];
    673:   hsize_t        offset[5];
    674:   PetscInt       cnt = 0;
    675:   PetscScalar    *x;
    676:   const char     *vecname;
    677:   hid_t          filespace; /* file dataspace identifier */
    678:   hid_t          plist_id;  /* property list identifier */
    679:   hid_t          dset_id;   /* dataset identifier */
    680:   hid_t          memspace;  /* memory dataspace identifier */
    681:   hid_t          file_id;
    682:   herr_t         status;
    683:   DM_DA          *dd;

    686:   PetscViewerHDF5GetFileId(viewer, &file_id);
    687:   VecGetDM(xin,&da);
    688:   dd   = (DM_DA*)da->data;

    690:   /* Create the dataspace for the dataset */
    691:   PetscHDF5IntCast(dd->dim + ((dd->w == 1) ? 0 : 1),&dim);
    692: #if defined(PETSC_USE_COMPLEX)
    693:   dim++;
    694: #endif

    696:   /* Create the dataset with default properties and close filespace */
    697:   PetscObjectGetName((PetscObject)xin,&vecname);
    698: #if (H5_VERS_MAJOR * 10000 + H5_VERS_MINOR * 100 + H5_VERS_RELEASE >= 10800)
    699:   dset_id = H5Dopen2(file_id, vecname, H5P_DEFAULT);
    700: #else
    701:   dset_id = H5Dopen(file_id, vecname);
    702: #endif
    703:   if (dset_id == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Dopen2() with Vec named %s",vecname);
    704:   filespace = H5Dget_space(dset_id);

    706:   /* Each process defines a dataset and reads it from the hyperslab in the file */
    707:   cnt = 0;
    708:   if (dd->dim == 3) {PetscHDF5IntCast(dd->zs,offset + cnt++);}
    709:   if (dd->dim > 1)  {PetscHDF5IntCast(dd->ys,offset + cnt++);}
    710:   PetscHDF5IntCast(dd->xs/dd->w,offset + cnt++);
    711:   if (dd->w > 1) offset[cnt++] = 0;
    712: #if defined(PETSC_USE_COMPLEX)
    713:   offset[cnt++] = 0;
    714: #endif
    715:   cnt = 0;
    716:   if (dd->dim == 3) {PetscHDF5IntCast(dd->ze - dd->zs,count + cnt++);}
    717:   if (dd->dim > 1)  {PetscHDF5IntCast(dd->ye - dd->ys,count + cnt++);}
    718:   PetscHDF5IntCast((dd->xe - dd->xs)/dd->w,count + cnt++);
    719:   if (dd->w > 1) {PetscHDF5IntCast(dd->w,count + cnt++);}
    720: #if defined(PETSC_USE_COMPLEX)
    721:   count[cnt++] = 2;
    722: #endif
    723:   memspace = H5Screate_simple(dim, count, NULL);
    724:   if (memspace == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Screate_simple()");

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

    728:   /* Create property list for collective dataset write */
    729:   plist_id = H5Pcreate(H5P_DATASET_XFER);
    730:   if (plist_id == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot H5Pcreate()");
    731: #if defined(PETSC_HAVE_H5PSET_FAPL_MPIO)
    732:   status = H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);CHKERRQ(status);
    733: #endif
    734:   /* To write dataset independently use H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_INDEPENDENT) */

    736:   VecGetArray(xin, &x);
    737:   status = H5Dread(dset_id, H5T_NATIVE_DOUBLE, memspace, filespace, plist_id, x);CHKERRQ(status);
    738:   VecRestoreArray(xin, &x);

    740:   /* Close/release resources */
    741:   status = H5Pclose(plist_id);CHKERRQ(status);
    742:   status = H5Sclose(filespace);CHKERRQ(status);
    743:   status = H5Sclose(memspace);CHKERRQ(status);
    744:   status = H5Dclose(dset_id);CHKERRQ(status);
    745:   return(0);
    746: }
    747: #endif

    751: PetscErrorCode VecLoad_Binary_DA(Vec xin, PetscViewer viewer)
    752: {
    753:   DM             da;
    755:   Vec            natural;
    756:   const char     *prefix;
    757:   PetscInt       bs;
    758:   PetscBool      flag;
    759:   DM_DA          *dd;
    760: #if defined(PETSC_HAVE_MPIIO)
    761:   PetscBool isMPIIO;
    762: #endif

    765:   VecGetDM(xin,&da);
    766:   dd   = (DM_DA*)da->data;
    767: #if defined(PETSC_HAVE_MPIIO)
    768:   PetscViewerBinaryGetMPIIO(viewer,&isMPIIO);
    769:   if (isMPIIO) {
    770:     DMDAArrayMPIIO(da,viewer,xin,PETSC_FALSE);
    771:     return(0);
    772:   }
    773: #endif

    775:   PetscObjectGetOptionsPrefix((PetscObject)xin,&prefix);
    776:   DMDACreateNaturalVector(da,&natural);
    777:   PetscObjectSetName((PetscObject)natural,((PetscObject)xin)->name);
    778:   PetscObjectSetOptionsPrefix((PetscObject)natural,prefix);
    779:   VecLoad(natural,viewer);
    780:   DMDANaturalToGlobalBegin(da,natural,INSERT_VALUES,xin);
    781:   DMDANaturalToGlobalEnd(da,natural,INSERT_VALUES,xin);
    782:   VecDestroy(&natural);
    783:   PetscInfo(xin,"Loading vector from natural ordering into DMDA\n");
    784:   PetscOptionsGetInt(((PetscObject)xin)->prefix,"-vecload_block_size",&bs,&flag);
    785:   if (flag && bs != dd->w) {
    786:     PetscInfo2(xin,"Block size in file %D not equal to DMDA's dof %D\n",bs,dd->w);
    787:   }
    788:   return(0);
    789: }

    793: PetscErrorCode  VecLoad_Default_DA(Vec xin, PetscViewer viewer)
    794: {
    796:   DM             da;
    797:   PetscBool      isbinary;
    798: #if defined(PETSC_HAVE_HDF5)
    799:   PetscBool ishdf5;
    800: #endif

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

    806: #if defined(PETSC_HAVE_HDF5)
    807:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);
    808: #endif
    809:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);

    811:   if (isbinary) {
    812:     VecLoad_Binary_DA(xin,viewer);
    813: #if defined(PETSC_HAVE_HDF5)
    814:   } else if (ishdf5) {
    815:     VecLoad_HDF5_DA(xin,viewer);
    816: #endif
    817:   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for vector loading", ((PetscObject)viewer)->type_name);
    818:   return(0);
    819: }