Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

CH_HDF5.H

Go to the documentation of this file.
00001 /*   _______              __
00002     / ___/ /  ___  __ _  / /  ___
00003    / /__/ _ \/ _ \/  ' \/ _ \/ _ \
00004    \___/_//_/\___/_/_/_/_.__/\___/ 
00005 */
00006 //
00007 // This software is copyright (C) by the Lawrence Berkeley
00008 // National Laboratory.  Permission is granted to reproduce
00009 // this software for non-commercial purposes provided that
00010 // this notice is left intact.
00011 // 
00012 // It is acknowledged that the U.S. Government has rights to
00013 // this software under Contract DE-AC03-765F00098 between
00014 // the U.S.  Department of Energy and the University of
00015 // California.
00016 //
00017 // This software is provided as a professional and academic
00018 // contribution for joint exchange. Thus it is experimental,
00019 // is provided ``as is'', with no warranties of any kind
00020 // whatsoever, no support, no promise of updates, or printed
00021 // documentation. By using this software, you acknowledge
00022 // that the Lawrence Berkeley National Laboratory and
00023 // Regents of the University of California shall have no
00024 // liability with respect to the infringement of other
00025 // copyrights by any part of this software.
00026 //
00027 //  ANAG, LBNL
00028 
00029 
00030 #ifndef CH_HDF5_H
00031 #define CH_HDF5_H
00032 
00033 #ifdef HDF5  // if you don't have HDF5, then this file is useless
00034 
00035 #include <iostream> 
00036 using std::cout;
00037 using std::endl;
00038 
00039 #ifdef MPI
00040 #include <mpi.h>
00041 #endif
00042 
00043 #include "LevelData.H"
00044 #include "HDF5Portable.H"
00045 // hdf5 #defines inline.... duh!
00046 #undef inline
00047 #include <string>
00048 #include <map>
00049 #include "RealVect.H"
00050 
00051 
00052 
00053 using std::map;
00054 
00055 class HDF5Handle;
00056 
00057 // CH_HDF5.H
00058 // ============
00059 
00060 
00062 
00073 template <class T>
00074 int writeLevel(HDF5Handle& a_handle, 
00075                const int& a_level, 
00076                const LevelData<T>& a_data,
00077                const Real& a_dx, 
00078                const Real& a_dt, 
00079                const Real& a_time, 
00080                const Box& a_domain,
00081                const int& a_refRatio,
00082                const IntVect& outputGhost = IntVect::Zero,
00083                const Interval& comps = Interval());
00084 
00085 template <class T>
00086 int readLevel(HDF5Handle& a_handle,  
00087               const int& a_level, 
00088               LevelData<T>& a_data, 
00089               Real& a_dx, 
00090               Real& a_dt, 
00091               Real& a_time, 
00092               Box& a_domain,
00093               int& a_refRatio, 
00094               const Interval& a_comps = Interval(), 
00095               const IntVect& ghost = IntVect::Zero, 
00096               bool setGhost = false);
00097 
00098 
00099 // More basic HDF5 functions.  These can be used at a persons own
00100 // discretion.  Refer to the User's Guide for a description of how these
00101 // functions interact with the convenience functions writeLevel, etc.
00102 
00104 
00111 int write(HDF5Handle& a_handle, 
00112           const BoxLayout& a_layout);
00113 
00115 
00120 template <class T>
00121 int write(HDF5Handle& a_handle, 
00122           const BoxLayoutData<T>& a_data, 
00123           const std::string& a_name,
00124           const IntVect& outputGhost = IntVect::Zero,
00125           const Interval& comps = Interval());
00126 
00128 
00135 template <class T>
00136 int write(HDF5Handle& a_handle, 
00137           const LevelData<T>& a_data, 
00138           const std::string& a_name,
00139           const IntVect& outputGhost = IntVect::Zero,
00140           const Interval& comps = Interval());
00141 
00143 
00150 int read(HDF5Handle& a_handle, 
00151          Vector<Box>& boxes);
00152 
00154 
00161 int readBoxes(HDF5Handle& a_handle,
00162               Vector<Vector<Box> >& boxes);
00163  
00164 
00166 
00174 int readFArrayBox(HDF5Handle& a_handle,
00175                   FArrayBox&  a_fab,
00176                   int a_level,
00177                   int a_boxNumber,
00178                   const Interval& a_components,
00179                   const std::string& a_dataName = "data" );
00180 
00182 
00188 template <class T>
00189 int read(HDF5Handle& a_handle, 
00190          BoxLayoutData<T>& a_data, 
00191          const std::string& a_name, 
00192          const BoxLayout& a_layout,
00193          const Interval&  a_comps = Interval(),
00194          bool redefineData = true);
00195 
00197 
00203 template <class T>
00204 int read(HDF5Handle& a_handle, 
00205          LevelData<T>& a_data, 
00206          const std::string& a_name, 
00207          const DisjointBoxLayout& a_layout,
00208          const Interval& a_comps = Interval(),
00209          bool redefineData = true);
00210 
00212 
00222 class HDF5Handle
00223 {
00224 public:
00226 
00240   enum mode {CREATE, OPEN_RDONLY, OPEN_RDWR};
00241 
00243 
00245 
00250   HDF5Handle();
00251 
00253 
00261   HDF5Handle(const std::string& a_filename, mode a_mode);
00262 
00264 
00266 
00286   int open(const std::string& a_filename, mode a_mode);
00287 
00289 
00292   bool isOpen() const;
00293 
00295 
00300   void close();
00301 
00303 
00305 
00308   void setGroupToLevel(int a_level);
00309 
00311 
00318   int setGroup(const std::string& groupAbsPath);
00319 
00321 
00327   const std::string& getGroup() const;
00328 
00329   const hid_t& fileID() const;
00330   const hid_t& groupID() const;
00331   static hid_t box_id;
00332   static hid_t intvect_id;
00333   static hid_t realvect_id;
00334 
00335 private:
00336 
00337   HDF5Handle(const HDF5Handle&);
00338   HDF5Handle& operator=(const HDF5Handle&);
00339 
00340   hid_t         m_fileID;
00341   hid_t         m_currentGroupID;
00342   bool          m_isOpen;
00343   std::string   m_filename; // keep around for debugging
00344   std::string   m_group;
00345   int           m_level;
00346 
00347   //  static hid_t  file_access;
00348   static bool   initialized;
00349   static void   initialize();
00350 
00351 };
00352 
00354 
00396 class HDF5HeaderData
00397 {
00398 public:
00399 
00401 
00407   int writeToFile(HDF5Handle& file) const;
00408 
00410 
00418   int readFromFile(HDF5Handle& file);
00419 
00421   void clear();
00422 
00424   map<std::string, Real>        m_real;
00425 
00427   map<std::string, int>         m_int;
00428 
00430   map<std::string, std::string> m_string;
00431 
00433   map<std::string, IntVect>     m_intvect;
00434 
00436   map<std::string, Box>         m_box;
00437 
00439   map<std::string, RealVect>    m_realvect;
00440 
00441   //users should not need these functions in general
00442 
00443   int writeToLocation(hid_t loc_id) const;
00444   int readFromLocation(hid_t loc_id);
00445 
00446 private:
00447   static herr_t attributeScan(hid_t loc_id, const char *name, void *opdata);
00448 };
00449 
00450 extern "C"{
00451   herr_t HDF5HeaderDataattributeScan(hid_t loc_id, const char *name, void *opdata);
00452 }
00453 
00454 std::ostream& operator<<(std::ostream& os, const HDF5HeaderData& data);
00455 
00456 
00457 //=============================================================================
00458 //
00459 // end of declarations.
00460 //
00461 //=============================================================================
00462 
00463 //#include "HDF5Implem.H"
00464 /* _______              __
00465    / ___/ /  ___  __ _  / /  ___
00466    / /__/ _ \/ _ \/  ' \/ _ \/ _ \
00467    \___/_//_/\___/_/_/_/_.__/\___/ 
00468 */
00469 //
00470 // This software is copyright (C) by the Lawrence Berkeley
00471 // National Laboratory.  Permission is granted to reproduce
00472 // this software for non-commercial purposes provided that
00473 // this notice is left intact.
00474 // 
00475 // It is acknowledged that the U.S. Government has rights to
00476 // this software under Contract DE-AC03-765F00098 between
00477 // the U.S.  Department of Energy and the University of
00478 // California.
00479 //
00480 // This software is provided as a professional and academic
00481 // contribution for joint exchange. Thus it is experimental,
00482 // is provided ``as is'', with no warranties of any kind
00483 // whatsoever, no support, no promise of updates, or printed
00484 // documentation. By using this software, you acknowledge
00485 // that the Lawrence Berkeley National Laboratory and
00486 // Regents of the University of California shall have no
00487 // liability with respect to the infringement of other
00488 // copyrights by any part of this software.
00489 //
00490 //  ANAG, LBNL
00491 
00492 #include "LoadBalance.H"
00493 #include "LayoutIterator.H"
00494 #include "Vector.H"
00495 #include "memtrack.H"
00496 
00497 
00498 // non-user code used in implementation of communication
00499 
00500 struct OffsetBuffer
00501 {
00502   Vector<int> index;
00503   Vector<Vector<int> > offsets;
00504   void operator=(const OffsetBuffer& rhs);
00505 };
00506 
00507 ostream& operator<<(ostream& os, const OffsetBuffer& ob);
00508 
00509 //OffsetBuffer specialization of linearSize
00510 template < >
00511 int linearSize(const OffsetBuffer& a_input); 
00512 
00513 //OffsetBuffer specialization of linearIn
00514 template < >
00515 void linearIn(OffsetBuffer& a_outputT, const void* const a_inBuf); 
00516 
00517 //OffsetBuffer specialization of linearOut
00518 template < >
00519 void linearOut(void* const a_outBuf, const OffsetBuffer& a_inputT); 
00520 
00521 template < > int linearSize(const Vector<OffsetBuffer>& a_input);
00522 template < > void linearIn(Vector<OffsetBuffer>& a_outputT, const void* const inBuf);
00523 template < > void linearOut(void* const a_outBuf, const Vector<OffsetBuffer>& a_inputT);
00524 
00525 // First, template specializations for read/write for FArrayBox.
00526 
00527 template <>
00528 inline void dataTypes(Vector<hid_t>& a_types, const BaseFab<int>& dummy)
00529 {  
00530   a_types.resize(1); 
00531   a_types[0] = H5T_NATIVE_INT;
00532 }
00533 
00534 /* since many compilers choke on the proper template specialization syntax
00535    I am forced to pass in a dummy specialization argument
00536 */
00537 template <>
00538 inline void dataTypes(Vector<hid_t>& a_types, const FArrayBox& dummy)
00539 {  a_types.resize(1); a_types[0] = H5T_NATIVE_REAL;}
00540 
00541 
00542 
00543 template <>
00544 inline void dataSize(const BaseFab<int>& item, Vector<int>& a_sizes, 
00545                      const Box& box, const Interval& comps)
00546 {
00547   a_sizes[0] = box.numPts() * comps.size();
00548 }
00549 
00550 template <>
00551 inline void dataSize(const FArrayBox& item, Vector<int>& a_sizes, 
00552                      const Box& box, const Interval& comps)
00553 {
00554   a_sizes[0] = box.numPts() * comps.size();
00555 }
00556 
00557 
00558 
00559 template <>
00560 inline const char* name(const FArrayBox& a_dummySpecializationArg)
00561 {
00562   // Attempt to get rid of warnings on IBM...
00563   //static const char* name = "FArrayBox";
00564   const char* name = "FArrayBox";
00565   return name;
00566 }
00567 
00568 
00569 
00570 template <>
00571 inline const char* name(const BaseFab<int>& a_dummySpecializationArg)
00572 {
00573   // Attempt to get rid of warnings on IBM...
00574   //static const char* name = "BaseFab<int>";
00575   const char* name = "BaseFab<int>";
00576   return name;
00577 }
00578 
00579 //
00580 // now, generic, non-binary portable version of template functions
00581 // for people who just want ot rely on linearIn/linearOut
00582 
00583 template <class T>
00584 inline void dataTypes(Vector<hid_t>& a_types, const T& dummy)
00585 {  a_types.resize(1); a_types[0] = H5T_NATIVE_CHAR;}
00586 
00587 template <class T>
00588 inline void dataSize(const T& item, Vector<int>& a_sizes, 
00589                      const Box& box, const Interval& comps)
00590 {
00591   a_sizes[0] = item.size(box, comps);
00592 }
00593 
00594 
00595 template <class T>
00596 inline void write(const T& item, Vector<void*>& a_allocatedBuffers, 
00597                   const Box& box, const Interval& comps)
00598 {
00599   item.linearOut(a_allocatedBuffers[0], box, comps);
00600 }
00601 
00602 template <class T>
00603 inline void read(T& item, Vector<void*>& a_allocatedBuffers, 
00604                  const Box& box, const Interval& comps)
00605 {
00606   item.linearIn(a_allocatedBuffers[0], box, comps);
00607 }
00608 
00609 template <class T>
00610 inline const char* name(const T& a_dummySpecializationArg)
00611 {
00612   static const char* name = "unknown";
00613   return name;
00614 }
00615 
00616 template <class T>
00617 void getOffsets(Vector<Vector<long long> >& offsets, const BoxLayoutData<T>& a_data,  
00618                 int types, const Interval& comps, const IntVect& outputGhost)
00619 {
00620 
00621 
00622   const BoxLayout& layout = a_data.boxLayout();
00623   offsets.resize(types, Vector<long long>(layout.size()+1));
00624   //  offsets.resize(layout.size() + 1, Vector<long long>(types));
00625   for(int t=0; t<types; t++) offsets[t][0] = 0;
00626   Vector<int> thisSize(types);
00627   if(T::preAllocatable()==0)
00628     { // static preAllocatable
00629       T dummy;
00630       unsigned int index = 1;
00631       for(LayoutIterator it(layout.layoutIterator()); it.ok(); ++it)
00632         {
00633           Box region = layout[it()];
00634           region.grow(outputGhost);
00635           dataSize(dummy, thisSize, region, comps);
00636           for(unsigned int i=0; i<thisSize.size(); ++i) 
00637             {
00638               //offsets[index][i] = offsets[index-1][i] + thisSize[i];
00639               offsets[i][index] = offsets[i][index-1] + thisSize[i];
00640             }
00641           ++index;
00642         }
00643     }
00644   else
00645     { // symmetric and dynamic preallocatable need two pass I/O
00646       OffsetBuffer buff;
00647       //int index = 0;
00648       for(DataIterator dit(a_data.dataIterator()); dit.ok(); ++dit)
00649         {
00650                   int index = a_data.boxLayout().index(dit());
00651           //int index = dit().intCode();
00652           buff.index.push_back(index);
00653           Box region = layout[dit()];
00654           region.grow(outputGhost);
00655           dataSize(a_data[dit()], thisSize, region, comps);
00656           buff.offsets.push_back(thisSize);
00657         }
00658       Vector<OffsetBuffer> gathering(numProc());
00659       gather(gathering, buff, uniqueProc(SerialTask::compute));
00660       broadcast(gathering,  uniqueProc(SerialTask::compute));
00661       //  pout() << gathering<<endl;
00662       for(int i=0; i<numProc(); ++i)
00663         {
00664           OffsetBuffer& offbuf = gathering[i];
00665           for(int num=0; num<offbuf.index.size(); num++)
00666             {
00667               int index = offbuf.index[num];
00668               for(unsigned int j=0; j<types; ++j) 
00669                 {
00670                   //offsets[index+1][j] = offbuf.offsets[num][j];
00671                   offsets[j][index+1] = offbuf.offsets[num][j];
00672                 }
00673             }
00674         }
00675       for(int i=0; i<layout.size(); i++)
00676         {
00677           for(unsigned int j=0; j<types; ++j) 
00678             {
00679               //offsets[i+1][j] += offsets[i][j];
00680               offsets[j][i+1] += offsets[j][i];
00681             }
00682         }
00683     }
00684 
00685   // pout() << offsets<<endl;
00686 }
00687 
00688 
00689 //==================================================================
00690 //
00691 // Now, linear IO routines for a BoxLayoutData of T
00692 //
00693 
00694 template <class T>
00695 int write(HDF5Handle& a_handle, const BoxLayoutData<T>& a_data, 
00696           const std::string& a_name, const IntVect& outputGhost, const Interval& in_comps)
00697 {
00698   int ret = 0;
00699 
00700   Interval comps(in_comps);
00701   if( comps.size() == 0) comps = a_data.interval();
00702   T dummy; // used for preallocatable methods for dumb compilers.
00703   Vector<hid_t> types;
00704   dataTypes(types, dummy);
00705 
00706   Vector<Vector<long long> > offsets;
00707   Vector<long long> bufferCapacity(types.size(), 1);  // noel (was 0)
00708   Vector<void*> buffers(types.size(), NULL);
00709 
00710   getOffsets(offsets, a_data, types.size(), comps, outputGhost);
00711 
00712   // create datasets collectively.
00713   hsize_t flatdims[1];
00714   char dataname[100];
00715   Vector<hid_t> dataspace(types.size());
00716   Vector<hid_t> dataset(types.size());
00717 
00718 
00719 
00720   herr_t err;
00721   hsize_t count[1];
00722   hssize_t offset[1];
00723 
00724   for(unsigned int i=0; i<types.size(); ++i) 
00725     {
00726       flatdims[0] = offsets[i][offsets[i].size()-1];
00727       sprintf(dataname, "%s:datatype=%i",a_name.c_str(), i);
00728       dataspace[i]      = H5Screate_simple(1, flatdims, NULL);
00729       assert(dataspace[i] >=0);
00730       dataset[i]        = H5Dcreate(a_handle.groupID(), dataname,  
00731                                     types[i],
00732                                     dataspace[i], H5P_DEFAULT);
00733       assert(dataset[i] >= 0);
00734     }
00735 
00736   hid_t offsetspace, offsetData;
00737   for(unsigned int i=0; i<types.size(); ++i) 
00738     {
00739       flatdims[0] =  offsets[i].size();
00740       sprintf(dataname, "%s:offsets=%i",a_name.c_str(), i);
00741       offsetspace =  H5Screate_simple(1, flatdims, NULL);
00742       assert(offsetspace >= 0);
00743       offsetData  =   H5Dcreate(a_handle.groupID(), dataname,  
00744                                 H5T_NATIVE_LLONG, offsetspace, H5P_DEFAULT);
00745       assert(offsetData >= 0);
00746       if(procID() == 0)
00747         {
00748           hid_t memdataspace = H5Screate_simple(1, flatdims, NULL);
00749           assert(memdataspace >= 0);
00750           err = H5Dwrite(offsetData, H5T_NATIVE_LLONG, memdataspace, offsetspace,
00751                          H5P_DEFAULT, &(offsets[i][0]));
00752           assert(err >= 0);
00753           H5Sclose(memdataspace);
00754         }
00755       H5Sclose(offsetspace);
00756       H5Dclose(offsetData);
00757     }
00758 
00759   // write BoxLayoutData attributes into Dataset[0]
00760   HDF5HeaderData info;
00761   info.m_int["comps"] = comps.size();
00762   info.m_string["objectType"] = name(dummy);
00763   std::string group = a_handle.getGroup();
00764   a_handle.setGroup(group+"/"+a_name+"_attributes");
00765   info.writeToFile(a_handle);
00766   a_handle.setGroup(group);
00767 
00768   // collective operations finished, now perform parallel writes
00769   // to specified hyperslabs.
00770 
00771   Vector<size_t> type_size(types.size());
00772   for(unsigned int i=0; i<types.size(); ++i) 
00773     {
00774       type_size[i] = H5Tget_size(types[i]);
00775     }
00776 
00777   Vector<int> thisSize(types.size());
00778 
00779   // step 1, create buffer big enough to hold the biggest linearized T
00780   // that I will have to output.
00781 
00782   //  pout()<<"offsets ";
00783    for(int i=0; i<offsets[0].size(); i++)
00784         {
00785           //      pout()<<" "<<offsets[0][i];
00786         }
00787   // pout()<<"\n";
00788   for(DataIterator it = a_data.dataIterator(); it.ok(); ++it)
00789     {
00790       unsigned int index = a_data.boxLayout().index(it());
00791       for(unsigned int i=0; i<types.size(); ++i) 
00792         {
00793           long long size = (offsets[i][index+1] - offsets[i][index]) 
00794             * type_size[i];
00795                   // pout()<<"index:size "<<index<<" "<<size<<"\n";
00796           assert(size >= 0);
00797           if(size > bufferCapacity[i]) // grow buffer if necessary.....
00798             {
00799               bufferCapacity[i] = size;
00800             } 
00801         }
00802     }
00803   //assert(bufferCapacity[0] > 1);
00804   for(unsigned int i=0; i<types.size(); ++i) 
00805     {
00806       buffers[i] = malloc(bufferCapacity[i]);
00807       if(buffers[i] == NULL) {
00808         pout() << " i=" << i
00809                << " types.size() = " << types.size()
00810                << " bufferCapacity[i] = " << (int)bufferCapacity[i]
00811                << endl;
00812         MayDay::Error("memory error in buffer allocation write");
00813       }
00814     }
00815 
00816   // Step 2.  actually a) write each of my T objects into the
00817   // buffer, then b) write that buffered data out to the
00818   // write position in the data file using hdf5 hyperslab functions.
00819   for(DataIterator it = a_data.dataIterator(); it.ok(); ++it)
00820     {
00821       const T& data = a_data[it()];
00822       unsigned int index = a_data.boxLayout().index(it());
00823       Box box = a_data.box(it());
00824       box.grow(outputGhost);
00825       write(data, buffers, box, comps); //write T to buffer
00826       for(unsigned int i=0; i<types.size(); ++i) 
00827         {
00828           offset[0] = offsets[i][index];
00829           count[0] = offsets[i][index+1] - offset[0];
00830           if(count[0] > 0){
00831                         err =  H5Sselect_hyperslab(dataspace[i], H5S_SELECT_SET, 
00832                                                                            offset, NULL, 
00833                                                                            count, NULL);
00834                         assert(err >= 0);
00835                         hid_t memdataspace = H5Screate_simple(1, count, NULL);
00836                         assert(memdataspace >= 0);
00837                         err = H5Dwrite(dataset[i], types[i], memdataspace, dataspace[i],
00838                                                    H5P_DEFAULT, buffers[i]);
00839                         assert(err >= 0);
00840                         H5Sclose(memdataspace);
00841                         if(err < 0) { ret = err; goto cleanup;}
00842                   }
00843         }
00844     }
00845 
00846   // OK, clean up data structures
00847 
00848  cleanup:
00849   for(unsigned int i=0; i<types.size(); ++i) 
00850     {
00851       free(buffers[i]);
00852       H5Sclose(dataspace[i]);
00853       H5Dclose(dataset[i]);
00854     }
00855   return ret;
00856 
00857 }
00858 
00859 template <class T>
00860 int write(HDF5Handle& a_handle, const LevelData<T>& a_data, 
00861           const std::string& a_name, const IntVect& outputGhost, const Interval& in_comps)
00862 {
00863   HDF5HeaderData info;
00864   info.m_intvect["ghost"] = a_data.ghostVect();
00865   IntVect og(outputGhost);
00866   og.min(a_data.ghostVect());
00867   info.m_intvect["outputGhost"] = og;
00868   std::string group = a_handle.getGroup();
00869   a_handle.setGroup(group+"/"+a_name+"_attributes");
00870   info.writeToFile(a_handle);
00871   a_handle.setGroup(group);
00872   return write(a_handle, (const BoxLayoutData<T>&)a_data, a_name, og, in_comps);
00873 }
00874 
00875 template <class T>
00876 int read(HDF5Handle& a_handle, LevelData<T>& a_data, const std::string& a_name, 
00877          const DisjointBoxLayout& a_layout, const Interval& a_comps, bool a_redefineData)
00878 {
00879   if(a_redefineData)
00880     {
00881       HDF5HeaderData info;
00882       std::string group = a_handle.getGroup();
00883       if(a_handle.setGroup(group+"/"+a_name+"_attributes"))
00884         {
00885           std::string message = "error opening "+a_handle.getGroup()+"/"+a_name ;
00886           MayDay::Warning(message.c_str());
00887           return 1;
00888         }
00889       info.readFromFile(a_handle);
00890       a_handle.setGroup(group);
00891       int ncomp =  info.m_int["comps"];
00892       IntVect ghost = info.m_intvect["ghost"];
00893       if(a_comps.end() > 0 && ncomp < a_comps.end())
00894         {
00895           MayDay::Error("attempt to read component interval that is not available");
00896         }
00897       if(a_comps.size() == 0)
00898         a_data.define(a_layout, ncomp, ghost);
00899       else
00900         a_data.define(a_layout, a_comps.size(), ghost);
00901     }
00902   return read(a_handle, (BoxLayoutData<T>&)a_data, a_name, a_layout, a_comps, false);
00903 
00904 }
00905 template <class T>
00906 int read(HDF5Handle& a_handle, BoxLayoutData<T>& a_data, const std::string& a_name, 
00907          const BoxLayout& a_layout, const Interval& a_comps, bool a_redefineData)
00908 {
00909   int ret = 0; // return value;
00910 
00911   herr_t err;
00912 
00913   char dataname[100];
00914   hsize_t count[1];
00915   hssize_t offset[1];
00916   Vector<Vector<long long> > offsets;
00917 
00918   T dummy;
00919   Vector<hid_t> types;
00920   dataTypes(types, dummy);
00921   Vector<hid_t> dataspace(types.size());
00922   Vector<hid_t> dataset(types.size());
00923   offsets.resize(types.size(), Vector<long long>(a_layout.size() +1));
00924 
00925   Vector<int> bufferCapacity(types.size(), 500);
00926   Vector<void*> buffers(types.size(), NULL);
00927 
00928   for(unsigned int i=0; i<types.size(); ++i) 
00929     {
00930       sprintf(dataname, "%s:datatype=%i",a_name.c_str(), i);
00931       dataset[i]        = H5Dopen(a_handle.groupID(), dataname);
00932       if(dataset[i] < 0) {MayDay::Warning("dataset open failure"); return dataset[i];}
00933       dataspace[i]      = H5Dget_space(dataset[i]);
00934       if(dataspace[i] < 0) {MayDay::Warning("dataspace open failure"); return dataspace[i];}
00935     }
00936 
00937   hid_t offsetspace, offsetData;
00938   hsize_t flatdims[1];
00939   for(unsigned int i=0; i<types.size(); ++i) 
00940     {
00941       flatdims[0] =  offsets[i].size();
00942       sprintf(dataname, "%s:offsets=%i",a_name.c_str(), i);
00943       offsetspace =  H5Screate_simple(1, flatdims, NULL);
00944       assert(offsetspace >= 0);
00945       offsetData  =   H5Dopen(a_handle.groupID(), dataname);  
00946       assert(offsetData >= 0);
00947       hid_t memdataspace = H5Screate_simple(1, flatdims, NULL);
00948       assert(memdataspace >= 0);
00949       err = H5Dread(offsetData, H5T_NATIVE_LLONG, memdataspace, offsetspace,
00950                     H5P_DEFAULT, &(offsets[i][0]));
00951       assert(err >=0);
00952       H5Sclose(memdataspace);
00953       H5Sclose(offsetspace);
00954       H5Dclose(offsetData);
00955     }
00956 
00957   HDF5HeaderData info;
00958   std::string group = a_handle.getGroup();
00959   if(a_handle.setGroup(a_handle.getGroup()+"/"+a_name+"_attributes"))
00960     {
00961       std::string message = "error opening "+a_handle.getGroup()+"/"+a_name ;
00962       MayDay::Warning(message.c_str());
00963       return 1;
00964     }
00965 
00966   info.readFromFile(a_handle);
00967   a_handle.setGroup(group);
00968   int ncomps = info.m_int["comps"];
00969   IntVect outputGhost(IntVect::Zero); // backwards file compatible mode.
00970   if(info.m_intvect.find("outputGhost") != info.m_intvect.end())
00971     {
00972       outputGhost = info.m_intvect["outputGhost"];
00973     }
00974   if(ncomps <= 0){
00975     MayDay::Warning("ncomps <= 0 in read");
00976     return ncomps;
00977   }
00978 
00979   if(a_redefineData){
00980     if(a_comps.size() != 0){
00981       a_data.define(a_layout, a_comps.size());
00982     } else {
00983       a_data.define(a_layout, ncomps);
00984     }
00985   }
00986 
00987   Interval comps(0, ncomps-1);
00988   //huh?
00989   //  if(a_comps.size() != 0)  comps = Interval(0, a_comps.size());
00990 
00991   //  getOffsets(offsets, a_data, types.size(), comps);
00992 
00993   Vector<size_t> type_size(types.size());
00994   for(unsigned int i=0; i<types.size(); ++i) 
00995     {
00996       type_size[i] = H5Tget_size(types[i]);
00997       buffers[i] = malloc(bufferCapacity[i]);
00998       if(buffers[i] == NULL) {
00999         pout() << " i= " << i 
01000                << " types.size()=" << types.size() 
01001                << " bufferCapacity[i] = " << (int)bufferCapacity[i]
01002                << endl; 
01003         MayDay::Error("memory error in buffer allocation read");
01004       }
01005     }
01006 
01007   Vector<int> thisSize(types.size());
01008   for(DataIterator it = a_data.dataIterator(); it.ok(); ++it)
01009     {
01010       T& data = a_data[it()];
01011       unsigned int index = a_data.boxLayout().index(it());
01012       Box box = a_data.box(it());
01013 
01014       for(unsigned int i=0; i<types.size(); ++i) 
01015         {
01016           if(a_comps.size() == 0){
01017             offset[0] = offsets[i][index];
01018             count[0] = offsets[i][index+1] - offset[0];
01019           } else {
01020             offset[0] = offsets[i][index] + box.numPts()*a_comps.begin();
01021             count[0]  = a_comps.size() * box.numPts();
01022           }
01023           if(count[0] > 0)
01024                         {
01025                           int size = count[0] * type_size[i];
01026                           if(size > bufferCapacity[i])
01027                                 {
01028                                   free(buffers[i]);
01029                                   bufferCapacity[i] = Max(2*bufferCapacity[i], size);
01030                                   buffers[i] = malloc(bufferCapacity[i]);
01031                                   if(buffers[i] == NULL) {
01032                                         MayDay::Error("memory error in buffer allocation read");
01033                                   }
01034                                 } 
01035                           
01036                           err =  H5Sselect_hyperslab(dataspace[i], H5S_SELECT_SET, 
01037                                      offset, NULL, 
01038                                      count, NULL);
01039                           assert(err >= 0);
01040                           hid_t memdataspace = H5Screate_simple(1, count, NULL);
01041                           assert(memdataspace >= 0);
01042                           err = H5Dread(dataset[i], types[i], memdataspace, dataspace[i],
01043                                                         H5P_DEFAULT, buffers[i]);
01044                           assert(err >= 0);
01045                           H5Sclose(memdataspace);
01046                           if(err < 0) { ret = err; goto cleanup;}
01047                         }
01048         }
01049       box.grow(outputGhost);
01050       read(data, buffers,  box, comps);
01051     }
01052 
01053  cleanup:
01054   for(unsigned int i=0; i<types.size(); ++i) 
01055     {
01056       free(buffers[i]);
01057       H5Sclose(dataspace[i]);
01058       H5Dclose(dataset[i]);
01059     }
01060   return ret;
01061 }
01062 
01063 
01064 template <class T>
01065 int writeLevel(HDF5Handle& a_handle, 
01066                const int&  a_level, 
01067                const LevelData<T>& a_data,
01068                const Real& a_dx, 
01069                const Real& a_dt, 
01070                const Real& a_time, 
01071                const Box&  a_domain,
01072                const int&  a_refRatio,
01073                const IntVect& outputGhost,
01074                const Interval& comps)
01075 {
01076   int error;
01077   char levelName[10];
01078   std::string currentGroup = a_handle.getGroup();
01079   sprintf(levelName, "/level_%i",a_level);
01080   error = a_handle.setGroup(currentGroup + levelName);
01081   if(error != 0) return 1;
01082 
01083   HDF5HeaderData meta;
01084   meta.m_real["dx"] = a_dx;
01085   meta.m_real["dt"] = a_dt;
01086   meta.m_real["time"] = a_time;
01087   meta.m_box["prob_domain"] = a_domain;
01088   meta.m_int["ref_ratio"] = a_refRatio;
01089 
01090   error = meta.writeToFile(a_handle);
01091   if(error != 0) return 2;
01092 
01093   error = write(a_handle, a_data.boxLayout());
01094   if(error != 0) return 3;
01095 
01096   error = write(a_handle, a_data, "data", outputGhost, comps);
01097   if(error != 0) return 4;
01098 
01099   a_handle.setGroup(currentGroup);
01100 
01101   return 0;
01102 }
01103 
01104 
01105 template <class T>
01106 int readLevel(HDF5Handle&   a_handle,  
01107               const int&    a_level, 
01108               LevelData<T>& a_data, 
01109               Real& a_dx, 
01110               Real& a_dt, 
01111               Real& a_time, 
01112               Box&  a_domain,
01113               int&  a_refRatio,
01114               const Interval&   a_comps,
01115               const IntVect& ghost,
01116               bool  setGhost)
01117 {
01118   HDF5HeaderData header;
01119   header.readFromFile(a_handle);
01120   int nComp = header.m_int["num_components"];
01121 
01122   int error;
01123   char levelName[10];
01124   std::string currentGroup = a_handle.getGroup();
01125   sprintf(levelName, "/level_%i",a_level);
01126   error = a_handle.setGroup(currentGroup + levelName);
01127   if(error != 0) return 1;
01128 
01129   HDF5HeaderData meta;
01130   error = meta.readFromFile(a_handle);
01131   if(error != 0) return 2;
01132   a_dx       = meta.m_real["dx"];
01133   a_dt       = meta.m_real["dt"];
01134   a_time     = meta.m_real["time"];
01135   a_domain   = meta.m_box["prob_domain"];
01136   a_refRatio = meta.m_int["ref_ratio"];
01137 
01138   Vector<Box> boxes;
01139   error = read(a_handle, boxes);
01140   Vector<int> procIDs;
01141   LoadBalance(procIDs, boxes);
01142 
01143   DisjointBoxLayout layout(boxes, procIDs);
01144 
01145   layout.close();
01146   if(error != 0) return 3;
01147 
01148   if(!setGhost)
01149     error = read(a_handle, a_data, "data", layout, a_comps);
01150   else
01151     {
01152       if(a_comps.size() !=  0)
01153         a_data.define(layout, a_comps.size(), ghost);
01154       else
01155         a_data.define(layout, nComp, ghost);
01156 
01157       error = read(a_handle, a_data, "data", layout, a_comps, false);
01158 
01159     }
01160   if(error != 0) return 4;
01161 
01162   a_handle.setGroup(currentGroup);
01163 
01164   return 0;
01165 }
01166 
01167 #else // HDF5
01168 
01169 // this is the only thing needed when HDF is not used
01170 #define HOFFSET(S,M)    (offsetof(S,M))
01171 
01172 #endif // HDF5
01173 
01174 #endif  // CH_HDF5_H

Generated on Wed Jun 2 13:53:32 2004 for Chombo&INSwithParticles by doxygen 1.3.2