00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011 #ifndef _CH_HDF5_H_
00012 #define _CH_HDF5_H_
00013
00014 #define CHOFFSET(object, member) (int)((char*)&(object.member) - (char*)&object)
00015
00016 #ifdef CH_USE_HDF5 // if you don't have CH_USE_HDF5, then this file is useless
00017
00018 #include <iostream>
00019 using std::cout;
00020 using std::endl;
00021
00022 #ifdef CH_MPI
00023 #include <mpi.h>
00024 #endif
00025
00026 #include "LevelData.H"
00027 #include "HDF5Portable.H"
00028
00029 #undef inline
00030 #include <string>
00031 #include <map>
00032 #include "RealVect.H"
00033 #include "CH_Timer.H"
00034 #include "LoadBalance.H"
00035 #include "LayoutIterator.H"
00036 #include "Vector.H"
00037 #include "memtrack.H"
00038 #include "FluxBox.H"
00039
00040 #ifdef CH_MULTIDIM
00041 #include "BoxTools_ExternC_Mangler.H"
00042 #endif
00043 #include "NamespaceHeader.H"
00044
00045
00046 template <class T>
00047 void read(T& item, Vector<Vector<char> >& a_allocatedBuffers, const Box& box,
00048 const Interval& comps)
00049 {
00050 Vector<void*> b(a_allocatedBuffers.size());
00051 for(int i=0; i<b.size(); ++i) b[i]= &(a_allocatedBuffers[i][0]);
00052 read(item, b, box, comps);
00053 }
00054
00055 using std::map;
00056
00057 class HDF5Handle;
00058
00059
00060
00061
00063
00074 template <class T>
00075 int writeLevel(HDF5Handle& a_handle,
00076 const int& a_level,
00077 const LevelData<T>& a_data,
00078 const Real& a_dx,
00079 const Real& a_dt,
00080 const Real& a_time,
00081 const Box& a_domain,
00082 const int& a_refRatio,
00083 const IntVect& outputGhost = IntVect::Zero,
00084 const Interval& comps = Interval());
00085
00086 template <class T>
00087 int readLevel(HDF5Handle& a_handle,
00088 const int& a_level,
00089 LevelData<T>& a_data,
00090 Real& a_dx,
00091 Real& a_dt,
00092 Real& a_time,
00093 Box& a_domain,
00094 int& a_refRatio,
00095 const Interval& a_comps = Interval(),
00096 bool setGhost = false);
00097
00098
00099
00100
00101
00103
00110 int write(HDF5Handle& a_handle,
00111 const BoxLayout& a_layout,
00112 const std::string& name = "boxes");
00113
00115
00120 template <class T>
00121 int write(HDF5Handle& a_handle,
00122 const BoxLayoutData<T>& a_data,
00123 const std::string& a_name,
00124 IntVect outputGhost = IntVect::Zero,
00125 const Interval& comps = Interval(),
00126 bool newForm = false);
00127
00129
00136 template <class T>
00137 int write(HDF5Handle& a_handle,
00138 const LevelData<T>& a_data,
00139 const std::string& a_name,
00140 const IntVect& outputGhost = IntVect::Zero,
00141 const Interval& comps = Interval());
00142
00144
00180 int read(HDF5Handle& a_handle,
00181 Vector<Box>& boxes,
00182 const std::string& name = "boxes");
00183
00185
00192 int readBoxes(HDF5Handle& a_handle,
00193 Vector<Vector<Box> >& boxes);
00194
00196
00204 int readFArrayBox(HDF5Handle& a_handle,
00205 FArrayBox& a_fab,
00206 int a_level,
00207 int a_boxNumber,
00208 const Interval& a_components,
00209 const std::string& a_dataName = "data" );
00210
00212
00218 template <class T>
00219 int read(HDF5Handle& a_handle,
00220 BoxLayoutData<T>& a_data,
00221 const std::string& a_name,
00222 const BoxLayout& a_layout,
00223 const Interval& a_comps = Interval(),
00224 bool redefineData = true);
00225
00227
00248 template <class T>
00249 int read(HDF5Handle& a_handle,
00250 LevelData<T>& a_data,
00251 const std::string& a_name,
00252 const DisjointBoxLayout& a_layout,
00253 const Interval& a_comps = Interval(),
00254 bool redefineData = true);
00255
00257
00267 class HDF5Handle
00268 {
00269 public:
00271
00285 enum mode {CREATE, OPEN_RDONLY, OPEN_RDWR};
00286
00288
00290
00294 HDF5Handle();
00295
00297
00305 HDF5Handle(const std::string& a_filename, mode a_mode);
00306
00307 ~HDF5Handle();
00308
00310
00312
00332 int open(const std::string& a_filename, mode a_mode);
00333
00335
00338 bool isOpen() const;
00339
00341
00346 void close();
00347
00349
00351
00354 void setGroupToLevel(int a_level);
00355
00357
00364 int setGroup(const std::string& groupAbsPath);
00365
00367
00373 int pushGroup( const std::string& grp );
00374
00376
00383 int popGroup();
00384
00386
00392 const std::string& getGroup() const;
00393
00394 const hid_t& fileID() const;
00395 const hid_t& groupID() const;
00396 static hid_t box_id;
00397 static hid_t intvect_id;
00398 static hid_t realvect_id;
00399 static map<std::string, std::string> groups;
00400
00401 private:
00402
00403 HDF5Handle(const HDF5Handle&);
00404 HDF5Handle& operator=(const HDF5Handle&);
00405
00406 hid_t m_fileID;
00407 hid_t m_currentGroupID;
00408 bool m_isOpen;
00409 std::string m_filename;
00410 std::string m_group;
00411 int m_level;
00412
00413
00414 static bool initialized;
00415 static void initialize();
00416
00417 };
00418
00420
00462 class HDF5HeaderData
00463 {
00464 public:
00465
00467
00473 int writeToFile(HDF5Handle& file) const;
00474
00476
00484 int readFromFile(HDF5Handle& file);
00485
00487 void clear();
00488
00490 map<std::string, Real> m_real;
00491
00493 map<std::string, int> m_int;
00494
00496 map<std::string, std::string> m_string;
00497
00499 map<std::string, IntVect> m_intvect;
00500
00502 map<std::string, Box> m_box;
00503
00505 map<std::string, RealVect> m_realvect;
00506
00507
00508
00509 int writeToLocation(hid_t loc_id) const;
00510 int readFromLocation(hid_t loc_id);
00511
00513 void dump() const;
00514
00515 private:
00516 static herr_t attributeScan(hid_t loc_id, const char *name, void *opdata);
00517 };
00518
00519 extern "C"{
00520 herr_t HDF5HeaderDataattributeScan(hid_t loc_id, const char *name, void *opdata);
00521 }
00522
00523 std::ostream& operator<<(std::ostream& os, const HDF5HeaderData& data);
00524
00525
00526
00527
00528
00529
00530
00531 #if ( H5_VERS_MAJOR == 1 && H5_VERS_MINOR > 6 )
00532 typedef hsize_t ch_offset_t;
00533 #else
00534 #if ( H5_VERS_MAJOR == 1 && H5_VERS_MINOR == 6 && H5_VERS_RELEASE >= 4 )
00535 typedef hsize_t ch_offset_t;
00536 #else
00537 typedef hssize_t ch_offset_t;
00538 #endif
00539 #endif
00540
00541
00542 template<class T>
00543 hid_t H5Type(const T* dummy);
00544
00545 template< >
00546 hid_t H5Type(const int* dummy);
00547
00548 template< >
00549 hid_t H5Type(const long long* dummy);
00550
00551 template< >
00552 hid_t H5Type(const float* dummy);
00553
00554 template< >
00555 hid_t H5Type(const double* dummy);
00556
00557 template< >
00558 hid_t H5Type(const Box* dummy);
00559
00560 template< >
00561 hid_t H5Type(const RealVect* dummy);
00562
00563 template< >
00564 hid_t H5Type(const IntVect* dummy);
00565
00566 template<class T>
00567 hid_t H5Type(const T* dummy)
00568 {
00569
00570 MayDay::Error(" H5Type(const T* dummy)");
00571 return -4;
00572 }
00573
00574
00575 void createData(hid_t& a_dataset,
00576 hid_t& a_dataspace,
00577 HDF5Handle& handle,
00578 const std::string& name,
00579 hid_t type,
00580 hsize_t size);
00581
00582 template <class T>
00583 void createDataset(hid_t& a_dataset,
00584 hid_t& a_dataspace,
00585 HDF5Handle& handle,
00586 const std::string& name,
00587 const T* dummy,
00588 hsize_t size)
00589 {
00590 createData(a_dataset, a_dataspace, handle, name, H5Type(dummy), size);
00591
00592 }
00593
00594 void writeDataset(hid_t a_dataset,
00595 hid_t a_dataspace,
00596 const void* start,
00597 ch_offset_t off,
00598 hsize_t count);
00599
00600 void readDataset(hid_t a_dataset,
00601 hid_t a_dataspace,
00602 void* start,
00603 ch_offset_t off,
00604 hsize_t count);
00605
00606
00607
00608 struct OffsetBuffer
00609 {
00610 Vector<int> index;
00611 Vector<Vector<int> > offsets;
00612 void operator=(const OffsetBuffer& rhs);
00613 };
00614
00615 ostream& operator<<(ostream& os, const OffsetBuffer& ob);
00616
00617
00618 #include "NamespaceFooter.H"
00619
00620 #include "BaseNamespaceHeader.H"
00621
00622 #include "NamespaceVar.H"
00623
00624
00625 template < >
00626 int linearSize(const CH_XDIR::OffsetBuffer& a_input);
00627
00628
00629 template < >
00630 void linearIn(CH_XDIR::OffsetBuffer& a_outputT, const void* const a_inBuf);
00631
00632
00633 template < >
00634 void linearOut(void* const a_outBuf, const CH_XDIR::OffsetBuffer& a_inputT);
00635
00636 template < > int linearSize(const Vector<CH_XDIR::OffsetBuffer>& a_input);
00637 template < > void linearIn(Vector<CH_XDIR::OffsetBuffer>& a_outputT, const void* const inBuf);
00638 template < > void linearOut(void* const a_outBuf, const Vector<CH_XDIR::OffsetBuffer>& a_inputT);
00639
00640
00641 #include "BaseNamespaceFooter.H"
00642 #include "NamespaceHeader.H"
00643
00644
00645
00646 template <>
00647 inline void dataTypes(Vector<hid_t>& a_types, const BaseFab<int>& dummy)
00648 {
00649 a_types.resize(1);
00650 a_types[0] = H5T_NATIVE_INT;
00651 }
00652
00653 template <>
00654 inline void dataTypes(Vector<hid_t>& a_types, const BaseFab<char>& dummy)
00655 {
00656 a_types.resize(1);
00657 a_types[0] = H5T_NATIVE_CHAR;
00658 }
00659
00660
00661
00662
00663 template <>
00664 inline void dataTypes(Vector<hid_t>& a_types, const FArrayBox& dummy)
00665 { a_types.resize(1); a_types[0] = H5T_NATIVE_REAL;}
00666
00667 template <>
00668 inline void dataTypes(Vector<hid_t>& a_types, const FluxBox& dummy)
00669 { a_types.resize(1); a_types[0] = H5T_NATIVE_REAL;}
00670
00671
00672 template <>
00673 inline void dataSize(const BaseFab<int>& item, Vector<int>& a_sizes,
00674 const Box& box, const Interval& comps)
00675 {
00676 a_sizes[0] = box.numPts() * comps.size();
00677 }
00678
00679 template <>
00680 inline void dataSize(const BaseFab<char>& item, Vector<int>& a_sizes,
00681 const Box& box, const Interval& comps)
00682 {
00683 a_sizes[0] = box.numPts() * comps.size();
00684 }
00685
00686 template <>
00687 inline void dataSize(const FArrayBox& item, Vector<int>& a_sizes,
00688 const Box& box, const Interval& comps)
00689 {
00690 a_sizes[0] = box.numPts() * comps.size();
00691 }
00692
00693 template <>
00694 inline void dataSize(const FluxBox& item, Vector<int>& a_sizes,
00695 const Box& box, const Interval& comps)
00696 {
00697 int& t = a_sizes[0];
00698 t = 0;
00699 for (int dir =0; dir<CH_SPACEDIM; dir++)
00700 {
00701 Box edgeBox(surroundingNodes(box,dir));
00702 t += edgeBox.numPts()*comps.size();
00703 }
00704 }
00705
00706 template <>
00707 inline const char* name(const FArrayBox& a_dummySpecializationArg)
00708 {
00709
00710
00711 const char* name = "FArrayBox";
00712 return name;
00713 }
00714
00715 template <>
00716 inline const char* name(const BaseFab<int>& a_dummySpecializationArg)
00717 {
00718
00719
00720 const char* name = "BaseFab<int>";
00721 return name;
00722 }
00723
00724 template <>
00725 inline const char* name(const BaseFab<char>& a_dummySpecializationArg)
00726 {
00727
00728
00729 const char* name = "BaseFab<char>";
00730 return name;
00731 }
00732
00733
00734
00735
00736 template <class T>
00737 inline void dataTypes(Vector<hid_t>& a_types, const T& dummy)
00738 { a_types.resize(1); a_types[0] = H5T_NATIVE_CHAR;}
00739
00740 template <class T>
00741 inline void dataSize(const T& item, Vector<int>& a_sizes,
00742 const Box& box, const Interval& comps)
00743 {
00744 a_sizes[0] = item.size(box, comps);
00745 }
00746
00747 template <class T>
00748 inline void write(const T& item, Vector<void*>& a_allocatedBuffers,
00749 const Box& box, const Interval& comps)
00750 {
00751 item.linearOut(a_allocatedBuffers[0], box, comps);
00752 }
00753
00754 template <class T>
00755 inline void read(T& item, Vector<void*>& a_allocatedBuffers,
00756 const Box& box, const Interval& comps)
00757 {
00758 item.linearIn(a_allocatedBuffers[0], box, comps);
00759 }
00760
00761 template <class T>
00762 inline const char* name(const T& a_dummySpecializationArg)
00763 {
00764 static const char* name = "unknown";
00765 return name;
00766 }
00767
00768 template <class T>
00769 void getOffsets(Vector<Vector<long long> >& offsets, const BoxLayoutData<T>& a_data,
00770 int types, const Interval& comps, const IntVect& outputGhost)
00771 {
00772 const BoxLayout& layout = a_data.boxLayout();
00773 offsets.resize(types, Vector<long long>(layout.size()+1));
00774
00775 for(int t=0; t<types; t++) offsets[t][0] = 0;
00776 Vector<int> thisSize(types);
00777 if(T::preAllocatable()==0)
00778 {
00779 T dummy;
00780 unsigned int index = 1;
00781 for(LayoutIterator it(layout.layoutIterator()); it.ok(); ++it)
00782 {
00783 Box region = layout[it()];
00784 region.grow(outputGhost);
00785 dataSize(dummy, thisSize, region, comps);
00786 for(unsigned int i=0; i<thisSize.size(); ++i)
00787 {
00788
00789 offsets[i][index] = offsets[i][index-1] + thisSize[i];
00790 }
00791 ++index;
00792 }
00793 }
00794 else
00795 {
00796 OffsetBuffer buff;
00797
00798 for(DataIterator dit(a_data.dataIterator()); dit.ok(); ++dit)
00799 {
00800 int index = a_data.boxLayout().index(dit());
00801
00802 buff.index.push_back(index);
00803 Box region = layout[dit()];
00804 region.grow(outputGhost);
00805 dataSize(a_data[dit()], thisSize, region, comps);
00806 buff.offsets.push_back(thisSize);
00807 }
00808 Vector<OffsetBuffer> gathering(numProc());
00809 gather(gathering, buff, uniqueProc(SerialTask::compute));
00810 broadcast(gathering, uniqueProc(SerialTask::compute));
00811
00812 for(int i=0; i<numProc(); ++i)
00813 {
00814 OffsetBuffer& offbuf = gathering[i];
00815 for(int num=0; num<offbuf.index.size(); num++)
00816 {
00817 int index = offbuf.index[num];
00818 for(unsigned int j=0; j<types; ++j)
00819 {
00820
00821 offsets[j][index+1] = offbuf.offsets[num][j];
00822 }
00823 }
00824 }
00825 for(int i=0; i<layout.size(); i++)
00826 {
00827 for(unsigned int j=0; j<types; ++j)
00828 {
00829
00830 offsets[j][i+1] += offsets[j][i];
00831 }
00832 }
00833 }
00834
00835
00836 }
00837
00838
00839
00840
00841
00842 template <class T>
00843 int write(HDF5Handle& a_handle, const BoxLayoutData<T>& a_data,
00844 const std::string& a_name, IntVect outputGhost,
00845 const Interval& in_comps, bool newForm)
00846 {
00847 CH_TIME("write Level");
00848 int ret = 0;
00849
00850 Interval comps(in_comps);
00851 if( comps.size() == 0) comps = a_data.interval();
00852 T dummy;
00853 Vector<hid_t> types;
00854 dataTypes(types, dummy);
00855
00856 if(newForm && memcmp(a_name.c_str(), "M", 1)==0)
00857 {
00858 std::string currentGroup = a_handle.getGroup();
00859 a_handle.setGroup("/");
00860 HDF5HeaderData info;
00861 info.readFromFile(a_handle);
00862
00863 info.clear();
00864 a_handle.setGroup("/" + HDF5Handle::groups[a_name] + "CenteredComponents");
00865 info.readFromFile(a_handle);
00866 int nc = info.m_int["Num"+a_name];
00867 if(nc == 0){
00868 char cname[40];
00869 info.m_int["Num"+a_name] = comps.size();
00870 nc = comps.size();
00871 for(int i=0; i<nc; ++i){
00872 sprintf(cname, "Component%i", i);
00873 info.m_string[cname] = cname;
00874 }
00875 info.writeToFile(a_handle);
00876 }
00877 a_handle.setGroup(currentGroup);
00878 CH_assert(nc == comps.size());
00879 }
00880
00881 Vector<Vector<long long> > offsets;
00882 Vector<long long> bufferCapacity(types.size(), 1);
00883 Vector<void*> buffers(types.size(), NULL);
00884
00885 getOffsets(offsets, a_data, types.size(), comps, outputGhost);
00886
00887
00888 hsize_t flatdims[1];
00889 char dataname[100];
00890 Vector<hid_t> dataspace(types.size());
00891 Vector<hid_t> dataset(types.size());
00892
00893 herr_t err;
00894 hsize_t count[1];
00895 ch_offset_t offset[1];
00896 CH_assert(!(newForm && types.size() != 1));
00897
00898 for(unsigned int i=0; i<types.size(); ++i)
00899 {
00900 flatdims[0] = offsets[i][offsets[i].size()-1];
00901 if(newForm){
00902 if(memcmp(a_name.c_str(), "M", 1)==0){
00903 strcpy(dataname, "Mask");
00904 }else{
00905 sprintf(dataname, "%sRegular", a_name.c_str());
00906 }
00907 }else {
00908 sprintf(dataname, "%s:datatype=%i",a_name.c_str(), i);
00909 }
00910 dataspace[i] = H5Screate_simple(1, flatdims, NULL);
00911 CH_assert(dataspace[i] >=0);
00912 dataset[i] = H5Dcreate(a_handle.groupID(), dataname,
00913 types[i],
00914 dataspace[i], H5P_DEFAULT);
00915 CH_assert(dataset[i] >= 0);
00916 }
00917
00918 hid_t offsetspace, offsetData;
00919 for(unsigned int i=0; i<types.size(); ++i)
00920 {
00921 flatdims[0] = offsets[i].size();
00922 if(newForm){
00923 sprintf(dataname, "%sOffsets",a_name.c_str());
00924 } else {
00925 sprintf(dataname, "%s:offsets=%i",a_name.c_str(), i);
00926 }
00927 offsetspace = H5Screate_simple(1, flatdims, NULL);
00928 CH_assert(offsetspace >= 0);
00929 offsetData = H5Dcreate(a_handle.groupID(), dataname,
00930 H5T_NATIVE_LLONG, offsetspace, H5P_DEFAULT);
00931 CH_assert(offsetData >= 0);
00932 if(procID() == 0)
00933 {
00934 hid_t memdataspace = H5Screate_simple(1, flatdims, NULL);
00935 CH_assert(memdataspace >= 0);
00936 err = H5Dwrite(offsetData, H5T_NATIVE_LLONG, memdataspace, offsetspace,
00937 H5P_DEFAULT, &(offsets[i][0]));
00938 CH_assert(err >= 0);
00939 H5Sclose(memdataspace);
00940 }
00941 H5Sclose(offsetspace);
00942 H5Dclose(offsetData);
00943 }
00944
00945
00946 if(!newForm){
00947 HDF5HeaderData info;
00948 info.m_int["comps"] = comps.size();
00949 info.m_string["objectType"] = name(dummy);
00950 std::string group = a_handle.getGroup();
00951 a_handle.setGroup(group+"/"+a_name+"_attributes");
00952 info.writeToFile(a_handle);
00953 a_handle.setGroup(group);
00954 }
00955
00956
00957
00958
00959 Vector<size_t> type_size(types.size());
00960 for(unsigned int i=0; i<types.size(); ++i)
00961 {
00962 type_size[i] = H5Tget_size(types[i]);
00963 }
00964
00965 Vector<int> thisSize(types.size());
00966
00967
00968
00969
00970
00971 for(int i=0; i<offsets[0].size(); i++)
00972 {
00973
00974 }
00975
00976 for(DataIterator it = a_data.dataIterator(); it.ok(); ++it)
00977 {
00978 unsigned int index = a_data.boxLayout().index(it());
00979 for(unsigned int i=0; i<types.size(); ++i)
00980 {
00981 long long size = (offsets[i][index+1] - offsets[i][index])
00982 * type_size[i];
00983
00984 CH_assert(size >= 0);
00985 if(size > bufferCapacity[i])
00986 {
00987 bufferCapacity[i] = size;
00988 }
00989 }
00990 }
00991
00992 for(unsigned int i=0; i<types.size(); ++i)
00993 {
00994 buffers[i] = mallocMT(bufferCapacity[i]);
00995 if(buffers[i] == NULL) {
00996 pout() << " i=" << i
00997 << " types.size() = " << types.size()
00998 << " bufferCapacity[i] = " << (int)bufferCapacity[i]
00999 << endl;
01000 MayDay::Error("memory error in buffer allocation write");
01001 }
01002 }
01003
01004
01005
01006
01007 #ifdef TRY_MPI_COLLECTIVES_
01008 hid_t DXPL = H5Pcreate(H5P_DATASET_XFER);
01009 H5Pset_dxpl_mpio(DXPL, H5FD_MPIO_COLLECTIVE);
01010 #endif
01011 for(DataIterator it = a_data.dataIterator(); it.ok(); ++it)
01012 {
01013 const T& data = a_data[it()];
01014 unsigned int index = a_data.boxLayout().index(it());
01015 Box box = a_data.box(it());
01016 box.grow(outputGhost);
01017 write(data, buffers, box, comps);
01018 for(unsigned int i=0; i<types.size(); ++i)
01019 {
01020 offset[0] = offsets[i][index];
01021 count[0] = offsets[i][index+1] - offset[0];
01022 if(count[0] > 0){
01023 err = H5Sselect_hyperslab(dataspace[i], H5S_SELECT_SET,
01024 offset, NULL,
01025 count, NULL);
01026 CH_assert(err >= 0);
01027 hid_t memdataspace = H5Screate_simple(1, count, NULL);
01028 CH_assert(memdataspace >= 0);
01029 #ifdef TRY_MPI_COLLECTIVES_
01030 err = H5Dwrite(dataset[i], types[i], memdataspace, dataspace[i],
01031 DXPL, buffers[i]);
01032 #else
01033 err = H5Dwrite(dataset[i], types[i], memdataspace, dataspace[i],
01034 H5P_DEFAULT, buffers[i]);
01035 #endif
01036 CH_assert(err >= 0);
01037 H5Sclose(memdataspace);
01038 if(err < 0) { ret = err; goto cleanup;}
01039 }
01040 }
01041 }
01042 #ifdef TRY_MPI_COLLECTIVES_
01043 H5Pclose(DXPL);
01044 #endif
01045
01046
01047
01048 cleanup:
01049 for(unsigned int i=0; i<types.size(); ++i)
01050 {
01051 freeMT(buffers[i]);
01052 H5Sclose(dataspace[i]);
01053 H5Dclose(dataset[i]);
01054 }
01055 return ret;
01056
01057 }
01058
01059 template <class T>
01060 int write(HDF5Handle& a_handle, const LevelData<T>& a_data,
01061 const std::string& a_name, const IntVect& outputGhost, const Interval& in_comps)
01062 {
01063 HDF5HeaderData info;
01064 info.m_intvect["ghost"] = a_data.ghostVect();
01065 IntVect og(outputGhost);
01066 og.min(a_data.ghostVect());
01067 info.m_intvect["outputGhost"] = og;
01068 std::string group = a_handle.getGroup();
01069 a_handle.setGroup(group+"/"+a_name+"_attributes");
01070 info.writeToFile(a_handle);
01071 a_handle.setGroup(group);
01072 return write(a_handle, (const BoxLayoutData<T>&)a_data, a_name, og, in_comps);
01073 }
01074
01075 template <class T>
01076 int read(HDF5Handle& a_handle, LevelData<T>& a_data, const std::string& a_name,
01077 const DisjointBoxLayout& a_layout, const Interval& a_comps, bool a_redefineData)
01078 {
01079 if(a_redefineData)
01080 {
01081 HDF5HeaderData info;
01082 std::string group = a_handle.getGroup();
01083 if(a_handle.setGroup(group+"/"+a_name+"_attributes"))
01084 {
01085 std::string message = "error opening "
01086 +a_handle.getGroup()+"/"+a_name+"_attributes" ;
01087 MayDay::Warning(message.c_str());
01088 return 1;
01089 }
01090 info.readFromFile(a_handle);
01091 a_handle.setGroup(group);
01092 int ncomp = info.m_int["comps"];
01093 IntVect ghost = info.m_intvect["ghost"];
01094 if(a_comps.end() > 0 && ncomp < a_comps.end())
01095 {
01096 MayDay::Error("attempt to read component interval that is not available");
01097 }
01098 if(a_comps.size() == 0)
01099 a_data.define(a_layout, ncomp, ghost);
01100 else
01101 a_data.define(a_layout, a_comps.size(), ghost);
01102 }
01103 return read(a_handle, (BoxLayoutData<T>&)a_data, a_name, a_layout, a_comps, false);
01104
01105 }
01106
01107 template <class T>
01108 int read(HDF5Handle& a_handle, BoxLayoutData<T>& a_data, const std::string& a_name,
01109 const BoxLayout& a_layout, const Interval& a_comps, bool a_redefineData)
01110 {
01111 int ret = 0;
01112
01113 herr_t err;
01114
01115 char dataname[100];
01116 hsize_t count[1];
01117 ch_offset_t offset[1];
01118 Vector<Vector<long long> > offsets;
01119
01120 T dummy;
01121 Vector<hid_t> types;
01122 dataTypes(types, dummy);
01123 Vector<hid_t> dataspace(types.size());
01124 Vector<hid_t> dataset(types.size());
01125 offsets.resize(types.size(), Vector<long long>(a_layout.size() +1));
01126
01127
01128
01129 Vector<Vector<char> > buffers(types.size(), 500);
01130
01131 for(unsigned int i=0; i<types.size(); ++i)
01132 {
01133 sprintf(dataname, "%s:datatype=%i",a_name.c_str(), i);
01134 dataset[i] = H5Dopen(a_handle.groupID(), dataname);
01135 if(dataset[i] < 0) {MayDay::Warning("dataset open failure"); return dataset[i];}
01136 dataspace[i] = H5Dget_space(dataset[i]);
01137 if(dataspace[i] < 0) {MayDay::Warning("dataspace open failure"); return dataspace[i];}
01138 }
01139
01140 hid_t offsetspace, offsetData;
01141 hsize_t flatdims[1];
01142 for(unsigned int i=0; i<types.size(); ++i)
01143 {
01144 flatdims[0] = offsets[i].size();
01145 sprintf(dataname, "%s:offsets=%i",a_name.c_str(), i);
01146 offsetspace = H5Screate_simple(1, flatdims, NULL);
01147 CH_assert(offsetspace >= 0);
01148 offsetData = H5Dopen(a_handle.groupID(), dataname);
01149 CH_assert(offsetData >= 0);
01150 hid_t memdataspace = H5Screate_simple(1, flatdims, NULL);
01151 CH_assert(memdataspace >= 0);
01152 err = H5Dread(offsetData, H5T_NATIVE_LLONG, memdataspace, offsetspace,
01153 H5P_DEFAULT, &(offsets[i][0]));
01154 CH_assert(err >=0);
01155 H5Sclose(memdataspace);
01156 H5Sclose(offsetspace);
01157 H5Dclose(offsetData);
01158 }
01159
01160 HDF5HeaderData info;
01161 std::string group = a_handle.getGroup();
01162 if(a_handle.setGroup(a_handle.getGroup()+"/"+a_name+"_attributes"))
01163 {
01164 std::string message = "error opening "+a_handle.getGroup()+"/"+a_name ;
01165 MayDay::Warning(message.c_str());
01166 return 1;
01167 }
01168
01169 info.readFromFile(a_handle);
01170 a_handle.setGroup(group);
01171 int ncomps = info.m_int["comps"];
01172 IntVect outputGhost(IntVect::Zero);
01173 if(info.m_intvect.find("outputGhost") != info.m_intvect.end())
01174 {
01175 outputGhost = info.m_intvect["outputGhost"];
01176 }
01177 if(ncomps <= 0){
01178 MayDay::Warning("ncomps <= 0 in read");
01179 return ncomps;
01180 }
01181
01182 if(a_redefineData){
01183 if(a_comps.size() != 0){
01184 a_data.define(a_layout, a_comps.size());
01185 } else {
01186 a_data.define(a_layout, ncomps);
01187 }
01188 }
01189
01190 Interval comps(0, ncomps-1);
01191
01192
01193
01194
01195
01196 Vector<size_t> type_size(types.size());
01197 for(unsigned int i=0; i<types.size(); ++i)
01198 {
01199 type_size[i] = H5Tget_size(types[i]);
01200
01201 }
01202
01203 Vector<int> thisSize(types.size());
01204 for(DataIterator it = a_data.dataIterator(); it.ok(); ++it)
01205 {
01206 T& data = a_data[it()];
01207 unsigned int index = a_data.boxLayout().index(it());
01208 Box box = a_data.box(it());
01209
01210 for(unsigned int i=0; i<types.size(); ++i)
01211 {
01212
01213
01214 offset[0] = offsets[i][index];
01215 count[0] = offsets[i][index+1] - offset[0];
01216
01217
01218
01219
01220 if(count[0] > 0)
01221 {
01222 int size = count[0] * type_size[i];
01223 while(size > buffers[i].size())
01224 {
01225 buffers[i].resize(2*buffers[i].size());
01226 }
01227
01228 err = H5Sselect_hyperslab(dataspace[i], H5S_SELECT_SET,
01229 offset, NULL,
01230 count, NULL);
01231 CH_assert(err >= 0);
01232 hid_t memdataspace = H5Screate_simple(1, count, NULL);
01233 CH_assert(memdataspace >= 0);
01234 err = H5Dread(dataset[i], types[i], memdataspace, dataspace[i],
01235 H5P_DEFAULT, &(buffers[i][0]));
01236 CH_assert(err >= 0);
01237 H5Sclose(memdataspace);
01238 if(err < 0) { ret = err; goto cleanup;}
01239 }
01240 }
01241 box.grow(outputGhost);
01242 read(data, buffers, box, comps);
01243 }
01244
01245 cleanup:
01246 for(unsigned int i=0; i<types.size(); ++i)
01247 {
01248
01249 H5Sclose(dataspace[i]);
01250 H5Dclose(dataset[i]);
01251 }
01252 return ret;
01253 }
01254
01255 template <class T>
01256 int writeLevel(HDF5Handle& a_handle,
01257 const int& a_level,
01258 const LevelData<T>& a_data,
01259 const Real& a_dx,
01260 const Real& a_dt,
01261 const Real& a_time,
01262 const Box& a_domain,
01263 const int& a_refRatio,
01264 const IntVect& outputGhost,
01265 const Interval& comps)
01266 {
01267 int error;
01268 char levelName[10];
01269 std::string currentGroup = a_handle.getGroup();
01270 sprintf(levelName, "/level_%i",a_level);
01271 error = a_handle.setGroup(currentGroup + levelName);
01272 if(error != 0) return 1;
01273
01274 HDF5HeaderData meta;
01275 meta.m_real["dx"] = a_dx;
01276 meta.m_real["dt"] = a_dt;
01277 meta.m_real["time"] = a_time;
01278 meta.m_box["prob_domain"] = a_domain;
01279 meta.m_int["ref_ratio"] = a_refRatio;
01280
01281 error = meta.writeToFile(a_handle);
01282 if(error != 0) return 2;
01283
01284 error = write(a_handle, a_data.boxLayout());
01285 if(error != 0) return 3;
01286
01287 error = write(a_handle, a_data, "data", outputGhost, comps);
01288 if(error != 0) return 4;
01289
01290 a_handle.setGroup(currentGroup);
01291
01292 return 0;
01293 }
01294
01295 template <class T>
01296 int readLevel(HDF5Handle& a_handle,
01297 const int& a_level,
01298 LevelData<T>& a_data,
01299 Real& a_dx,
01300 Real& a_dt,
01301 Real& a_time,
01302 Box& a_domain,
01303 int& a_refRatio,
01304 const Interval& a_comps,
01305 bool setGhost)
01306 {
01307 HDF5HeaderData header;
01308 header.readFromFile(a_handle);
01309
01310
01311
01312 int error;
01313 char levelName[10];
01314 std::string currentGroup = a_handle.getGroup();
01315 sprintf(levelName, "/level_%i",a_level);
01316 error = a_handle.setGroup(currentGroup + levelName);
01317 if(error != 0) return 1;
01318
01319 HDF5HeaderData meta;
01320 error = meta.readFromFile(a_handle);
01321 if(error != 0) return 2;
01322 a_dx = meta.m_real["dx"];
01323 a_dt = meta.m_real["dt"];
01324 a_time = meta.m_real["time"];
01325 a_domain = meta.m_box["prob_domain"];
01326 a_refRatio = meta.m_int["ref_ratio"];
01327
01328 Vector<Box> boxes;
01329 error = read(a_handle, boxes);
01330 Vector<int> procIDs;
01331 LoadBalance(procIDs, boxes);
01332
01333 DisjointBoxLayout layout(boxes, procIDs);
01334
01335 layout.close();
01336 if(error != 0) return 3;
01337
01338 error = read(a_handle, a_data, "data", layout, a_comps);
01339
01340 if(error != 0) return 4;
01341
01342 a_handle.setGroup(currentGroup);
01343
01344 return 0;
01345 }
01346
01347 #include "NamespaceFooter.H"
01348
01349 #else // CH_USE_HDF5
01350
01351
01352 #define HOFFSET(S,M) (offsetof(S,M))
01353
01354 #endif // CH_USE_HDF5 not defined
01355 #endif // CH_HDF5_H