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    / /__/ _ \/ _ \/  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 HDF5  // if you don't have HDF5, then this file is useless
00056 
00057 #include <iostream>
00058 using std::cout;
00059 using std::endl;
00060 
00061 #ifdef 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 template<class T>
00526 hid_t H5Type(const T* dummy);
00527 
00528 template< >
00529 hid_t H5Type(const int* dummy);
00530 
00531 template< >
00532 hid_t H5Type(const long long* dummy);
00533 
00534 template< >
00535 hid_t H5Type(const float* dummy);
00536 
00537 template< >
00538 hid_t H5Type(const double* dummy);
00539 
00540 template< >
00541 hid_t H5Type(const Box* dummy);
00542 
00543 template< >
00544 hid_t H5Type(const RealVect* dummy);
00545 
00546 template< >
00547 hid_t H5Type(const IntVect* dummy);
00548 
00549 template<class T>
00550 hid_t H5Type(const T* dummy)
00551 {
00552   // no such definition;
00553   MayDay::Error(" H5Type(const T* dummy)");
00554   return -4;
00555 }
00556 
00557 void createData(hid_t& a_dataset,
00558                 hid_t& a_dataspace,
00559                 HDF5Handle& handle,
00560                 const std::string& name,
00561                 hid_t type,
00562                 hsize_t size);
00563 
00564 template <class T>
00565 void createDataset(hid_t& a_dataset,
00566                    hid_t& a_dataspace,
00567                    HDF5Handle& handle,
00568                    const std::string& name,
00569                    const T* dummy,
00570                    hsize_t size)
00571 {
00572   createData(a_dataset, a_dataspace, handle, name, H5Type(dummy), size);
00573 
00574 }
00575 
00576 void writeDataset(hid_t a_dataset,
00577                   hid_t a_dataspace,
00578                   const void* start,
00579                   hssize_t off,
00580                   hsize_t  count);
00581 
00582 void readDataset(hid_t a_dataset,
00583                  hid_t a_dataspace,
00584                  void* start,
00585                  hssize_t off,
00586                  hsize_t  count);
00587 
00588 // non-user code used in implementation of communication
00589 
00590 struct OffsetBuffer
00591 {
00592   Vector<int> index;
00593   Vector<Vector<int> > offsets;
00594   void operator=(const OffsetBuffer& rhs);
00595 };
00596 
00597 ostream& operator<<(ostream& os, const OffsetBuffer& ob);
00598 
00599 //OffsetBuffer specialization of linearSize
00600 template < >
00601 int linearSize(const OffsetBuffer& a_input);
00602 
00603 //OffsetBuffer specialization of linearIn
00604 template < >
00605 void linearIn(OffsetBuffer& a_outputT, const void* const a_inBuf);
00606 
00607 //OffsetBuffer specialization of linearOut
00608 template < >
00609 void linearOut(void* const a_outBuf, const OffsetBuffer& a_inputT);
00610 
00611 template < > int linearSize(const Vector<OffsetBuffer>& a_input);
00612 template < > void linearIn(Vector<OffsetBuffer>& a_outputT, const void* const inBuf);
00613 template < > void linearOut(void* const a_outBuf, const Vector<OffsetBuffer>& a_inputT);
00614 
00615 // First, template specializations for read/write for FArrayBox.
00616 
00617 template <>
00618 inline void dataTypes(Vector<hid_t>& a_types, const BaseFab<int>& dummy)
00619 {
00620   a_types.resize(1);
00621   a_types[0] = H5T_NATIVE_INT;
00622 }
00623 
00624 template <>
00625 inline void dataTypes(Vector<hid_t>& a_types, const BaseFab<char>& dummy)
00626 {
00627   a_types.resize(1);
00628   a_types[0] = H5T_NATIVE_CHAR;
00629 }
00630 
00631 /* since many compilers choke on the proper template specialization syntax
00632    I am forced to pass in a dummy specialization argument
00633 */
00634 template <>
00635 inline void dataTypes(Vector<hid_t>& a_types, const FArrayBox& dummy)
00636 {  a_types.resize(1); a_types[0] = H5T_NATIVE_REAL;}
00637 
00638 template <>
00639 inline void dataSize(const BaseFab<int>& item, Vector<int>& a_sizes,
00640                      const Box& box, const Interval& comps)
00641 {
00642   a_sizes[0] = box.numPts() * comps.size();
00643 }
00644 
00645 template <>
00646 inline void dataSize(const BaseFab<char>& item, Vector<int>& a_sizes,
00647                      const Box& box, const Interval& comps)
00648 {
00649   a_sizes[0] = box.numPts() * comps.size();
00650 }
00651 
00652 template <>
00653 inline void dataSize(const FArrayBox& item, Vector<int>& a_sizes,
00654                      const Box& box, const Interval& comps)
00655 {
00656   a_sizes[0] = box.numPts() * comps.size();
00657 }
00658 
00659 template <>
00660 inline const char* name(const FArrayBox& a_dummySpecializationArg)
00661 {
00662   // Attempt to get rid of warnings on IBM...
00663   //static const char* name = "FArrayBox";
00664   const char* name = "FArrayBox";
00665   return name;
00666 }
00667 
00668 template <>
00669 inline const char* name(const BaseFab<int>& a_dummySpecializationArg)
00670 {
00671   // Attempt to get rid of warnings on IBM...
00672   //static const char* name = "BaseFab<int>";
00673   const char* name = "BaseFab<int>";
00674   return name;
00675 }
00676 
00677 template <>
00678 inline const char* name(const BaseFab<char>& a_dummySpecializationArg)
00679 {
00680   // Attempt to get rid of warnings on IBM...
00681   //static const char* name = "BaseFab<int>";
00682   const char* name = "BaseFab<char>";
00683   return name;
00684 }
00685 //
00686 // now, generic, non-binary portable version of template functions
00687 // for people who just want ot rely on linearIn/linearOut
00688 
00689 template <class T>
00690 inline void dataTypes(Vector<hid_t>& a_types, const T& dummy)
00691 {  a_types.resize(1); a_types[0] = H5T_NATIVE_CHAR;}
00692 
00693 template <class T>
00694 inline void dataSize(const T& item, Vector<int>& a_sizes,
00695                      const Box& box, const Interval& comps)
00696 {
00697   a_sizes[0] = item.size(box, comps);
00698 }
00699 
00700 template <class T>
00701 inline void write(const T& item, Vector<void*>& a_allocatedBuffers,
00702                   const Box& box, const Interval& comps)
00703 {
00704   item.linearOut(a_allocatedBuffers[0], box, comps);
00705 }
00706 
00707 template <class T>
00708 inline void read(T& item, Vector<void*>& a_allocatedBuffers,
00709                  const Box& box, const Interval& comps)
00710 {
00711   item.linearIn(a_allocatedBuffers[0], box, comps);
00712 }
00713 
00714 template <class T>
00715 inline const char* name(const T& a_dummySpecializationArg)
00716 {
00717   static const char* name = "unknown";
00718   return name;
00719 }
00720 
00721 template <class T>
00722 void getOffsets(Vector<Vector<long long> >& offsets, const BoxLayoutData<T>& a_data,
00723                 int types, const Interval& comps, const IntVect& outputGhost)
00724 {
00725   const BoxLayout& layout = a_data.boxLayout();
00726   offsets.resize(types, Vector<long long>(layout.size()+1));
00727   //  offsets.resize(layout.size() + 1, Vector<long long>(types));
00728   for(int t=0; t<types; t++) offsets[t][0] = 0;
00729   Vector<int> thisSize(types);
00730   if(T::preAllocatable()==0)
00731     { // static preAllocatable
00732       T dummy;
00733       unsigned int index = 1;
00734       for(LayoutIterator it(layout.layoutIterator()); it.ok(); ++it)
00735         {
00736           Box region = layout[it()];
00737           region.grow(outputGhost);
00738           dataSize(dummy, thisSize, region, comps);
00739           for(unsigned int i=0; i<thisSize.size(); ++i)
00740             {
00741               //offsets[index][i] = offsets[index-1][i] + thisSize[i];
00742               offsets[i][index] = offsets[i][index-1] + thisSize[i];
00743             }
00744           ++index;
00745         }
00746     }
00747   else
00748     { // symmetric and dynamic preallocatable need two pass I/O
00749       OffsetBuffer buff;
00750       //int index = 0;
00751       for(DataIterator dit(a_data.dataIterator()); dit.ok(); ++dit)
00752         {
00753           int index = a_data.boxLayout().index(dit());
00754           //int index = dit().intCode();
00755           buff.index.push_back(index);
00756           Box region = layout[dit()];
00757           region.grow(outputGhost);
00758           dataSize(a_data[dit()], thisSize, region, comps);
00759           buff.offsets.push_back(thisSize);
00760         }
00761       Vector<OffsetBuffer> gathering(numProc());
00762       gather(gathering, buff, uniqueProc(SerialTask::compute));
00763       broadcast(gathering,  uniqueProc(SerialTask::compute));
00764       //  pout() << gathering<<endl;
00765       for(int i=0; i<numProc(); ++i)
00766         {
00767           OffsetBuffer& offbuf = gathering[i];
00768           for(int num=0; num<offbuf.index.size(); num++)
00769             {
00770               int index = offbuf.index[num];
00771               for(unsigned int j=0; j<types; ++j)
00772                 {
00773                   //offsets[index+1][j] = offbuf.offsets[num][j];
00774                   offsets[j][index+1] = offbuf.offsets[num][j];
00775                 }
00776             }
00777         }
00778       for(int i=0; i<layout.size(); i++)
00779         {
00780           for(unsigned int j=0; j<types; ++j)
00781             {
00782               //offsets[i+1][j] += offsets[i][j];
00783               offsets[j][i+1] += offsets[j][i];
00784             }
00785         }
00786     }
00787 
00788   // pout() << offsets<<endl;
00789 }
00790 
00791 //==================================================================
00792 //
00793 // Now, linear IO routines for a BoxLayoutData of T
00794 //
00795 template <class T>
00796 int write(HDF5Handle& a_handle, const BoxLayoutData<T>& a_data,
00797           const std::string& a_name, IntVect outputGhost,
00798           const Interval& in_comps, bool newForm)
00799 {
00800   int ret = 0;
00801 
00802   Interval comps(in_comps);
00803   if( comps.size() == 0) comps = a_data.interval();
00804   T dummy; // used for preallocatable methods for dumb compilers.
00805   Vector<hid_t> types;
00806   dataTypes(types, dummy);
00807 
00808   if(newForm && memcmp(a_name.c_str(), "M", 1)==0)
00809     {
00810       std::string currentGroup = a_handle.getGroup();
00811       a_handle.setGroup("/");
00812       HDF5HeaderData info;
00813       info.readFromFile(a_handle);
00814       outputGhost = info.m_intvect["Ghost"];
00815       info.clear();
00816       a_handle.setGroup("/" + HDF5Handle::groups[a_name] + "CenteredComponents");
00817       info.readFromFile(a_handle);
00818       int nc = info.m_int["Num"+a_name];
00819       if(nc == 0){
00820         char cname[40];
00821         info.m_int["Num"+a_name] = comps.size();
00822         nc = comps.size();
00823         for(int i=0; i<nc; ++i){
00824           sprintf(cname, "Component%i", i);
00825           info.m_string[cname] = cname;
00826         }
00827         info.writeToFile(a_handle);
00828       }
00829       a_handle.setGroup(currentGroup);
00830       assert(nc == comps.size());
00831     }
00832 
00833   Vector<Vector<long long> > offsets;
00834   Vector<long long> bufferCapacity(types.size(), 1);  // noel (was 0)
00835   Vector<void*> buffers(types.size(), NULL);
00836 
00837   getOffsets(offsets, a_data, types.size(), comps, outputGhost);
00838 
00839   // create datasets collectively.
00840   hsize_t flatdims[1];
00841   char dataname[100];
00842   Vector<hid_t> dataspace(types.size());
00843   Vector<hid_t> dataset(types.size());
00844 
00845   herr_t err;
00846   hsize_t count[1];
00847   hssize_t offset[1];
00848   assert(!(newForm && types.size() != 1));
00849 
00850   for(unsigned int i=0; i<types.size(); ++i)
00851     {
00852       flatdims[0] = offsets[i][offsets[i].size()-1];
00853       if(newForm){
00854         if(memcmp(a_name.c_str(), "M", 1)==0){
00855           sprintf(dataname, "Mask");
00856         }else{
00857           sprintf(dataname, "%sRegular", a_name.c_str());
00858         }
00859       }else {
00860         sprintf(dataname, "%s:datatype=%i",a_name.c_str(), i);
00861       }
00862       dataspace[i]      = H5Screate_simple(1, flatdims, NULL);
00863       assert(dataspace[i] >=0);
00864       dataset[i]        = H5Dcreate(a_handle.groupID(), dataname,
00865                                     types[i],
00866                                     dataspace[i], H5P_DEFAULT);
00867       assert(dataset[i] >= 0);
00868     }
00869 
00870   hid_t offsetspace, offsetData;
00871   for(unsigned int i=0; i<types.size(); ++i)
00872     {
00873       flatdims[0] =  offsets[i].size();
00874       if(newForm){
00875         sprintf(dataname, "%sOffsets",a_name.c_str());
00876       } else {
00877         sprintf(dataname, "%s:offsets=%i",a_name.c_str(), i);
00878       }
00879       offsetspace =  H5Screate_simple(1, flatdims, NULL);
00880       assert(offsetspace >= 0);
00881       offsetData  =   H5Dcreate(a_handle.groupID(), dataname,
00882                                 H5T_NATIVE_LLONG, offsetspace, H5P_DEFAULT);
00883       assert(offsetData >= 0);
00884       if(procID() == 0)
00885         {
00886           hid_t memdataspace = H5Screate_simple(1, flatdims, NULL);
00887           assert(memdataspace >= 0);
00888           err = H5Dwrite(offsetData, H5T_NATIVE_LLONG, memdataspace, offsetspace,
00889                          H5P_DEFAULT, &(offsets[i][0]));
00890           assert(err >= 0);
00891           H5Sclose(memdataspace);
00892         }
00893       H5Sclose(offsetspace);
00894       H5Dclose(offsetData);
00895     }
00896 
00897   // write BoxLayoutData attributes into Dataset[0]
00898   if(!newForm){
00899     HDF5HeaderData info;
00900     info.m_int["comps"] = comps.size();
00901     info.m_string["objectType"] = name(dummy);
00902     std::string group = a_handle.getGroup();
00903     a_handle.setGroup(group+"/"+a_name+"_attributes");
00904     info.writeToFile(a_handle);
00905     a_handle.setGroup(group);
00906   }
00907 
00908   // collective operations finished, now perform parallel writes
00909   // to specified hyperslabs.
00910 
00911   Vector<size_t> type_size(types.size());
00912   for(unsigned int i=0; i<types.size(); ++i)
00913     {
00914       type_size[i] = H5Tget_size(types[i]);
00915     }
00916 
00917   Vector<int> thisSize(types.size());
00918 
00919   // step 1, create buffer big enough to hold the biggest linearized T
00920   // that I will have to output.
00921 
00922   //  pout()<<"offsets ";
00923   for(int i=0; i<offsets[0].size(); i++)
00924   {
00925     //    pout()<<" "<<offsets[0][i];
00926   }
00927   // pout()<<"\n";
00928   for(DataIterator it = a_data.dataIterator(); it.ok(); ++it)
00929     {
00930       unsigned int index = a_data.boxLayout().index(it());
00931       for(unsigned int i=0; i<types.size(); ++i)
00932         {
00933           long long size = (offsets[i][index+1] - offsets[i][index])
00934             * type_size[i];
00935           // pout()<<"index:size "<<index<<" "<<size<<"\n";
00936           assert(size >= 0);
00937           if(size > bufferCapacity[i]) // grow buffer if necessary.....
00938             {
00939               bufferCapacity[i] = size;
00940             }
00941         }
00942     }
00943   //assert(bufferCapacity[0] > 1);
00944   for(unsigned int i=0; i<types.size(); ++i)
00945     {
00946       buffers[i] = malloc(bufferCapacity[i]);
00947       if(buffers[i] == NULL) {
00948         pout() << " i=" << i
00949                << " types.size() = " << types.size()
00950                << " bufferCapacity[i] = " << (int)bufferCapacity[i]
00951                << endl;
00952         MayDay::Error("memory error in buffer allocation write");
00953       }
00954     }
00955 
00956   // Step 2.  actually a) write each of my T objects into the
00957   // buffer, then b) write that buffered data out to the
00958   // write position in the data file using hdf5 hyperslab functions.
00959   for(DataIterator it = a_data.dataIterator(); it.ok(); ++it)
00960     {
00961       const T& data = a_data[it()];
00962       unsigned int index = a_data.boxLayout().index(it());
00963       Box box = a_data.box(it());
00964       box.grow(outputGhost);
00965       write(data, buffers, box, comps); //write T to buffer
00966       for(unsigned int i=0; i<types.size(); ++i)
00967         {
00968           offset[0] = offsets[i][index];
00969           count[0] = offsets[i][index+1] - offset[0];
00970           if(count[0] > 0){
00971           err =  H5Sselect_hyperslab(dataspace[i], H5S_SELECT_SET,
00972                                      offset, NULL,
00973                                      count, NULL);
00974           assert(err >= 0);
00975           hid_t memdataspace = H5Screate_simple(1, count, NULL);
00976           assert(memdataspace >= 0);
00977           err = H5Dwrite(dataset[i], types[i], memdataspace, dataspace[i],
00978                          H5P_DEFAULT, buffers[i]);
00979           assert(err >= 0);
00980           H5Sclose(memdataspace);
00981           if(err < 0) { ret = err; goto cleanup;}
00982           }
00983         }
00984     }
00985 
00986   // OK, clean up data structures
00987 
00988  cleanup:
00989   for(unsigned int i=0; i<types.size(); ++i)
00990     {
00991       free(buffers[i]);
00992       H5Sclose(dataspace[i]);
00993       H5Dclose(dataset[i]);
00994     }
00995   return ret;
00996 
00997 }
00998 
00999 template <class T>
01000 int write(HDF5Handle& a_handle, const LevelData<T>& a_data,
01001           const std::string& a_name, const IntVect& outputGhost, const Interval& in_comps)
01002 {
01003   HDF5HeaderData info;
01004   info.m_intvect["ghost"] = a_data.ghostVect();
01005   IntVect og(outputGhost);
01006   og.min(a_data.ghostVect());
01007   info.m_intvect["outputGhost"] = og;
01008   std::string group = a_handle.getGroup();
01009   a_handle.setGroup(group+"/"+a_name+"_attributes");
01010   info.writeToFile(a_handle);
01011   a_handle.setGroup(group);
01012   return write(a_handle, (const BoxLayoutData<T>&)a_data, a_name, og, in_comps);
01013 }
01014 
01015 template <class T>
01016 int read(HDF5Handle& a_handle, LevelData<T>& a_data, const std::string& a_name,
01017          const DisjointBoxLayout& a_layout, const Interval& a_comps, bool a_redefineData)
01018 {
01019   if(a_redefineData)
01020     {
01021       HDF5HeaderData info;
01022       std::string group = a_handle.getGroup();
01023       if(a_handle.setGroup(group+"/"+a_name+"_attributes"))
01024         {
01025           std::string message = "error opening "+a_handle.getGroup()+"/"+a_name ;
01026           MayDay::Warning(message.c_str());
01027           return 1;
01028         }
01029       info.readFromFile(a_handle);
01030       a_handle.setGroup(group);
01031       int ncomp =  info.m_int["comps"];
01032       IntVect ghost = info.m_intvect["ghost"];
01033       if(a_comps.end() > 0 && ncomp < a_comps.end())
01034         {
01035           MayDay::Error("attempt to read component interval that is not available");
01036         }
01037       if(a_comps.size() == 0)
01038         a_data.define(a_layout, ncomp, ghost);
01039       else
01040         a_data.define(a_layout, a_comps.size(), ghost);
01041     }
01042   return read(a_handle, (BoxLayoutData<T>&)a_data, a_name, a_layout, a_comps, false);
01043 
01044 }
01045 
01046 template <class T>
01047 int read(HDF5Handle& a_handle, BoxLayoutData<T>& a_data, const std::string& a_name,
01048          const BoxLayout& a_layout, const Interval& a_comps, bool a_redefineData)
01049 {
01050   int ret = 0; // return value;
01051 
01052   herr_t err;
01053 
01054   char dataname[100];
01055   hsize_t count[1];
01056   hssize_t offset[1];
01057   Vector<Vector<long long> > offsets;
01058 
01059   T dummy;
01060   Vector<hid_t> types;
01061   dataTypes(types, dummy);
01062   Vector<hid_t> dataspace(types.size());
01063   Vector<hid_t> dataset(types.size());
01064   offsets.resize(types.size(), Vector<long long>(a_layout.size() +1));
01065 
01066   //Vector<int> bufferCapacity(types.size(), 500);
01067   //Vector<void*> buffers(types.size(), NULL);
01068   Vector<Vector<char> > buffers(types.size(), 500);
01069 
01070   for(unsigned int i=0; i<types.size(); ++i)
01071     {
01072       sprintf(dataname, "%s:datatype=%i",a_name.c_str(), i);
01073       dataset[i]        = H5Dopen(a_handle.groupID(), dataname);
01074       if(dataset[i] < 0) {MayDay::Warning("dataset open failure"); return dataset[i];}
01075       dataspace[i]      = H5Dget_space(dataset[i]);
01076       if(dataspace[i] < 0) {MayDay::Warning("dataspace open failure"); return dataspace[i];}
01077     }
01078 
01079   hid_t offsetspace, offsetData;
01080   hsize_t flatdims[1];
01081   for(unsigned int i=0; i<types.size(); ++i)
01082     {
01083       flatdims[0] =  offsets[i].size();
01084       sprintf(dataname, "%s:offsets=%i",a_name.c_str(), i);
01085       offsetspace =  H5Screate_simple(1, flatdims, NULL);
01086       assert(offsetspace >= 0);
01087       offsetData  =   H5Dopen(a_handle.groupID(), dataname);
01088       assert(offsetData >= 0);
01089       hid_t memdataspace = H5Screate_simple(1, flatdims, NULL);
01090       assert(memdataspace >= 0);
01091       err = H5Dread(offsetData, H5T_NATIVE_LLONG, memdataspace, offsetspace,
01092                     H5P_DEFAULT, &(offsets[i][0]));
01093       assert(err >=0);
01094       H5Sclose(memdataspace);
01095       H5Sclose(offsetspace);
01096       H5Dclose(offsetData);
01097     }
01098 
01099   HDF5HeaderData info;
01100   std::string group = a_handle.getGroup();
01101   if(a_handle.setGroup(a_handle.getGroup()+"/"+a_name+"_attributes"))
01102     {
01103       std::string message = "error opening "+a_handle.getGroup()+"/"+a_name ;
01104       MayDay::Warning(message.c_str());
01105       return 1;
01106     }
01107 
01108   info.readFromFile(a_handle);
01109   a_handle.setGroup(group);
01110   int ncomps = info.m_int["comps"];
01111   IntVect outputGhost(IntVect::Zero); // backwards file compatible mode.
01112   if(info.m_intvect.find("outputGhost") != info.m_intvect.end())
01113     {
01114       outputGhost = info.m_intvect["outputGhost"];
01115     }
01116   if(ncomps <= 0){
01117     MayDay::Warning("ncomps <= 0 in read");
01118     return ncomps;
01119   }
01120 
01121   if(a_redefineData){
01122     if(a_comps.size() != 0){
01123       a_data.define(a_layout, a_comps.size());
01124     } else {
01125       a_data.define(a_layout, ncomps);
01126     }
01127   }
01128 
01129   Interval comps(0, ncomps-1);
01130   //huh?
01131   //  if(a_comps.size() != 0)  comps = Interval(0, a_comps.size());
01132 
01133   //  getOffsets(offsets, a_data, types.size(), comps);
01134 
01135   Vector<size_t> type_size(types.size());
01136   for(unsigned int i=0; i<types.size(); ++i)
01137     {
01138       type_size[i] = H5Tget_size(types[i]);
01139 
01140     }
01141 
01142   Vector<int> thisSize(types.size());
01143   for(DataIterator it = a_data.dataIterator(); it.ok(); ++it)
01144     {
01145       T& data = a_data[it()];
01146       unsigned int index = a_data.boxLayout().index(it());
01147       Box box = a_data.box(it());
01148 
01149       for(unsigned int i=0; i<types.size(); ++i)
01150         {
01151           if(a_comps.size() == 0){
01152             offset[0] = offsets[i][index];
01153             count[0] = offsets[i][index+1] - offset[0];
01154           } else {
01155             offset[0] = offsets[i][index] + box.numPts()*a_comps.begin();
01156             count[0]  = a_comps.size() * box.numPts();
01157           }
01158           if(count[0] > 0)
01159           {
01160             int size = count[0] * type_size[i];
01161             while(size > buffers[i].size())
01162             {
01163               buffers[i].resize(2*buffers[i].size());
01164             }
01165 
01166             err =  H5Sselect_hyperslab(dataspace[i], H5S_SELECT_SET,
01167                                        offset, NULL,
01168                                        count, NULL);
01169             assert(err >= 0);
01170             hid_t memdataspace = H5Screate_simple(1, count, NULL);
01171             assert(memdataspace >= 0);
01172             err = H5Dread(dataset[i], types[i], memdataspace, dataspace[i],
01173                           H5P_DEFAULT, &(buffers[i][0]));
01174             assert(err >= 0);
01175             H5Sclose(memdataspace);
01176             if(err < 0) { ret = err; goto cleanup;}
01177           }
01178         }
01179       box.grow(outputGhost);
01180       read(data, buffers,  box, comps);
01181     }
01182 
01183  cleanup:
01184   for(unsigned int i=0; i<types.size(); ++i)
01185     {
01186       // free(buffers[i]);
01187       H5Sclose(dataspace[i]);
01188       H5Dclose(dataset[i]);
01189     }
01190   return ret;
01191 }
01192 
01193 template <class T>
01194 int writeLevel(HDF5Handle& a_handle,
01195                const int&  a_level,
01196                const LevelData<T>& a_data,
01197                const Real& a_dx,
01198                const Real& a_dt,
01199                const Real& a_time,
01200                const Box&  a_domain,
01201                const int&  a_refRatio,
01202                const IntVect& outputGhost,
01203                const Interval& comps)
01204 {
01205   int error;
01206   char levelName[10];
01207   std::string currentGroup = a_handle.getGroup();
01208   sprintf(levelName, "/level_%i",a_level);
01209   error = a_handle.setGroup(currentGroup + levelName);
01210   if(error != 0) return 1;
01211 
01212   HDF5HeaderData meta;
01213   meta.m_real["dx"] = a_dx;
01214   meta.m_real["dt"] = a_dt;
01215   meta.m_real["time"] = a_time;
01216   meta.m_box["prob_domain"] = a_domain;
01217   meta.m_int["ref_ratio"] = a_refRatio;
01218 
01219   error = meta.writeToFile(a_handle);
01220   if(error != 0) return 2;
01221 
01222   error = write(a_handle, a_data.boxLayout());
01223   if(error != 0) return 3;
01224 
01225   error = write(a_handle, a_data, "data", outputGhost, comps);
01226   if(error != 0) return 4;
01227 
01228   a_handle.setGroup(currentGroup);
01229 
01230   return 0;
01231 }
01232 
01233 template <class T>
01234 int readLevel(HDF5Handle&   a_handle,
01235               const int&    a_level,
01236               LevelData<T>& a_data,
01237               Real& a_dx,
01238               Real& a_dt,
01239               Real& a_time,
01240               Box&  a_domain,
01241               int&  a_refRatio,
01242               const Interval&   a_comps,
01243               bool  setGhost)
01244 {
01245   HDF5HeaderData header;
01246   header.readFromFile(a_handle);
01247   //unused
01248   // int nComp = header.m_int["num_components"];
01249 
01250   int error;
01251   char levelName[10];
01252   std::string currentGroup = a_handle.getGroup();
01253   sprintf(levelName, "/level_%i",a_level);
01254   error = a_handle.setGroup(currentGroup + levelName);
01255   if(error != 0) return 1;
01256 
01257   HDF5HeaderData meta;
01258   error = meta.readFromFile(a_handle);
01259   if(error != 0) return 2;
01260   a_dx       = meta.m_real["dx"];
01261   a_dt       = meta.m_real["dt"];
01262   a_time     = meta.m_real["time"];
01263   a_domain   = meta.m_box["prob_domain"];
01264   a_refRatio = meta.m_int["ref_ratio"];
01265 
01266   Vector<Box> boxes;
01267   error = read(a_handle, boxes);
01268   Vector<int> procIDs;
01269   LoadBalance(procIDs, boxes);
01270 
01271   DisjointBoxLayout layout(boxes, procIDs);
01272 
01273   layout.close();
01274   if(error != 0) return 3;
01275 
01276     error = read(a_handle, a_data, "data", layout, a_comps);
01277 
01278   if(error != 0) return 4;
01279 
01280   a_handle.setGroup(currentGroup);
01281 
01282   return 0;
01283 }
01284 
01285 #else // HDF5
01286 
01287 // this is the only thing needed when HDF is not used
01288 #define HOFFSET(S,M)    (offsetof(S,M))
01289 
01290 #endif // HDF5
01291 
01292 #endif  // CH_HDF5_H

Generated on Wed Jan 19 17:51:23 2005 for Chombo&INSwithParticles by doxygen1.2.16