Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

CH_HDF5.H

Go to the documentation of this file.
00001 /*   _______              __
00002     / ___/ /  ___  __ _  / /  ___
00003    / /__/ _ \/ _ \/  V \/ _ \/ _ \
00004    \___/_//_/\___/_/_/_/_.__/\___/
00005 */
00006 // CHOMBO Copyright (c) 2000-2004, The Regents of the University of
00007 // California, through Lawrence Berkeley National Laboratory (subject to
00008 // receipt of any required approvals from U.S. Dept. of Energy).  All
00009 // rights reserved.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are met:
00013 //
00014 // (1) Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 // (2) Redistributions in binary form must reproduce the above copyright
00017 // notice, this list of conditions and the following disclaimer in the
00018 // documentation and/or other materials provided with the distribution.
00019 // (3) Neither the name of Lawrence Berkeley National Laboratory, U.S.
00020 // Dept. of Energy nor the names of its contributors may be used to endorse
00021 // or promote products derived from this software without specific prior
00022 // written permission.
00023 //
00024 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00026 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00027 // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00028 // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00029 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00030 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00031 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00032 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00033 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00034 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035 //
00036 // You are under no obligation whatsoever to provide any bug fixes,
00037 // patches, or upgrades to the features, functionality or performance of
00038 // the source code ("Enhancements") to anyone; however, if you choose to
00039 // make your Enhancements available either publicly, or directly to
00040 // Lawrence Berkeley National Laboratory, without imposing a separate
00041 // written license agreement for such Enhancements, then you hereby grant
00042 // the following license: a non-exclusive, royalty-free perpetual license
00043 // to install, use, modify, prepare derivative works, incorporate into
00044 // other computer software, distribute, and sublicense such Enhancements or
00045 // derivative works thereof, in binary and source code form.
00046 //
00047 // TRADEMARKS. Product and company names mentioned herein may be the
00048 // trademarks of their respective owners.  Any rights not expressly granted
00049 // herein are reserved.
00050 //
00051 
00052 #ifndef _CH_HDF5_H_
00053 #define _CH_HDF5_H_
00054 
00055 #ifdef CH_USE_HDF5  // if you don't have CH_USE_HDF5, then this file is useless
00056 
00057 #include <iostream>
00058 using std::cout;
00059 using std::endl;
00060 
00061 #ifdef CH_MPI
00062 #include <mpi.h>
00063 #endif
00064 
00065 #include "LevelData.H"
00066 #include "HDF5Portable.H"
00067 // hdf5 #defines inline.... duh!
00068 #undef inline
00069 #include <string>
00070 #include <map>
00071 #include "RealVect.H"
00072 
00073 template <class T>
00074 void read(T& item, Vector<Vector<char> >& a_allocatedBuffers, const Box& box,
00075           const Interval& comps)
00076 {
00077   Vector<void*> b(a_allocatedBuffers.size());
00078   for(int i=0; i<b.size(); ++i) b[i]= &(a_allocatedBuffers[i][0]);
00079   read(item, b, box, comps);
00080 }
00081 
00082 using std::map;
00083 
00084 class HDF5Handle;
00085 
00086 // CH_HDF5.H
00087 // ============
00088 
00090 
00101 template <class T>
00102 int writeLevel(HDF5Handle& a_handle,
00103                const int& a_level,
00104                const LevelData<T>& a_data,
00105                const Real& a_dx,
00106                const Real& a_dt,
00107                const Real& a_time,
00108                const Box& a_domain,
00109                const int& a_refRatio,
00110                const IntVect& outputGhost = IntVect::Zero,
00111                const Interval& comps = Interval());
00112 
00113 template <class T>
00114 int readLevel(HDF5Handle& a_handle,
00115               const int& a_level,
00116               LevelData<T>& a_data,
00117               Real& a_dx,
00118               Real& a_dt,
00119               Real& a_time,
00120               Box& a_domain,
00121               int& a_refRatio,
00122               const Interval& a_comps = Interval(),
00123               bool setGhost = false);
00124 
00125 // More basic HDF5 functions.  These can be used at a persons own
00126 // discretion.  Refer to the User's Guide for a description of how these
00127 // functions interact with the convenience functions writeLevel, etc.
00128 
00130 
00137 int write(HDF5Handle& a_handle,
00138           const BoxLayout& a_layout,
00139           const std::string& name = "boxes");
00140 
00142 
00147 template <class T>
00148 int write(HDF5Handle& a_handle,
00149           const BoxLayoutData<T>& a_data,
00150           const std::string& a_name,
00151           IntVect outputGhost = IntVect::Zero,
00152           const Interval& comps = Interval(),
00153           bool  newForm = false);
00154 
00156 
00163 template <class T>
00164 int write(HDF5Handle& a_handle,
00165           const LevelData<T>& a_data,
00166           const std::string& a_name,
00167           const IntVect& outputGhost = IntVect::Zero,
00168           const Interval& comps = Interval());
00169 
00171 
00178 int read(HDF5Handle& a_handle,
00179          Vector<Box>& boxes,
00180          const std::string& name = "boxes");
00181 
00183 
00190 int readBoxes(HDF5Handle& a_handle,
00191               Vector<Vector<Box> >& boxes);
00192 
00194 
00202 int readFArrayBox(HDF5Handle& a_handle,
00203                   FArrayBox&  a_fab,
00204                   int a_level,
00205                   int a_boxNumber,
00206                   const Interval& a_components,
00207                   const std::string& a_dataName = "data" );
00208 
00210 
00216 template <class T>
00217 int read(HDF5Handle& a_handle,
00218          BoxLayoutData<T>& a_data,
00219          const std::string& a_name,
00220          const BoxLayout& a_layout,
00221          const Interval&  a_comps = Interval(),
00222          bool redefineData = true);
00223 
00225 
00231 template <class T>
00232 int read(HDF5Handle& a_handle,
00233          LevelData<T>& a_data,
00234          const std::string& a_name,
00235          const DisjointBoxLayout& a_layout,
00236          const Interval& a_comps = Interval(),
00237          bool redefineData = true);
00238 
00240 
00250 class HDF5Handle
00251 {
00252 public:
00254 
00268   enum mode {CREATE, OPEN_RDONLY, OPEN_RDWR};
00269 
00271 
00273 
00278   HDF5Handle();
00279 
00281 
00289   HDF5Handle(const std::string& a_filename, mode a_mode);
00290 
00292 
00294 
00314   int open(const std::string& a_filename, mode a_mode);
00315 
00317 
00320   bool isOpen() const;
00321 
00323 
00328   void close();
00329 
00331 
00333 
00336   void setGroupToLevel(int a_level);
00337 
00339 
00346   int setGroup(const std::string& groupAbsPath);
00347 
00349 
00355   const std::string& getGroup() const;
00356 
00357   const hid_t& fileID() const;
00358   const hid_t& groupID() const;
00359   static hid_t box_id;
00360   static hid_t intvect_id;
00361   static hid_t realvect_id;
00362   static map<std::string, std::string> groups;
00363 
00364 private:
00365 
00366   HDF5Handle(const HDF5Handle&);
00367   HDF5Handle& operator=(const HDF5Handle&);
00368 
00369   hid_t         m_fileID;
00370   hid_t         m_currentGroupID;
00371   bool          m_isOpen;
00372   std::string   m_filename; // keep around for debugging
00373   std::string   m_group;
00374   int           m_level;
00375 
00376   //  static hid_t  file_access;
00377   static bool   initialized;
00378   static void   initialize();
00379 
00380 };
00381 
00383 
00425 class HDF5HeaderData
00426 {
00427 public:
00428 
00430 
00436   int writeToFile(HDF5Handle& file) const;
00437 
00439 
00447   int readFromFile(HDF5Handle& file);
00448 
00450   void clear();
00451 
00453   map<std::string, Real>        m_real;
00454 
00456   map<std::string, int>         m_int;
00457 
00459   map<std::string, std::string> m_string;
00460 
00462   map<std::string, IntVect>     m_intvect;
00463 
00465   map<std::string, Box>         m_box;
00466 
00468   map<std::string, RealVect>    m_realvect;
00469 
00470   //users should not need these functions in general
00471 
00472   int writeToLocation(hid_t loc_id) const;
00473   int readFromLocation(hid_t loc_id);
00474 
00475 private:
00476   static herr_t attributeScan(hid_t loc_id, const char *name, void *opdata);
00477 };
00478 
00479 extern "C"{
00480   herr_t HDF5HeaderDataattributeScan(hid_t loc_id, const char *name, void *opdata);
00481 }
00482 
00483 std::ostream& operator<<(std::ostream& os, const HDF5HeaderData& data);
00484 
00485 //=============================================================================
00486 //
00487 // end of declarations.
00488 //
00489 //=============================================================================
00490 
00491 //#include "HDF5Implem.H"
00492 /*   _______              __
00493     / ___/ /  ___  __ _  / /  ___
00494    / /__/ _ \/ _ \/  ' \/ _ \/ _ \
00495    \___/_//_/\___/_/_/_/_.__/\___/
00496 */
00497 //
00498 // This software is copyright (C) by the Lawrence Berkeley
00499 // National Laboratory.  Permission is granted to reproduce
00500 // this software for non-commercial purposes provided that
00501 // this notice is left intact.
00502 //
00503 // It is acknowledged that the U.S. Government has rights to
00504 // this software under Contract DE-AC03-765F00098 between
00505 // the U.S.  Department of Energy and the University of
00506 // California.
00507 //
00508 // This software is provided as a professional and academic
00509 // contribution for joint exchange. Thus it is experimental,
00510 // is provided ``as is'', with no warranties of any kind
00511 // whatsoever, no support, no promise of updates, or printed
00512 // documentation. By using this software, you acknowledge
00513 // that the Lawrence Berkeley National Laboratory and
00514 // Regents of the University of California shall have no
00515 // liability with respect to the infringement of other
00516 // copyrights by any part of this software.
00517 //
00518 //  ANAG, LBNL
00519 
00520 #include "LoadBalance.H"
00521 #include "LayoutIterator.H"
00522 #include "Vector.H"
00523 #include "memtrack.H"
00524 
00525 
00526 #if ( H5_VERS_MAJOR == 1 && H5_VERS_MINOR > 6 )
00527 typedef hsize_t ch_offset_t;
00528 #else
00529 #if ( H5_VERS_MAJOR == 1 && H5_VERS_MINOR == 6 && H5_VERS_RELEASE >= 4 )
00530 typedef hsize_t ch_offset_t;
00531 #else
00532 typedef hssize_t ch_offset_t;
00533 #endif
00534 #endif
00535 
00536 
00537 template<class T>
00538 hid_t H5Type(const T* dummy);
00539 
00540 template< >
00541 hid_t H5Type(const int* dummy);
00542 
00543 template< >
00544 hid_t H5Type(const long long* dummy);
00545 
00546 template< >
00547 hid_t H5Type(const float* dummy);
00548 
00549 template< >
00550 hid_t H5Type(const double* dummy);
00551 
00552 template< >
00553 hid_t H5Type(const Box* dummy);
00554 
00555 template< >
00556 hid_t H5Type(const RealVect* dummy);
00557 
00558 template< >
00559 hid_t H5Type(const IntVect* dummy);
00560 
00561 template<class T>
00562 hid_t H5Type(const T* dummy)
00563 {
00564   // no such definition;
00565   MayDay::Error(" H5Type(const T* dummy)");
00566   return -4;
00567 }
00568 
00569 void createData(hid_t& a_dataset,
00570                 hid_t& a_dataspace,
00571                 HDF5Handle& handle,
00572                 const std::string& name,
00573                 hid_t type,
00574                 hsize_t size);
00575 
00576 template <class T>
00577 void createDataset(hid_t& a_dataset,
00578                    hid_t& a_dataspace,
00579                    HDF5Handle& handle,
00580                    const std::string& name,
00581                    const T* dummy,
00582                    hsize_t size)
00583 {
00584   createData(a_dataset, a_dataspace, handle, name, H5Type(dummy), size);
00585 
00586 }
00587 
00588 void writeDataset(hid_t a_dataset,
00589                   hid_t a_dataspace,
00590                   const void* start,
00591                   ch_offset_t off,
00592                   hsize_t  count);
00593 
00594 void readDataset(hid_t a_dataset,
00595                  hid_t a_dataspace,
00596                  void* start,
00597                  ch_offset_t off,
00598                  hsize_t  count);
00599 
00600 // non-user code used in implementation of communication
00601 
00602 struct OffsetBuffer
00603 {
00604   Vector<int> index;
00605   Vector<Vector<int> > offsets;
00606   void operator=(const OffsetBuffer& rhs);
00607 };
00608 
00609 ostream& operator<<(ostream& os, const OffsetBuffer& ob);
00610 
00611 //OffsetBuffer specialization of linearSize
00612 template < >
00613 int linearSize(const OffsetBuffer& a_input);
00614 
00615 //OffsetBuffer specialization of linearIn
00616 template < >
00617 void linearIn(OffsetBuffer& a_outputT, const void* const a_inBuf);
00618 
00619 //OffsetBuffer specialization of linearOut
00620 template < >
00621 void linearOut(void* const a_outBuf, const OffsetBuffer& a_inputT);
00622 
00623 template < > int linearSize(const Vector<OffsetBuffer>& a_input);
00624 template < > void linearIn(Vector<OffsetBuffer>& a_outputT, const void* const inBuf);
00625 template < > void linearOut(void* const a_outBuf, const Vector<OffsetBuffer>& a_inputT);
00626 
00627 // First, template specializations for read/write for FArrayBox.
00628 
00629 template <>
00630 inline void dataTypes(Vector<hid_t>& a_types, const BaseFab<int>& dummy)
00631 {
00632   a_types.resize(1);
00633   a_types[0] = H5T_NATIVE_INT;
00634 }
00635 
00636 template <>
00637 inline void dataTypes(Vector<hid_t>& a_types, const BaseFab<char>& dummy)
00638 {
00639   a_types.resize(1);
00640   a_types[0] = H5T_NATIVE_CHAR;
00641 }
00642 
00643 /* since many compilers choke on the proper template specialization syntax
00644    I am forced to pass in a dummy specialization argument
00645 */
00646 template <>
00647 inline void dataTypes(Vector<hid_t>& a_types, const FArrayBox& dummy)
00648 {  a_types.resize(1); a_types[0] = H5T_NATIVE_REAL;}
00649 
00650 template <>
00651 inline void dataSize(const BaseFab<int>& item, Vector<int>& a_sizes,
00652                      const Box& box, const Interval& comps)
00653 {
00654   a_sizes[0] = box.numPts() * comps.size();
00655 }
00656 
00657 template <>
00658 inline void dataSize(const BaseFab<char>& item, Vector<int>& a_sizes,
00659                      const Box& box, const Interval& comps)
00660 {
00661   a_sizes[0] = box.numPts() * comps.size();
00662 }
00663 
00664 template <>
00665 inline void dataSize(const FArrayBox& item, Vector<int>& a_sizes,
00666                      const Box& box, const Interval& comps)
00667 {
00668   a_sizes[0] = box.numPts() * comps.size();
00669 }
00670 
00671 template <>
00672 inline const char* name(const FArrayBox& a_dummySpecializationArg)
00673 {
00674   // Attempt to get rid of warnings on IBM...
00675   //static const char* name = "FArrayBox";
00676   const char* name = "FArrayBox";
00677   return name;
00678 }
00679 
00680 template <>
00681 inline const char* name(const BaseFab<int>& a_dummySpecializationArg)
00682 {
00683   // Attempt to get rid of warnings on IBM...
00684   //static const char* name = "BaseFab<int>";
00685   const char* name = "BaseFab<int>";
00686   return name;
00687 }
00688 
00689 template <>
00690 inline const char* name(const BaseFab<char>& a_dummySpecializationArg)
00691 {
00692   // Attempt to get rid of warnings on IBM...
00693   //static const char* name = "BaseFab<int>";
00694   const char* name = "BaseFab<char>";
00695   return name;
00696 }
00697 //
00698 // now, generic, non-binary portable version of template functions
00699 // for people who just want ot rely on linearIn/linearOut
00700 
00701 template <class T>
00702 inline void dataTypes(Vector<hid_t>& a_types, const T& dummy)
00703 {  a_types.resize(1); a_types[0] = H5T_NATIVE_CHAR;}
00704 
00705 template <class T>
00706 inline void dataSize(const T& item, Vector<int>& a_sizes,
00707                      const Box& box, const Interval& comps)
00708 {
00709   a_sizes[0] = item.size(box, comps);
00710 }
00711 
00712 template <class T>
00713 inline void write(const T& item, Vector<void*>& a_allocatedBuffers,
00714                   const Box& box, const Interval& comps)
00715 {
00716   item.linearOut(a_allocatedBuffers[0], box, comps);
00717 }
00718 
00719 template <class T>
00720 inline void read(T& item, Vector<void*>& a_allocatedBuffers,
00721                  const Box& box, const Interval& comps)
00722 {
00723   item.linearIn(a_allocatedBuffers[0], box, comps);
00724 }
00725 
00726 template <class T>
00727 inline const char* name(const T& a_dummySpecializationArg)
00728 {
00729   static const char* name = "unknown";
00730   return name;
00731 }
00732 
00733 template <class T>
00734 void getOffsets(Vector<Vector<long long> >& offsets, const BoxLayoutData<T>& a_data,
00735                 int types, const Interval& comps, const IntVect& outputGhost)
00736 {
00737   const BoxLayout& layout = a_data.boxLayout();
00738   offsets.resize(types, Vector<long long>(layout.size()+1));
00739   //  offsets.resize(layout.size() + 1, Vector<long long>(types));
00740   for(int t=0; t<types; t++) offsets[t][0] = 0;
00741   Vector<int> thisSize(types);
00742   if(T::preAllocatable()==0)
00743     { // static preAllocatable
00744       T dummy;
00745       unsigned int index = 1;
00746       for(LayoutIterator it(layout.layoutIterator()); it.ok(); ++it)
00747         {
00748           Box region = layout[it()];
00749           region.grow(outputGhost);
00750           dataSize(dummy, thisSize, region, comps);
00751           for(unsigned int i=0; i<thisSize.size(); ++i)
00752             {
00753               //offsets[index][i] = offsets[index-1][i] + thisSize[i];
00754               offsets[i][index] = offsets[i][index-1] + thisSize[i];
00755             }
00756           ++index;
00757         }
00758     }
00759   else
00760     { // symmetric and dynamic preallocatable need two pass I/O
00761       OffsetBuffer buff;
00762       //int index = 0;
00763       for(DataIterator dit(a_data.dataIterator()); dit.ok(); ++dit)
00764         {
00765           int index = a_data.boxLayout().index(dit());
00766           //int index = dit().intCode();
00767           buff.index.push_back(index);
00768           Box region = layout[dit()];
00769           region.grow(outputGhost);
00770           dataSize(a_data[dit()], thisSize, region, comps);
00771           buff.offsets.push_back(thisSize);
00772         }
00773       Vector<OffsetBuffer> gathering(numProc());
00774       gather(gathering, buff, uniqueProc(SerialTask::compute));
00775       broadcast(gathering,  uniqueProc(SerialTask::compute));
00776       //  pout() << gathering<<endl;
00777       for(int i=0; i<numProc(); ++i)
00778         {
00779           OffsetBuffer& offbuf = gathering[i];
00780           for(int num=0; num<offbuf.index.size(); num++)
00781             {
00782               int index = offbuf.index[num];
00783               for(unsigned int j=0; j<types; ++j)
00784                 {
00785                   //offsets[index+1][j] = offbuf.offsets[num][j];
00786                   offsets[j][index+1] = offbuf.offsets[num][j];
00787                 }
00788             }
00789         }
00790       for(int i=0; i<layout.size(); i++)
00791         {
00792           for(unsigned int j=0; j<types; ++j)
00793             {
00794               //offsets[i+1][j] += offsets[i][j];
00795               offsets[j][i+1] += offsets[j][i];
00796             }
00797         }
00798     }
00799 
00800   // pout() << offsets<<endl;
00801 }
00802 
00803 //==================================================================
00804 //
00805 // Now, linear IO routines for a BoxLayoutData of T
00806 //
00807 template <class T>
00808 int write(HDF5Handle& a_handle, const BoxLayoutData<T>& a_data,
00809           const std::string& a_name, IntVect outputGhost,
00810           const Interval& in_comps, bool newForm)
00811 {
00812   int ret = 0;
00813 
00814   Interval comps(in_comps);
00815   if( comps.size() == 0) comps = a_data.interval();
00816   T dummy; // used for preallocatable methods for dumb compilers.
00817   Vector<hid_t> types;
00818   dataTypes(types, dummy);
00819 
00820   if(newForm && memcmp(a_name.c_str(), "M", 1)==0)
00821     {
00822       std::string currentGroup = a_handle.getGroup();
00823       a_handle.setGroup("/");
00824       HDF5HeaderData info;
00825       info.readFromFile(a_handle);
00826       outputGhost = info.m_intvect["Ghost"];
00827       info.clear();
00828       a_handle.setGroup("/" + HDF5Handle::groups[a_name] + "CenteredComponents");
00829       info.readFromFile(a_handle);
00830       int nc = info.m_int["Num"+a_name];
00831       if(nc == 0){
00832         char cname[40];
00833         info.m_int["Num"+a_name] = comps.size();
00834         nc = comps.size();
00835         for(int i=0; i<nc; ++i){
00836           sprintf(cname, "Component%i", i);
00837           info.m_string[cname] = cname;
00838         }
00839         info.writeToFile(a_handle);
00840       }
00841       a_handle.setGroup(currentGroup);
00842       CH_assert(nc == comps.size());
00843     }
00844 
00845   Vector<Vector<long long> > offsets;
00846   Vector<long long> bufferCapacity(types.size(), 1);  // noel (was 0)
00847   Vector<void*> buffers(types.size(), NULL);
00848 
00849   getOffsets(offsets, a_data, types.size(), comps, outputGhost);
00850 
00851   // create datasets collectively.
00852   hsize_t flatdims[1];
00853   char dataname[100];
00854   Vector<hid_t> dataspace(types.size());
00855   Vector<hid_t> dataset(types.size());
00856 
00857   herr_t err;
00858   hsize_t count[1];
00859   ch_offset_t offset[1];
00860   CH_assert(!(newForm && types.size() != 1));
00861 
00862   for(unsigned int i=0; i<types.size(); ++i)
00863     {
00864       flatdims[0] = offsets[i][offsets[i].size()-1];
00865       if(newForm){
00866         if(memcmp(a_name.c_str(), "M", 1)==0){
00867           strcpy(dataname, "Mask");
00868         }else{
00869           sprintf(dataname, "%sRegular", a_name.c_str());
00870         }
00871       }else {
00872         sprintf(dataname, "%s:datatype=%i",a_name.c_str(), i);
00873       }
00874       dataspace[i]      = H5Screate_simple(1, flatdims, NULL);
00875       CH_assert(dataspace[i] >=0);
00876       dataset[i]        = H5Dcreate(a_handle.groupID(), dataname,
00877                                     types[i],
00878                                     dataspace[i], H5P_DEFAULT);
00879       CH_assert(dataset[i] >= 0);
00880     }
00881 
00882   hid_t offsetspace, offsetData;
00883   for(unsigned int i=0; i<types.size(); ++i)
00884     {
00885       flatdims[0] =  offsets[i].size();
00886       if(newForm){
00887         sprintf(dataname, "%sOffsets",a_name.c_str());
00888       } else {
00889         sprintf(dataname, "%s:offsets=%i",a_name.c_str(), i);
00890       }
00891       offsetspace =  H5Screate_simple(1, flatdims, NULL);
00892       CH_assert(offsetspace >= 0);
00893       offsetData  =   H5Dcreate(a_handle.groupID(), dataname,
00894                                 H5T_NATIVE_LLONG, offsetspace, H5P_DEFAULT);
00895       CH_assert(offsetData >= 0);
00896       if(procID() == 0)
00897         {
00898           hid_t memdataspace = H5Screate_simple(1, flatdims, NULL);
00899           CH_assert(memdataspace >= 0);
00900           err = H5Dwrite(offsetData, H5T_NATIVE_LLONG, memdataspace, offsetspace,
00901                          H5P_DEFAULT, &(offsets[i][0]));
00902           CH_assert(err >= 0);
00903           H5Sclose(memdataspace);
00904         }
00905       H5Sclose(offsetspace);
00906       H5Dclose(offsetData);
00907     }
00908 
00909   // write BoxLayoutData attributes into Dataset[0]
00910   if(!newForm){
00911     HDF5HeaderData info;
00912     info.m_int["comps"] = comps.size();
00913     info.m_string["objectType"] = name(dummy);
00914     std::string group = a_handle.getGroup();
00915     a_handle.setGroup(group+"/"+a_name+"_attributes");
00916     info.writeToFile(a_handle);
00917     a_handle.setGroup(group);
00918   }
00919 
00920   // collective operations finished, now perform parallel writes
00921   // to specified hyperslabs.
00922 
00923   Vector<size_t> type_size(types.size());
00924   for(unsigned int i=0; i<types.size(); ++i)
00925     {
00926       type_size[i] = H5Tget_size(types[i]);
00927     }
00928 
00929   Vector<int> thisSize(types.size());
00930 
00931   // step 1, create buffer big enough to hold the biggest linearized T
00932   // that I will have to output.
00933 
00934   //  pout()<<"offsets ";
00935   for(int i=0; i<offsets[0].size(); i++)
00936   {
00937     //    pout()<<" "<<offsets[0][i];
00938   }
00939   // pout()<<"\n";
00940   for(DataIterator it = a_data.dataIterator(); it.ok(); ++it)
00941     {
00942       unsigned int index = a_data.boxLayout().index(it());
00943       for(unsigned int i=0; i<types.size(); ++i)
00944         {
00945           long long size = (offsets[i][index+1] - offsets[i][index])
00946             * type_size[i];
00947           // pout()<<"index:size "<<index<<" "<<size<<"\n";
00948           CH_assert(size >= 0);
00949           if(size > bufferCapacity[i]) // grow buffer if necessary.....
00950             {
00951               bufferCapacity[i] = size;
00952             }
00953         }
00954     }
00955   // CH_assert(bufferCapacity[0] > 1);
00956   for(unsigned int i=0; i<types.size(); ++i)
00957     {
00958       buffers[i] = malloc(bufferCapacity[i]);
00959       if(buffers[i] == NULL) {
00960         pout() << " i=" << i
00961                << " types.size() = " << types.size()
00962                << " bufferCapacity[i] = " << (int)bufferCapacity[i]
00963                << endl;
00964         MayDay::Error("memory error in buffer allocation write");
00965       }
00966     }
00967 
00968   // Step 2.  actually a) write each of my T objects into the
00969   // buffer, then b) write that buffered data out to the
00970   // write position in the data file using hdf5 hyperslab functions.
00971   for(DataIterator it = a_data.dataIterator(); it.ok(); ++it)
00972     {
00973       const T& data = a_data[it()];
00974       unsigned int index = a_data.boxLayout().index(it());
00975       Box box = a_data.box(it());
00976       box.grow(outputGhost);
00977       write(data, buffers, box, comps); //write T to buffer
00978       for(unsigned int i=0; i<types.size(); ++i)
00979         {
00980           offset[0] = offsets[i][index];
00981           count[0] = offsets[i][index+1] - offset[0];
00982           if(count[0] > 0){
00983           err =  H5Sselect_hyperslab(dataspace[i], H5S_SELECT_SET,
00984                                      offset, NULL,
00985                                      count, NULL);
00986           CH_assert(err >= 0);
00987           hid_t memdataspace = H5Screate_simple(1, count, NULL);
00988           CH_assert(memdataspace >= 0);
00989           err = H5Dwrite(dataset[i], types[i], memdataspace, dataspace[i],
00990                          H5P_DEFAULT, buffers[i]);
00991           CH_assert(err >= 0);
00992           H5Sclose(memdataspace);
00993           if(err < 0) { ret = err; goto cleanup;}
00994           }
00995         }
00996     }
00997 
00998   // OK, clean up data structures
00999 
01000  cleanup:
01001   for(unsigned int i=0; i<types.size(); ++i)
01002     {
01003       free(buffers[i]);
01004       H5Sclose(dataspace[i]);
01005       H5Dclose(dataset[i]);
01006     }
01007   return ret;
01008 
01009 }
01010 
01011 template <class T>
01012 int write(HDF5Handle& a_handle, const LevelData<T>& a_data,
01013           const std::string& a_name, const IntVect& outputGhost, const Interval& in_comps)
01014 {
01015   HDF5HeaderData info;
01016   info.m_intvect["ghost"] = a_data.ghostVect();
01017   IntVect og(outputGhost);
01018   og.min(a_data.ghostVect());
01019   info.m_intvect["outputGhost"] = og;
01020   std::string group = a_handle.getGroup();
01021   a_handle.setGroup(group+"/"+a_name+"_attributes");
01022   info.writeToFile(a_handle);
01023   a_handle.setGroup(group);
01024   return write(a_handle, (const BoxLayoutData<T>&)a_data, a_name, og, in_comps);
01025 }
01026 
01027 template <class T>
01028 int read(HDF5Handle& a_handle, LevelData<T>& a_data, const std::string& a_name,
01029          const DisjointBoxLayout& a_layout, const Interval& a_comps, bool a_redefineData)
01030 {
01031   if(a_redefineData)
01032     {
01033       HDF5HeaderData info;
01034       std::string group = a_handle.getGroup();
01035       if(a_handle.setGroup(group+"/"+a_name+"_attributes"))
01036         {
01037           std::string message = "error opening "+a_handle.getGroup()+"/"+a_name ;
01038           MayDay::Warning(message.c_str());
01039           return 1;
01040         }
01041       info.readFromFile(a_handle);
01042       a_handle.setGroup(group);
01043       int ncomp =  info.m_int["comps"];
01044       IntVect ghost = info.m_intvect["ghost"];
01045       if(a_comps.end() > 0 && ncomp < a_comps.end())
01046         {
01047           MayDay::Error("attempt to read component interval that is not available");
01048         }
01049       if(a_comps.size() == 0)
01050         a_data.define(a_layout, ncomp, ghost);
01051       else
01052         a_data.define(a_layout, a_comps.size(), ghost);
01053     }
01054   return read(a_handle, (BoxLayoutData<T>&)a_data, a_name, a_layout, a_comps, false);
01055 
01056 }
01057 
01058 template <class T>
01059 int read(HDF5Handle& a_handle, BoxLayoutData<T>& a_data, const std::string& a_name,
01060          const BoxLayout& a_layout, const Interval& a_comps, bool a_redefineData)
01061 {
01062   int ret = 0; // return value;
01063 
01064   herr_t err;
01065 
01066   char dataname[100];
01067   hsize_t count[1];
01068   ch_offset_t offset[1];
01069   Vector<Vector<long long> > offsets;
01070 
01071   T dummy;
01072   Vector<hid_t> types;
01073   dataTypes(types, dummy);
01074   Vector<hid_t> dataspace(types.size());
01075   Vector<hid_t> dataset(types.size());
01076   offsets.resize(types.size(), Vector<long long>(a_layout.size() +1));
01077 
01078   //Vector<int> bufferCapacity(types.size(), 500);
01079   //Vector<void*> buffers(types.size(), NULL);
01080   Vector<Vector<char> > buffers(types.size(), 500);
01081 
01082   for(unsigned int i=0; i<types.size(); ++i)
01083     {
01084       sprintf(dataname, "%s:datatype=%i",a_name.c_str(), i);
01085       dataset[i]        = H5Dopen(a_handle.groupID(), dataname);
01086       if(dataset[i] < 0) {MayDay::Warning("dataset open failure"); return dataset[i];}
01087       dataspace[i]      = H5Dget_space(dataset[i]);
01088       if(dataspace[i] < 0) {MayDay::Warning("dataspace open failure"); return dataspace[i];}
01089     }
01090 
01091   hid_t offsetspace, offsetData;
01092   hsize_t flatdims[1];
01093   for(unsigned int i=0; i<types.size(); ++i)
01094     {
01095       flatdims[0] =  offsets[i].size();
01096       sprintf(dataname, "%s:offsets=%i",a_name.c_str(), i);
01097       offsetspace =  H5Screate_simple(1, flatdims, NULL);
01098       CH_assert(offsetspace >= 0);
01099       offsetData  =   H5Dopen(a_handle.groupID(), dataname);
01100       CH_assert(offsetData >= 0);
01101       hid_t memdataspace = H5Screate_simple(1, flatdims, NULL);
01102       CH_assert(memdataspace >= 0);
01103       err = H5Dread(offsetData, H5T_NATIVE_LLONG, memdataspace, offsetspace,
01104                     H5P_DEFAULT, &(offsets[i][0]));
01105       CH_assert(err >=0);
01106       H5Sclose(memdataspace);
01107       H5Sclose(offsetspace);
01108       H5Dclose(offsetData);
01109     }
01110 
01111   HDF5HeaderData info;
01112   std::string group = a_handle.getGroup();
01113   if(a_handle.setGroup(a_handle.getGroup()+"/"+a_name+"_attributes"))
01114     {
01115       std::string message = "error opening "+a_handle.getGroup()+"/"+a_name ;
01116       MayDay::Warning(message.c_str());
01117       return 1;
01118     }
01119 
01120   info.readFromFile(a_handle);
01121   a_handle.setGroup(group);
01122   int ncomps = info.m_int["comps"];
01123   IntVect outputGhost(IntVect::Zero); // backwards file compatible mode.
01124   if(info.m_intvect.find("outputGhost") != info.m_intvect.end())
01125     {
01126       outputGhost = info.m_intvect["outputGhost"];
01127     }
01128   if(ncomps <= 0){
01129     MayDay::Warning("ncomps <= 0 in read");
01130     return ncomps;
01131   }
01132 
01133   if(a_redefineData){
01134     if(a_comps.size() != 0){
01135       a_data.define(a_layout, a_comps.size());
01136     } else {
01137       a_data.define(a_layout, ncomps);
01138     }
01139   }
01140 
01141   Interval comps(0, ncomps-1);
01142   //huh?
01143   //  if(a_comps.size() != 0)  comps = Interval(0, a_comps.size());
01144 
01145   //  getOffsets(offsets, a_data, types.size(), comps);
01146 
01147   Vector<size_t> type_size(types.size());
01148   for(unsigned int i=0; i<types.size(); ++i)
01149     {
01150       type_size[i] = H5Tget_size(types[i]);
01151 
01152     }
01153 
01154   Vector<int> thisSize(types.size());
01155   for(DataIterator it = a_data.dataIterator(); it.ok(); ++it)
01156     {
01157       T& data = a_data[it()];
01158       unsigned int index = a_data.boxLayout().index(it());
01159       Box box = a_data.box(it());
01160 
01161       for(unsigned int i=0; i<types.size(); ++i)
01162         {
01163           if(a_comps.size() == 0){
01164             offset[0] = offsets[i][index];
01165             count[0] = offsets[i][index+1] - offset[0];
01166           } else {
01167             offset[0] = offsets[i][index] + box.numPts()*a_comps.begin();
01168             count[0]  = a_comps.size() * box.numPts();
01169           }
01170           if(count[0] > 0)
01171           {
01172             int size = count[0] * type_size[i];
01173             while(size > buffers[i].size())
01174             {
01175               buffers[i].resize(2*buffers[i].size());
01176             }
01177 
01178             err =  H5Sselect_hyperslab(dataspace[i], H5S_SELECT_SET,
01179                                        offset, NULL,
01180                                        count, NULL);
01181             CH_assert(err >= 0);
01182             hid_t memdataspace = H5Screate_simple(1, count, NULL);
01183             CH_assert(memdataspace >= 0);
01184             err = H5Dread(dataset[i], types[i], memdataspace, dataspace[i],
01185                           H5P_DEFAULT, &(buffers[i][0]));
01186             CH_assert(err >= 0);
01187             H5Sclose(memdataspace);
01188             if(err < 0) { ret = err; goto cleanup;}
01189           }
01190         }
01191       box.grow(outputGhost);
01192       read(data, buffers,  box, comps);
01193     }
01194 
01195  cleanup:
01196   for(unsigned int i=0; i<types.size(); ++i)
01197     {
01198       // free(buffers[i]);
01199       H5Sclose(dataspace[i]);
01200       H5Dclose(dataset[i]);
01201     }
01202   return ret;
01203 }
01204 
01205 template <class T>
01206 int writeLevel(HDF5Handle& a_handle,
01207                const int&  a_level,
01208                const LevelData<T>& a_data,
01209                const Real& a_dx,
01210                const Real& a_dt,
01211                const Real& a_time,
01212                const Box&  a_domain,
01213                const int&  a_refRatio,
01214                const IntVect& outputGhost,
01215                const Interval& comps)
01216 {
01217   int error;
01218   char levelName[10];
01219   std::string currentGroup = a_handle.getGroup();
01220   sprintf(levelName, "/level_%i",a_level);
01221   error = a_handle.setGroup(currentGroup + levelName);
01222   if(error != 0) return 1;
01223 
01224   HDF5HeaderData meta;
01225   meta.m_real["dx"] = a_dx;
01226   meta.m_real["dt"] = a_dt;
01227   meta.m_real["time"] = a_time;
01228   meta.m_box["prob_domain"] = a_domain;
01229   meta.m_int["ref_ratio"] = a_refRatio;
01230 
01231   error = meta.writeToFile(a_handle);
01232   if(error != 0) return 2;
01233 
01234   error = write(a_handle, a_data.boxLayout());
01235   if(error != 0) return 3;
01236 
01237   error = write(a_handle, a_data, "data", outputGhost, comps);
01238   if(error != 0) return 4;
01239 
01240   a_handle.setGroup(currentGroup);
01241 
01242   return 0;
01243 }
01244 
01245 template <class T>
01246 int readLevel(HDF5Handle&   a_handle,
01247               const int&    a_level,
01248               LevelData<T>& a_data,
01249               Real& a_dx,
01250               Real& a_dt,
01251               Real& a_time,
01252               Box&  a_domain,
01253               int&  a_refRatio,
01254               const Interval&   a_comps,
01255               bool  setGhost)
01256 {
01257   HDF5HeaderData header;
01258   header.readFromFile(a_handle);
01259   //unused
01260   // int nComp = header.m_int["num_components"];
01261 
01262   int error;
01263   char levelName[10];
01264   std::string currentGroup = a_handle.getGroup();
01265   sprintf(levelName, "/level_%i",a_level);
01266   error = a_handle.setGroup(currentGroup + levelName);
01267   if(error != 0) return 1;
01268 
01269   HDF5HeaderData meta;
01270   error = meta.readFromFile(a_handle);
01271   if(error != 0) return 2;
01272   a_dx       = meta.m_real["dx"];
01273   a_dt       = meta.m_real["dt"];
01274   a_time     = meta.m_real["time"];
01275   a_domain   = meta.m_box["prob_domain"];
01276   a_refRatio = meta.m_int["ref_ratio"];
01277 
01278   Vector<Box> boxes;
01279   error = read(a_handle, boxes);
01280   Vector<int> procIDs;
01281   LoadBalance(procIDs, boxes);
01282 
01283   DisjointBoxLayout layout(boxes, procIDs);
01284 
01285   layout.close();
01286   if(error != 0) return 3;
01287 
01288     error = read(a_handle, a_data, "data", layout, a_comps);
01289 
01290   if(error != 0) return 4;
01291 
01292   a_handle.setGroup(currentGroup);
01293 
01294   return 0;
01295 }
01296 
01297 #else // CH_USE_HDF5
01298 
01299 // this is the only thing needed when HDF is not used
01300 #define HOFFSET(S,M)    (offsetof(S,M))
01301 
01302 #endif // CH_USE_HDF5
01303 
01304 #endif  // CH_HDF5_H

Generated on Wed Oct 5 13:52:08 2005 for Chombo&AMRSelfGravity by  doxygen 1.4.1