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

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

Generated on Wed Apr 16 14:26:49 2003 for Chombo by doxygen1.2.16