src/hdf5/parallel/H5Part.cc

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <hdf5.h>
00004 #include "H5Part.hh"
00005 
00006 /********* Private Function Declarations *************/
00007 herr_t H5PartIOcounter(hid_t group_id,
00008                    const char *member_name,
00009                    void *operator_data);
00010 
00011 
00012 /********** Definitions of Functions/Subroutines ******/
00013 
00014 /*========== File Opening/Closing ===============*/
00015 /*
00016   H5PartOpenFile:  Opens file with specified filename. 
00017     If you open with flag H5PART_WRITE, it will truncate any
00018     file with the specified filename and start writing to it.
00019     If you open with H5PART_READ, then it will open the file
00020     readonly.  I could probably do an APPEND mode as well, but
00021     just haven't done so yet.  APPEND would need to check the
00022     file to determine its current state and modify the 
00023     H5PartFile datastructure accordingly.
00024 
00025     H5PartFile should be treated as an essentially opaque
00026     datastructure.  It acts as the file handle, but internally
00027     it maintains several key state variables associated with 
00028     the file.
00029 */
00030 
00031 H5PartFile *H5PartOpenFileParallel(const char *filename,unsigned flags
00032 #ifdef PARALLEL_IO
00033                 ,                  MPI_Comm comm
00034 #endif
00035 ){
00036   H5PartFile *f=(H5PartFile*)malloc(sizeof(H5PartFile));
00037 #ifdef PARALLEL_IO
00038   MPI_Info info = MPI_INFO_NULL; /* for the SP2... perhaps different for linux */
00039 #endif
00040   f->xfer_prop = f->create_prop = f->access_prop=H5P_DEFAULT;
00041 #ifdef PARALLEL_IO
00042   MPI_Comm_size(comm,&f->nprocs);
00043   MPI_Comm_rank(comm,&f->myproc);
00044   f->pnparticles=(long long*)malloc(sizeof(long long)*f->nprocs);
00045   /* access_prop: properties like chunking or parallel I/O */
00046   f->access_prop = H5Pcreate(H5P_FILE_ACCESS);
00047   if(H5Pset_fapl_mpio(f->access_prop,comm,info)<0){
00048         fprintf(stderr,"Total failure trying to setup mpi-io for access\n");
00049         exit(0);
00050   }
00051   /* create_prop: tunable parameters like blocksize and btree sizes */
00052   /* f->create_prop = H5Pcreate(H5P_FILE_CREATE); */
00053   f->create_prop = H5P_DEFAULT;
00054   /* currently create_prop is empty */
00055   /* xfer_prop:  also used for parallel I/O, during actual writes
00056           rather than the access_prop which is for file creation. */
00057   f->xfer_prop = H5Pcreate(H5P_DATASET_XFER);
00058   H5Pset_dxpl_mpio(f->xfer_prop,H5FD_MPIO_COLLECTIVE);
00059   f->comm = comm;
00060 #endif
00061   if(flags==H5PART_READ){
00062     /*  f->file=H5Fopen(filename,H5F_ACC_RDONLY,f->access_prop); */
00063     /* just do this serially */
00064     f->file = H5Fopen(filename,H5F_ACC_RDONLY,H5P_DEFAULT);
00065   }
00066   else if(flags==H5PART_WRITE){
00067     f->file=H5Fcreate(filename,H5F_ACC_TRUNC,f->create_prop,f->access_prop);
00068   }
00069   else {
00070     f->file=-1;
00071     fprintf(stderr,"H5Open: Invalid file access type %d\n",flags);
00072   }
00073   if(f->file<=0) {
00074     free(f);
00075     fprintf(stderr,"H5Open: File open failed for file [%s]\n",
00076             filename);
00077         exit(0); 
00078         return 0;
00079   }
00080   f->mode=flags;
00081   f->maxstep=0;
00082   f->timegroup=0;
00083   f->timestep=0;
00084   f->shape=0;
00085   f->diskshape=H5S_ALL;
00086   f->memshape=H5S_ALL;
00087   return f;
00088 }
00089 
00090 H5PartFile *H5PartOpenFile(const char *filename,unsigned flags){
00091   H5PartFile *f=(H5PartFile*)malloc(sizeof(H5PartFile));
00092   f->xfer_prop = f->create_prop = f->access_prop=H5P_DEFAULT;
00093 #ifdef PARALLEL_IO
00094   f->pnparticles=0;
00095   f->comm = MPI_COMM_WORLD;
00096   f->nprocs=1;
00097   f->myproc=0;
00098 #endif
00099   if(flags==H5PART_READ){
00100     /*  f->file=H5Fopen(filename,H5F_ACC_RDONLY,f->access_prop); */
00101     /* just do this serially */
00102     f->file = H5Fopen(filename,H5F_ACC_RDONLY,H5P_DEFAULT);
00103   }
00104   else if(flags==H5PART_WRITE){
00105     f->file=H5Fcreate(filename,H5F_ACC_TRUNC,H5P_DEFAULT,H5P_DEFAULT);
00106   }
00107   else {
00108     f->file=-1;
00109     fprintf(stderr,"H5Open: Invalid file access type %d\n",flags);
00110   }
00111   if(f->file<0) {
00112     free(f);
00113     fprintf(stderr,"H5Open: File open failed for file [%s]\n",
00114             filename);
00115     return 0;
00116   }
00117   f->mode=flags;
00118   f->maxstep=0;
00119   f->timegroup=0;
00120   f->timestep=0;
00121   f->shape=0;
00122   f->diskshape=H5S_ALL;
00123   f->memshape=H5S_ALL;
00124   return f;
00125 }
00126 /*
00127   H5PartCloseFile:  Does what it says it does.
00128 */
00129 void H5PartCloseFile(H5PartFile *f){
00130   if(f->shape>0) H5Sclose(f->shape); f->shape=0;
00131   if(f->timegroup>0) H5Gclose(f->timegroup); f->timegroup=0;
00132   if(f->diskshape!=H5S_ALL) H5Sclose(f->diskshape);
00133 #ifdef PARALLEL_IO
00134   if(f->pnparticles) free(f->pnparticles);
00135 #endif
00136   if(f->xfer_prop!=H5P_DEFAULT) {
00137     H5Pclose(f->xfer_prop); f->xfer_prop=H5P_DEFAULT;
00138   }
00139   if(f->access_prop!=H5P_DEFAULT) {
00140     H5Pclose(f->access_prop); f->access_prop=H5P_DEFAULT;
00141   }  
00142   if(f->create_prop!=H5P_DEFAULT) {
00143     H5Pclose(f->create_prop); f->create_prop=H5P_DEFAULT;
00144   }
00145   if(f->file) H5Fclose(f->file); f->file=0;
00146   free(f);
00147 }
00148 
00149 
00150 /*============== File Writing Functions ==================== */
00151 /*
00152   H5PartSetNumParticles:  This is a private function used by the 
00153   other functions that write arrays.  Its sole purpose is to 
00154   prevent needless creation of new HDF5 DataSpace handles if
00155   the number of particles is invariant throughout the sim.
00156   That's its only reason for existence.
00157 */
00158 void H5PartSetNumParticles(H5PartFile *f,long long nparticles){
00159   hssize_t start[1];
00160   hsize_t stride[1],count[1],total;
00161   register int i,r;
00162   /*  printf("Set Number of Particles to %lld\n",nparticles); */
00163   if(f->nparticles==nparticles) return; // no change
00164   if(f->diskshape!=H5S_ALL) H5Sclose(f->diskshape);
00165   if(f->memshape!=H5S_ALL) H5Sclose(f->memshape);
00166   f->memshape=f->diskshape = H5S_ALL;
00167   if(f->shape) H5Sclose(f->shape);
00168   f->nparticles=(hsize_t)nparticles;
00169 #ifndef PARALLEL_IO
00170   f->shape=H5Screate_simple(1, /* 1 dimensional shape */
00171                             &(f->nparticles), /* with nparticles elements */
00172                             NULL); /* ignore this :-) */
00173 #else /* PARALLEL_IO */
00174   /* The Gameplan here is to declare the overall size of the on-disk
00175      data structure the same way we do for the serial case.  But
00176      then we must have additional "DataSpace" structures to define
00177      our in-memory layout of our domain-decomposed portion of the particle
00178      list as well as a "selection" of a subset of the on-disk 
00179      data layout that will be written in parallel to mutually exclusive
00180      regions by all of the processors during a parallel I/O operation.
00181      These are f->shape, f->memshape and f->diskshape respectively. */
00182   /* acquire the number of particles to be written from each MPI process */
00183   MPI_Allgather(&nparticles,1,MPI_LONG_LONG,f->pnparticles,1,MPI_LONG_LONG,f->comm);
00184 
00185   //  if(f->myproc==0){
00186   //    puts("AllGather:  Particle offsets:\n");
00187   //    for(i=0;i<f->nprocs;i++) 
00188   //            printf("\tnp=%u\n",f->pnparticles[i]); /* compute total nparticles */
00189   //}
00190   /* should I create a selection here? */
00191   stride[0]=1;
00192   start[0]=0;
00193   for(i=0;i<f->myproc;i++) start[0]+=f->pnparticles[i]; /* compute start offsets */
00194   total=0;
00195   for(i=0;i<f->nprocs;i++) total+=f->pnparticles[i]; /* compute total nparticles */
00196   f->shape = H5Screate_simple(1,&total,NULL); /* declare overall datasize */
00197   f->diskshape = H5Screate_simple(1,&total,NULL); /* declare overall data size  but then will select a subset */
00198   f->memshape = H5Screate_simple(1,&(f->nparticles),NULL); /* declare local memory datasize */
00199 
00200   if(f->shape<0 || f->memshape<0 || f->diskshape<0){
00201         fprintf(stderr,"Abort:  shape construction failed\n");
00202         exit(0);
00203 }
00204   count[0]=nparticles; /* based on local nparticles (for the selection */
00205   /* and then set the subset of the data you will write to */
00206   r=H5Sselect_hyperslab(f->diskshape,H5S_SELECT_SET,start,stride,count,NULL);
00207   if(r<0){
00208         fprintf(stderr,"Abort: Selection Failed!\n");
00209         exit(0);
00210   }
00211 #endif
00212 }
00213 
00214 /*
00215   H5PartWriteArray:  This writes an individual array of data
00216     for a given timestep.  It probably would be convenient if this
00217     were public, but its private because it there are some order/
00218     state dependencies that get kind of nasty to manage (and therefore
00219     are not managed).  It is otherwise assuming that the timegroup
00220     has already been created and other such details.
00221     It is called by the mongo H5PartWriteStep() routine.
00222  */
00223 int H5PartWriteDataFloat64(H5PartFile *f,char *name,double *array){
00224   register int r;
00225   hid_t dataset;
00226   //fprintf(stderr,"Create a dataset[%s]  mounted on the timegroup %u\n",
00227   //     name,f->timestep);
00228   if(f->timegroup<=0) {fprintf(stderr,"Eeeerrrrroooorrrr!!!!\n");}
00229   dataset = H5Dcreate(f->timegroup,name,H5T_NATIVE_DOUBLE,f->shape,H5P_DEFAULT);
00230   if(dataset<0)
00231     fprintf(stderr,"Dataset open failed for name=[%s] step=%u!\n",
00232             name,f->timestep);
00233   r=H5Dwrite(dataset,H5T_NATIVE_DOUBLE,f->memshape,f->diskshape,H5P_DEFAULT,array);
00234   H5Dclose(dataset);
00235   return r;
00236 }
00237 int H5PartWriteDataInt64(H5PartFile *f,char *name,long long *array){
00238   register int r;
00239   hid_t dataset;
00240   //fprintf(stderr,"Create a dataset[%s]  mounted on the timegroup %u\n",
00241   //     name,f->timestep);
00242   if(f->timegroup<=0) {fprintf(stderr,"Eeeerrrrroooorrrr!!!!\n");}
00243   dataset = H5Dcreate(f->timegroup,name,H5T_NATIVE_INT64,f->shape,H5P_DEFAULT);
00244   if(dataset<0){
00245     fprintf(stderr,"Dataset open failed for name=[%s] step=%u!\n",
00246             name,f->timestep);
00247     exit(0);
00248   }
00249   r=H5Dwrite(dataset,H5T_NATIVE_INT64,f->memshape,f->diskshape,H5P_DEFAULT,array);
00250   if(r<0) {
00251         fprintf(stderr,"Attempt to write dataset failed!\n");
00252         exit(0);
00253   }
00254   H5Dclose(dataset);
00255   return r;
00256 }
00257 
00258 int H5PartWriteStepAttrib(H5PartFile *f,char *name,
00259                           hid_t type,void *value,int nelem){
00260   register int r;
00261   hid_t attrib;
00262   hid_t space;
00263   hsize_t len;
00264   //fprintf(stderr,"Create a attribute[%s]  mounted on the timegroup %u\n",
00265   //     name,f->timestep);
00266   if(f->timegroup<=0) {fprintf(stderr,"Eeeerrrrroooorrrr!!!!\n");}
00267   len = nelem;
00268   space = H5Screate_simple(1,&len,NULL);
00269   attrib = H5Acreate(f->timegroup,name,type,space,H5P_DEFAULT);
00270   r=H5Awrite(attrib,type,value);
00271   H5Aclose(attrib);
00272   H5Sclose(space);
00273   return r;
00274 }
00275 
00276 int H5PartWriteAttrib(H5PartFile *f,char *name,
00277     hid_t type,void *value,int nelem){
00278     return H5PartWriteStepAttrib(f,name,type,value,nelem);
00279 }
00280 
00281 int H5PartWriteFileAttrib(H5PartFile *f,char *name,
00282                           hid_t type,void *value,int nelem){
00283   register int r;
00284   hid_t attrib;
00285   hid_t space;
00286   hsize_t len;
00287   //fprintf(stderr,"Create a attribute[%s]  mounted on the timegroup %u\n",
00288   //     name,f->timestep);
00289   if(f->file<=0) {fprintf(stderr,"Eeeerrrrroooorrrr!!!!\n");}
00290   len = nelem;
00291   space = H5Screate_simple(1,&len,NULL);
00292   attrib = H5Acreate(f->file,name,type,space,H5P_DEFAULT);
00293   r=H5Awrite(attrib,type,value);
00294   H5Aclose(attrib);
00295   H5Sclose(space);
00296   return r;
00297 }
00298 herr_t H5PartAttribcounter(hid_t group_id,
00299                    const char *member_name,
00300                    void *operator_data){
00301   int *count = (int*)operator_data;
00302   (*count)++;
00303   return 0;
00304 }
00305 int H5PartGetNumStepAttribs(H5PartFile *f){ /* for current filestep */
00306   return H5Aget_num_attrs(f->timegroup);
00307 }
00308 int H5PartGetNumFileAttribs(H5PartFile *f){
00309   /* must walk the attributes */
00310   /* iterate to get numsteps */
00311   int nattribs;
00312   hid_t rootgroup=H5Gopen(f->file,"/");;
00313   nattribs=H5Aget_num_attrs(rootgroup); /* open / for the file?
00314                                        or is there a problem with 
00315                                        file attributes? */
00316   H5Gclose(rootgroup);
00317   return nattribs;
00318 }
00319 
00320 hid_t H5PartNormType(hid_t type){
00321   H5T_class_t tclass = H5Tget_class(type);
00322   int size = H5Tget_size(type);
00323   switch(tclass){
00324   case H5T_INTEGER:
00325     if(size==8) return H5T_NATIVE_INT64;
00326     else if(size==1) return H5T_NATIVE_CHAR;
00327     else fprintf(stderr,"Unknown type %u.  Cannot infer normalized type\n",type);
00328     break;
00329   case H5T_FLOAT:
00330     return H5T_NATIVE_DOUBLE;
00331     break;
00332   }
00333   return -1;
00334 }
00335 
00336 void H5PartGetStepAttribInfo(H5PartFile *f,int idx,
00337                          char *name,size_t maxname,hid_t *type,int *nelem){
00338   hid_t attrib=H5Aopen_idx(f->timegroup,idx);
00339   hid_t mytype=H5Aget_type(attrib);
00340   hid_t space = H5Aget_space(attrib);
00341   if(nelem)
00342     *nelem=H5Sget_simple_extent_npoints(space);
00343   if(name)
00344     H5Aget_name(attrib,maxname,name);
00345   if(type)
00346     *type=H5PartNormType(mytype); /* normalize the type to be machine-native
00347                                  this means one of 
00348                                 H5T_NATIVE_DOUBLE
00349                                 H5T_NATIVE_INT64
00350                                 H5T_NATIVE_CHAR */
00351   H5Sclose(space);
00352   H5Tclose(mytype);
00353   H5Aclose(attrib);
00354 }
00355 void H5PartGetFileAttribInfo(H5PartFile *f,int idx,
00356                          char *name,size_t maxname,hid_t *type,int *nelem){
00357   hid_t attrib=H5Aopen_idx(f->file,idx);
00358   hid_t mytype=H5Aget_type(attrib);
00359   hid_t space = H5Aget_space(attrib);
00360   if(nelem)
00361     *nelem=H5Sget_simple_extent_npoints(space);
00362   if(name)
00363     H5Aget_name(attrib,maxname,name);
00364   if(type)
00365     *type=H5PartNormType(mytype); /* normalize the type to be machine-native
00366                                  this means one of 
00367                                 H5T_NATIVE_DOUBLE
00368                                 H5T_NATIVE_INT64
00369                                 H5T_NATIVE_CHAR */
00370   H5Sclose(space);
00371   H5Tclose(mytype);
00372   H5Aclose(attrib);
00373 }
00374 void H5ReadStepAttrib(H5PartFile *f,char *name,void *data){
00375   /* use the open attribute by name mode of operation */
00376   hid_t attrib=H5Aopen_name(f->timegroup,name);
00377   hid_t mytype=H5Aget_type(attrib);
00378   hid_t space = H5Aget_space(attrib);
00379   hsize_t nelem=H5Sget_simple_extent_npoints(space);
00380   hid_t type=H5PartNormType(mytype); /* normalize the type to be machine-native
00381                                  this means one of 
00382                                 H5T_NATIVE_DOUBLE
00383                                 H5T_NATIVE_INT64
00384                                 H5T_NATIVE_CHAR */
00385   H5Aread(attrib,type,data);
00386   H5Sclose(space);
00387   H5Tclose(mytype);
00388   H5Aclose(attrib);
00389 }
00390 
00391 void H5PartReadAttrib(H5PartFile *f,char *name,void *data){
00392     /* use the open attribute by name mode of operation */
00393     H5ReadStepAttrib(f,name,data);
00394 }
00395 
00396 void H5ReadFileAttrib(H5PartFile *f,char *name,void *data){
00397   hid_t attrib=H5Aopen_name(f->file,name);
00398   hid_t mytype=H5Aget_type(attrib);
00399   hid_t space = H5Aget_space(attrib);
00400   hsize_t nelem=H5Sget_simple_extent_npoints(space);
00401   hid_t type=H5PartNormType(mytype); /* normalize the type to be machine-native
00402                                  this means one of 
00403                                 H5T_NATIVE_DOUBLE
00404                                 H5T_NATIVE_INT64
00405                                 H5T_NATIVE_CHAR */
00406   H5Aread(attrib,type,data);
00407   H5Sclose(space);
00408   H5Tclose(mytype);
00409   H5Aclose(attrib);
00410 }
00411 
00412 
00413 /*================== File Reading Routines =================*/
00414 /*
00415   H5PartSetStep:  This routine is *only* useful when you are reading
00416   data.  Using it while you are writing will generate nonsense results!
00417   (This file format is only half-baked... robustness is not std equipment!)
00418   So you use this to random-access the file for a particular timestep.
00419   Failure to explicitly set the timestep on each read will leave you
00420   stuck on the same timestep for *all* of your reads.  That is to say
00421   the writes auto-advance the file pointer, but the reads do not
00422   (they require explicit advancing by selecting a particular timestep).
00423 */
00424 void H5PartSetStep(H5PartFile *f,int step){
00425   char name[128];
00426   /*printf("Proc[%u] SetStep to %u for file %u\n",f->myproc,step,f->file);  */
00427   f->timestep=step;
00428   if(f->timegroup>0) {
00429         H5Gclose(f->timegroup); 
00430   }
00431   f->timegroup=-1;
00432   sprintf(name,"Particles#%u",f->timestep);
00433   /*fprintf(stderr,"P[%u] Open timegroup [%s] for file %d\n",
00434         f->myproc,name,f->file);*/
00435   if(f->mode==H5PART_READ) { /* kludge to prevent error messages */
00436 /*      fprintf(stderr,"P[%u] open group\n"); */
00437     f->timegroup=H5Gopen(f->file,name);
00438   }
00439   if(f->timegroup<=0){
00440     /* timegroup doesn't exist, so we need to create one */
00441         /* fprintf(stderr,"P[%u] create group\n"); */
00442     f->timegroup = H5Gcreate(f->file,name,0);
00443     if(f->timegroup<0) 
00444         fprintf(stderr,"p[%u] timegroup creation failed!\n",
00445                 f->myproc);
00446   }
00447 }
00448 
00449 /*
00450   H5PartIOcounter:  This is an entirely internal callback function 
00451    which is used in conjunction with HDF5 iterators.  The HDF5 Group
00452    iterator will call this repeatedly in order to count how many
00453    timesteps of data have been stored in a particular file.
00454    This is used by H5PartGetNumSteps().
00455 */
00456 herr_t H5PartIOcounter(hid_t group_id,
00457                    const char *member_name,
00458                    void *operator_data){
00459   int *count = (int*)operator_data;
00460   H5G_stat_t objinfo;
00461   /* only count the particle groups... ignore all others */
00462   if(!strncmp(member_name,"Particles",9)) (*count)++;
00463   return 0;
00464 }
00465 herr_t H5PartDScounter(hid_t group_id,
00466                    const char *member_name,
00467                    void *operator_data){
00468   int *count = (int*)operator_data;
00469   H5G_stat_t objinfo;
00470   /* only count the datasets... ignore all others */
00471   if(H5Gget_objinfo(group_id, 
00472                  member_name,
00473                  1 /* follow links */, 
00474                     &objinfo)<0) {
00475     return 0; /* error (probably bad symlink) */
00476   }
00477   if(objinfo.type==H5G_DATASET)    (*count)++;
00478   return 0;
00479 }
00480 struct H5IO_getname_t {
00481   int index,count;
00482   char *name;
00483 };
00484 herr_t H5IOgetname(hid_t group_id,
00485                           const char *member_name, 
00486                           void *operator_data){
00487   H5IO_getname_t *getn = (H5IO_getname_t*)operator_data;
00488   // check type first (only respond if it is a dataset)
00489   H5G_stat_t objinfo;
00490   // request info about the type of objects in root group
00491   if(H5Gget_objinfo(group_id, 
00492                     member_name,
00493                     1 /* follow links */, 
00494                     &objinfo)<0) return 0; // error (probably bad symlink)
00495   // only count objects that are datasets (not subgroups)
00496   if(objinfo.type!=H5G_DATASET) 
00497     return 0; // do not increment count if it isn't a dataset.
00498   if(getn->index==getn->count){
00499     strcpy(getn->name,member_name);
00500     return 1; // success
00501   }
00502   getn->count++;
00503   return 0;
00504 }
00505 /* 
00506    H5PartGetNumSteps:  This reads the number of datasteps that are 
00507      currently stored in the datafile.  (simple return of an int).
00508      It works for both reading and writing of files, but is probably
00509      only typically used when you are reading.
00510 */
00511 int H5PartGetNumSteps(H5PartFile *f){
00512   /* iterate to get numsteps */
00513   int count=0;
00514   int idx=0;
00515   while(H5Giterate(f->file, /* hid_t loc_id, */
00516                    "/", /*const char *name, */
00517                    &idx, /* int *idx, */
00518                    H5PartIOcounter,
00519                    &count)<0){}  
00520   return count;
00521 }
00522 int H5PartGetNumDatasets(H5PartFile *f){
00523   int count=0;
00524   int idx=0;
00525   char name[128];
00526   sprintf(name,"Particles#%u",f->timestep);
00527   while(H5Giterate(f->file, /* hid_t loc_id */
00528                    name,
00529                    &idx,
00530                    H5PartDScounter,
00531                    &count)<0){}
00532   return count;   
00533 }
00534 int H5PartGetDatasetName(H5PartFile *f,
00535                          int _index, /* index of the dataset (0 to N-1) */
00536                          char *name, /* buffer to store name of dataset */
00537                          int maxlen){ /* max size of the "name" buffer */
00538   H5IO_getname_t getn;
00539   int idx=_index;
00540   char gname[128];
00541   sprintf(gname,"Particles#%u",f->timestep);
00542   getn.index=_index; getn.name=name; getn.count=_index;
00543   while(H5Giterate(f->file, /* hid_t loc_id, */
00544                    gname, /*const char *name, */
00545                    &idx, /* int *idx, */
00546                    H5IOgetname,
00547                    &getn)<0){}
00548   return 1;
00549 }
00550 
00551 /*
00552   H5PartGetNumParticles:  This gets the number of particles 
00553     that are stored in the current timestep.  It will arbitrarily
00554     select a timestep if you haven't already set the timestep
00555     with H5PartSetStep().
00556  */
00557 long long H5PartGetNumParticles(H5PartFile *f){
00558   hid_t space,dataset;
00559   hsize_t nparticles;
00560   if(f->timegroup<=0) H5PartSetStep(f,f->timestep); /* choose a step */
00561   /* lets open up a dataset in this group... we know "x" is there */
00562   dataset=H5Dopen(f->timegroup,"x");/* choice of X is a kludge of sorts */
00563   space = H5Dget_space(dataset);
00564   nparticles= H5Sget_simple_extent_npoints(space);
00565   H5Sclose(space); /* release data shape handle */
00566   H5Dclose(dataset); /* release the dataset handle */
00567   return (long long)nparticles;
00568 }
00569 
00570 
00571 /*
00572   H5PartReadArray:  This reads in an individual array from a
00573     particlar timestep.  Unlike its "Write" mode sibling, this routine
00574     is completely public and will not have any wacky state dependencies.
00575     If you haven't selected a particular timestep, it will pick
00576     the current one.
00577 */
00578 int H5PartReadDataFloat64(H5PartFile *f,char *name,double *array){
00579   hid_t space,dataset,datatype;
00580   if(!f->timegroup) H5PartSetStep(f,f->timestep); /* choose a step */
00581   dataset=H5Dopen(f->timegroup,name);
00582   space = H5Dget_space(dataset);
00583   /*  datatype=H5Dget_type(dataset); */
00584   H5Dread(dataset, /* handle for the dataset */
00585           H5T_NATIVE_DOUBLE, /* the datatype we use in memory 
00586                               you can change it to FLOAT if you want */
00587           H5S_ALL, /* shape/size of data in memory (currently get all) */
00588           H5S_ALL, /* shape/size of data on disk  (currently get all) */
00589           H5P_DEFAULT,/* ignore... its for parallel reads */
00590           array); /* the data array we are reading into */
00591   H5Sclose(space); /* release data shape handle */
00592   H5Dclose(dataset); /* release the dataset handle */
00593   return 1;
00594 }
00595 
00596 int H5PartReadDataInt64(H5PartFile *f,char *name,long long *array){
00597   hid_t space,dataset,datatype;
00598   if(!f->timegroup) H5PartSetStep(f,f->timestep); /* choose a step */
00599   dataset=H5Dopen(f->timegroup,name);
00600   space = H5Dget_space(dataset);
00601   /*  datatype=H5Dget_type(dataset); */
00602   H5Dread(dataset, /* handle for the dataset */
00603           H5T_NATIVE_INT64, /* the datatype we use in memory 
00604                               you can change it to FLOAT if you want */
00605           H5S_ALL, /* shape/size of data in memory (currently get all) */
00606           H5S_ALL, /* shape/size of data on disk  (currently get all) */
00607           H5P_DEFAULT,/* ignore... its for parallel reads */
00608           array); /* the data array we are reading into */
00609   H5Sclose(space); /* release data shape handle */
00610   H5Dclose(dataset); /* release the dataset handle */
00611   return 1; /* totally bogus */
00612 }
00613 
00614 /*
00615   H5PartReadParticleStep:  This is the mongo read function that
00616     pulls in all of the data for a given timestep in one shot.
00617     It also takes the timestep as an argument and will call
00618     H5PartSetStep() internally so that you don't have to 
00619     make that call separately.
00620     See also: H5PartReadArray() if you want to just
00621     read in one of the many arrays.
00622 */
00623 int H5PartReadParticleStep(H5PartFile *f,
00624                            int step,
00625                            double *x,double *y,double *z,
00626                            long long *id){
00627   H5PartSetStep(f,step);
00628   /* or smuggle it into the array names */
00629   H5PartReadDataFloat64(f,"x",x);
00630   H5PartReadDataFloat64(f,"y",y);
00631   H5PartReadDataFloat64(f,"z",z);
00632   H5PartReadDataInt64(f,"id",id);
00633   
00634   return 1;
00635 }
00636 
00637 
00638 #ifdef REGRESSIONTEST
00639 
00640 /*
00641   A simple regression test that shows how you use this API
00642   to write and read multi-timestep files of particle data.
00643 */
00644 #ifdef PARALLEL_IO
00645 
00646 int main(int argc,char *argv[]){
00647   int sz=5;
00648   double *x,*y,*z;
00649   long long *id;
00650   char name[64];
00651   H5PartFile *file;
00652   int i,t,nt,nds;
00653   int nprocs,myproc;
00654   hid_t gid;
00655   MPI_Comm comm=MPI_COMM_WORLD;
00656   
00657   MPI_Init(&argc,&argv);
00658   MPI_Comm_size(comm,&nprocs);
00659   MPI_Comm_rank(comm,&myproc);
00660 
00661   x=(double*)malloc(sz*nprocs*sizeof(double));
00662   y=(double*)malloc(sz*nprocs*sizeof(double));
00663   z=(double*)malloc(sz*nprocs*sizeof(double));
00664   id=(long long*)malloc(sz*nprocs*sizeof(long long));
00665   /* parallel file creation */
00666   file=H5PartOpenFileParallel("parttest.h5",H5PART_WRITE,comm);
00667   if(!file) {
00668     perror("File open failed:  exiting!");
00669     exit(0);
00670   }
00671   
00672   for(t=0;t<5;t++){
00673     MPI_Barrier(comm);
00674     for(i=0;i<sz;i++) {
00675       x[i]=(double)(i+t)+10.0*(double)myproc;
00676       y[i]=0.1 + (double)(i+t);
00677       z[i]=0.2 + (double)(i+t*10);
00678       id[i]=i+sz*myproc;
00679     }
00680     printf("Proc[%u] Writing timestep %u file=%u\n",myproc,t,file->file);
00681     H5PartSetStep(file,t); /* must set the current timestep in file */
00682     H5PartSetNumParticles(file,sz); /* then set number of particles to store */
00683     /* now write different tuples of data into this timestep of the file */
00684     H5PartWriteDataFloat64(file,"x",x); 
00685     H5PartWriteDataFloat64(file,"y",y);
00686     H5PartWriteDataFloat64(file,"z",z);
00687     H5PartWriteDataInt64(file,"id",id);
00688   }
00689   printf("AllDone p[%u]\n",myproc);
00690   H5PartCloseFile(file);
00691     MPI_Barrier(comm);
00692   printf("p[%u:%u] : OK, close file and reopen for reading \n",myproc,nprocs);
00693   if(myproc==0){ /* now only proc 0 reads the file serially */
00694     file= H5PartOpenFileSerial("parttest.h5",H5PART_READ);
00695     nt=H5PartGetNumSteps(file); /* get number of steps in file */
00696     H5PartSetStep(file,0);
00697     nds=H5PartGetNumDatasets(file); /* get number of datasets in timestep 0 */
00698     
00699     puts("\n\n===============================");
00700     for(i=0;i<nds;i++){ /* and print out those names */
00701       H5PartGetDatasetName(file,i,name,64);
00702       printf("\tDataset[%u] name=[%s]\n",
00703              i,name);
00704     }
00705     puts("===============================\n\n");
00706     printf("Number of datasteps in file is %u\n",nt);
00707     for(t=0;t<nt;t++){
00708       int nparticles;
00709       H5PartSetStep(file,t); /* select a timestep */
00710       nparticles=(int)H5PartGetNumParticles(file);
00711       printf("Step[%u] nparticles this step=%u\n",
00712              t,nparticles); /* get num particles this step */
00713       H5PartReadParticleStep(file,t,/* do a mongo read of all data this step */
00714                              x,y,z,id);
00715       printf("\tid\t\tx\t\ty\t\tz\n");
00716       puts("\t----------------------------------------------------");
00717       for(i=0;i<nparticles;i++) {
00718         printf("\t%llu\t%f\t%f\t%f\n\n",id[i],x[i],y[i],z[i]);
00719       }
00720     }
00721     H5PartCloseFile(file);
00722   }
00723   if(x) free(x); 
00724   if(y) free(y);
00725   if(z) free(z);
00726   if(id) free(id);
00727   MPI_Barrier(comm);
00728   fprintf(stderr,"proc[%u]:  done\n",myproc);
00729   return MPI_Finalize();
00730 }
00731 
00732 #else
00733   
00734   int main(int argc,char *argv){
00735     const int sz=5;
00736     double x[sz],y[sz],z[sz];
00737   long long id[sz];
00738   char name[64];
00739   H5PartFile *file;
00740   int i,t,nt,nds,myproc;
00741   int nfattribs,nsattribs;
00742   
00743 
00744   if (argc==1) {
00745 
00746     file=H5PartOpenFile("parttest.h5",H5PART_WRITE);
00747     if(!file) {
00748       perror("File open failed:  exiting!");
00749       exit(0);
00750     }
00751     for(t=0;t<5;t++){
00752       long long step=t;
00753       printf("Writing timestep %u\n",t);
00754       for(i=0;i<sz;i++) {
00755         x[i]=(double)(i+t);
00756         y[i]=0.1 + (double)(i+t);
00757         z[i]=0.2 + (double)(i+t);
00758         id[i]=i;
00759       }
00760       H5PartSetStep(file,t); /* must set the current timestep in file */
00761       H5PartSetNumParticles(file,sz); /* then set number of particles to store */
00762       /* now write different tuples of data into this timestep of the file */
00763       H5PartWriteDataFloat64(file,"x",x); 
00764       H5PartWriteDataFloat64(file,"y",y);
00765       H5PartWriteDataFloat64(file,"z",z);
00766       H5PartWriteDataInt64(file,"id",id);
00767       H5PartWriteStepAttrib(file,"Step",H5T_NATIVE_INT64,&step,1);
00768     }
00769     H5PartCloseFile(file);
00770     printf("OK, close file and reopen for reading\n");
00771     file= H5PartOpenFile("parttest.h5",H5PART_READ);
00772     nt=H5PartGetNumSteps(file); /* get number of steps in file */
00773     H5PartSetStep(file,0);
00774     nds=H5PartGetNumDatasets(file); /* get number of datasets in timestep 0 */
00775     
00776     puts("\n\n===============================");
00777     for(i=0;i<nds;i++){ /* and print out those names */
00778       H5PartGetDatasetName(file,i,name,64);
00779       printf("\tDataset[%u] name=[%s]\n",
00780              i,name);
00781     }
00782     puts("===============================\n\n");
00783     
00784     nfattribs=H5PartGetNumFileAttribs(file);
00785     printf("Number of datasteps in file is %u num file attribs=%d\n",
00786            nt,nfattribs);
00787     for(t=0;t<nt;t++){
00788       int nparticles;
00789       H5PartSetStep(file,t); /* select a timestep */
00790       nparticles=(int)H5PartGetNumParticles(file);
00791       nsattribs=H5PartGetNumStepAttribs(file);
00792       printf("Step[%u] nparticles this step=%u stepattribs=%u\n",
00793              t,nparticles,nsattribs); /* get num particles this step */
00794       if(nsattribs>0){
00795         char attrname[32];
00796         H5PartGetStepAttribInfo(file,0,attrname,32,0,0);
00797         printf("First Attrib name is [%s]\n",attrname);
00798       }
00799       H5PartReadParticleStep(file,t,/* do a mongo read of all data this step */
00800                              x,y,z,id);
00801       printf("\tid\t\tx\t\ty\t\tz\n");
00802       puts("\t----------------------------------------------------");
00803       for(i=0;i<sz;i++) {
00804         printf("\t%llu\t%f\t%f\t%f\n\n",id[i],x[i],y[i],z[i]);
00805       }
00806     }
00807     H5PartCloseFile(file);
00808   }
00809   }
00810 #endif
00811 
00812 #endif
00813 

Generated on Mon Jan 16 13:23:48 2006 for IPPL by  doxygen 1.4.6