00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
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
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
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
00126
00127
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;
00373 std::string m_group;
00374 int m_level;
00375
00376
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
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
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
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
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
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
00612 template < >
00613 int linearSize(const OffsetBuffer& a_input);
00614
00615
00616 template < >
00617 void linearIn(OffsetBuffer& a_outputT, const void* const a_inBuf);
00618
00619
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
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
00644
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
00675
00676 const char* name = "FArrayBox";
00677 return name;
00678 }
00679
00680 template <>
00681 inline const char* name(const BaseFab<int>& a_dummySpecializationArg)
00682 {
00683
00684
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
00693
00694 const char* name = "BaseFab<char>";
00695 return name;
00696 }
00697
00698
00699
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
00740 for(int t=0; t<types; t++) offsets[t][0] = 0;
00741 Vector<int> thisSize(types);
00742 if(T::preAllocatable()==0)
00743 {
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
00754 offsets[i][index] = offsets[i][index-1] + thisSize[i];
00755 }
00756 ++index;
00757 }
00758 }
00759 else
00760 {
00761 OffsetBuffer buff;
00762
00763 for(DataIterator dit(a_data.dataIterator()); dit.ok(); ++dit)
00764 {
00765 int index = a_data.boxLayout().index(dit());
00766
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
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
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
00795 offsets[j][i+1] += offsets[j][i];
00796 }
00797 }
00798 }
00799
00800
00801 }
00802
00803
00804
00805
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;
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);
00847 Vector<void*> buffers(types.size(), NULL);
00848
00849 getOffsets(offsets, a_data, types.size(), comps, outputGhost);
00850
00851
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
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
00921
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
00932
00933
00934
00935 for(int i=0; i<offsets[0].size(); i++)
00936 {
00937
00938 }
00939
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
00948 CH_assert(size >= 0);
00949 if(size > bufferCapacity[i])
00950 {
00951 bufferCapacity[i] = size;
00952 }
00953 }
00954 }
00955
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
00969
00970
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);
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
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;
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
01079
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);
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
01143
01144
01145
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
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
01260
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
01300 #define HOFFSET(S,M) (offsetof(S,M))
01301
01302 #endif // CH_USE_HDF5
01303
01304 #endif // CH_HDF5_H