00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011 #ifndef _BLOCKWRITEI_H_
00012 #define _BLOCKWRITEI_H_
00013
00014 #include "LevelData.H"
00015 #include "HDF5Portable.H"
00016 #include "CH_HDF5.H"
00017 #include <string>
00018 #include <map>
00019 #include "RealVect.H"
00020 #include "CH_Timer.H"
00021 #include "LoadBalance.H"
00022 #include "LayoutIterator.H"
00023 #include "Vector.H"
00024 #include "memtrack.H"
00025 #include "FluxBox.H"
00026 #include "SPMD.H"
00027
00028
00029
00030 template <class T> void
00031 blockLocalOffsets(Vector<long long>& a_localSizes,
00032
00033 long long & a_localTotalSize,
00034 Vector<Box> & a_localBoxes,
00035 const BoxLayoutData<T>& a_data,
00036 const Interval& a_comps,
00037 const IntVect& a_outputGhost)
00038 {
00039 if (!(T::preAllocatable()==0))
00040 {
00041 MayDay::Error("non static preallocatable data not covered yet.");
00042 }
00043
00044 Vector<int> thisSize(1);
00045 const BoxLayout& layout = a_data.boxLayout();
00046 T dummy;
00047 unsigned int curIndex = 0;
00048 DataIterator it(layout.dataIterator());
00049
00050 a_localTotalSize = 0;
00051 a_localSizes.resize(it.size());
00052 a_localBoxes.resize(it.size());
00053 for (it.reset(); it.ok(); ++it)
00054 {
00055 long long curSize = 0;
00056 const Box& curBox = layout[it()];
00057 Box region = curBox;
00058 region.grow(a_outputGhost);
00059 dataSize(dummy, thisSize, region, a_comps);
00060
00061 curSize = thisSize[0];
00062 a_localSizes[curIndex] = curSize;
00063 a_localBoxes[curIndex] = curBox;
00064
00065 a_localTotalSize += thisSize[0];
00066 curIndex += 1;
00067 }
00068 }
00069
00070 template <class T> void
00071 blockWriteToBuffer(void* a_buffer,
00072 const Vector<long long>& a_sizes,
00073 const BoxLayoutData<T>& a_data,
00074 const Interval& a_comps,
00075 const IntVect& a_outputGhost)
00076 {
00077 int* curPtr = (int*)(a_buffer);
00078 int curIndex = 0;
00079 for (DataIterator it = a_data.dataIterator(); it.ok(); ++it)
00080 {
00081 Vector<void*> buffers(1, (void*) curPtr);
00082 const T& data = a_data[it()];
00083
00084 Box box = a_data.box(it());
00085 box.grow(a_outputGhost);
00086 write(data, buffers, box, a_comps);
00087
00088 curPtr += a_sizes[curIndex];
00089 curIndex += 1;
00090 }
00091
00092 }
00093
00094 int
00095 gatherBoxesAndOffsets(long long& a_offsetThisProc,
00096 long long& a_allProcSize,
00097 Vector<long long>& a_globalOffsets,
00098 Vector<Box>& a_globalBoxes,
00099 const Vector<long long>& a_localBoxSizes,
00100 const Vector<Box>& a_localBoxes,
00101 const long long& a_localAllBoxSize)
00102
00103 {
00104 Vector<Vector<Box > > allBoxes;
00105 Vector<Vector<long long> > allBoxSizes;
00106 Vector<long long> allSizes;
00107 int iprocdest = 0;
00108 gather(allBoxes, a_localBoxes, iprocdest);
00109 gather(allBoxSizes, a_localBoxSizes, iprocdest);
00110 gather(allSizes, a_localAllBoxSize, iprocdest);
00111 Vector<long long> offsetsProcs(numProc());
00112 if (procID() == iprocdest)
00113 {
00114 a_allProcSize = 0;
00115 long long numBoxes = 0;
00116 for (int iproc = 0; iproc < numProc(); iproc++)
00117 {
00118 a_allProcSize += allSizes[iproc];
00119 numBoxes += allBoxes[iproc].size();
00120 }
00121 a_globalBoxes. resize(numBoxes);
00122 a_globalOffsets.resize(numBoxes+1);
00123
00124 long long curOffset = 0;
00125 int curIndex = 0;
00126 for (int iproc = 0; iproc < numProc(); iproc++)
00127 {
00128 for (int ivec = 0; ivec < allBoxSizes[iproc].size(); ivec++)
00129 {
00130 if (ivec == 0)
00131 {
00132 offsetsProcs[iproc] = curOffset;
00133 }
00134 long long boxSize = allBoxSizes[iproc][ivec];
00135 Box curBox = allBoxes[iproc][ivec];
00136
00137 a_globalBoxes [curIndex] = curBox;
00138 a_globalOffsets[curIndex] = curOffset;
00139
00140 curIndex += 1;
00141 curOffset += boxSize;
00142 }
00143 }
00144 if (curOffset != a_allProcSize)
00145 {
00146 return -43;
00147 }
00148 a_globalOffsets[curIndex] = curOffset;
00149
00150 }
00151 a_offsetThisProc = offsetsProcs[procID()];
00152 broadcast(a_allProcSize, iprocdest);
00153 broadcast(a_globalOffsets, iprocdest);
00154 broadcast(a_globalBoxes, iprocdest);
00155 return 0;
00156 }
00157
00158 int
00159 blockWriteBufferToFile(HDF5Handle& a_handle,
00160 void* a_buffer,
00161 const std::string& a_name,
00162 Vector<Box>& a_boxes,
00163 Vector<long long>& a_sizes,
00164 const Vector<hid_t>& a_types,
00165 const BoxLayout& a_layout,
00166 const long long& a_thisprocsize)
00167 {
00168
00169 herr_t err;
00170
00171 long long offsetthisproc, sumprocsize;
00172 Vector<Box> globalBoxes;
00173 Vector<long long> globalOffsets;
00174
00175
00176 int ret = gatherBoxesAndOffsets(offsetthisproc, sumprocsize, globalOffsets, globalBoxes, a_sizes, a_boxes, a_thisprocsize);
00177 if (ret!=0)
00178 {
00179 return ret;
00180 }
00181
00182 if (globalBoxes.size() != a_layout.size())
00183 {
00184 return -12;
00185 }
00186
00187 {
00188 char offsetname[1024];
00189 sprintf(offsetname, "%s:offsets=0",a_name.c_str());
00190
00191 hsize_t flatdims[1];
00192 flatdims[0] = globalOffsets.size();
00193 hid_t offsetspace = H5Screate_simple(1, flatdims, NULL);
00194 hid_t offsetdata = H5Dcreate(a_handle.groupID(), offsetname,
00195 H5T_NATIVE_LLONG, offsetspace, H5P_DEFAULT);
00196
00197 if (procID() == 0)
00198 {
00199 hid_t memdataspace = H5Screate_simple(1, flatdims, NULL);
00200 err = H5Dwrite(offsetdata, H5T_NATIVE_LLONG, memdataspace, offsetspace,
00201 H5P_DEFAULT, &(globalOffsets[0]));
00202 if (err < 0) return err;
00203 H5Sclose(memdataspace);
00204 }
00205
00206 H5Sclose(offsetspace);
00207 H5Dclose(offsetdata);
00208 }
00209 {
00210 hsize_t hs_procsize[1];
00211 hsize_t hs_allprocsize[1];
00212 ch_offset_t ch_offset[1];
00213
00214 ch_offset[0] = offsetthisproc;
00215 hs_procsize[0] = a_thisprocsize;
00216 hs_allprocsize[0] = sumprocsize;
00217
00218 char dataname[1024];
00219 sprintf(dataname, "%s:datatype=0",a_name.c_str());
00220
00221
00222 hid_t dataspace = H5Screate_simple(1, hs_allprocsize, NULL);
00223 hid_t memdataspace = H5Screate_simple(1, hs_procsize, NULL);
00224
00225 hid_t dataset = H5Dcreate(a_handle.groupID(), dataname,
00226 a_types[0], dataspace, H5P_DEFAULT);
00227
00228
00229
00230 err = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
00231 ch_offset, NULL,
00232 hs_procsize, NULL);
00233 if (err < 0) return err;
00234
00235 err = H5Dwrite(dataset, a_types[0], memdataspace, dataspace,
00236 H5P_DEFAULT, a_buffer);
00237 if (err < 0) return err;
00238
00239
00240 H5Sclose(memdataspace);
00241 H5Sclose(dataspace);
00242 H5Dclose(dataset);
00243 }
00244 return 0;
00245 }
00246
00247 template <class T>
00248 int blockWrite(HDF5Handle& a_handle,
00249 const LevelData<T>& a_data,
00250 const std::string& a_name,
00251 const IntVect& a_outputGhost,
00252 const Interval& a_in_comps)
00253 {
00254 HDF5HeaderData info;
00255 info.m_intvect["ghost"] = a_data.ghostVect();
00256 IntVect og(a_outputGhost);
00257 og.min(a_data.ghostVect());
00258 info.m_intvect["outputGhost"] = og;
00259 std::string group = a_handle.getGroup();
00260 a_handle.setGroup(group+"/"+a_name+"_attributes");
00261 info.writeToFile(a_handle);
00262 a_handle.setGroup(group);
00263 return blockWrite(a_handle, (const BoxLayoutData<T>&)a_data, a_name, og, a_in_comps);
00264 }
00265
00266
00267 template <class T> int
00268 blockWrite(HDF5Handle& a_handle,
00269 const BoxLayoutData<T>& a_data,
00270 const std::string& a_name,
00271 const IntVect& a_outputGhost,
00272 const Interval& a_comps)
00273 {
00274 CH_TIME("block write Level");
00275 int ret = 0;
00276
00277
00278 const BoxLayout& layout = a_data.boxLayout();
00279 T dummy;
00280
00281 Vector<hid_t> types;
00282 dataTypes(types, dummy);
00283 if (types.size() != 1)
00284 {
00285 MayDay::Error("premature generality, I only deal with types of size 1");
00286 }
00287
00288
00289 Vector<long long> sizes;
00290 Vector<Box> boxes;
00291 long long totalsize;
00292
00293
00294
00295 blockLocalOffsets(sizes, totalsize, boxes, a_data, a_comps, a_outputGhost);
00296
00297
00298 size_t type_size = H5Tget_size(types[0]);
00299
00300
00301 void* buffer = mallocMT(totalsize*type_size);
00302
00303
00304 blockWriteToBuffer(buffer, sizes, a_data, a_comps, a_outputGhost);
00305
00306
00307 HDF5HeaderData info;
00308 info.m_int["comps"] = a_comps.size();
00309 info.m_string["objectType"] = name(dummy);
00310 std::string group = a_handle.getGroup();
00311
00312 a_handle.setGroup(group+"/"+a_name+"_attributes");
00313 info.writeToFile(a_handle);
00314 a_handle.setGroup(group);
00315
00316
00317
00318 ret = blockWriteBufferToFile(a_handle,
00319 buffer,
00320 a_name,
00321 boxes,
00322 sizes,
00323 types,
00324 layout,
00325 totalsize);
00326 if (ret != 0)
00327 {
00328 return ret;
00329 }
00330
00331
00332
00333 freeMT(buffer);
00334 buffer = NULL;
00335
00336 return ret;
00337 }
00338
00339 template <class T> int
00340 blockWriteLevel(HDF5Handle& a_handle,
00341 const int& a_level,
00342 const LevelData<T>& a_data,
00343 const Real& a_dx,
00344 const Real& a_dt,
00345 const Real& a_time,
00346 const Box& a_domain,
00347 const int& a_refRatio,
00348 const IntVect& a_outputGhost,
00349 const Interval& a_comps)
00350 {
00351 int error;
00352 char levelName[10];
00353 std::string currentGroup = a_handle.getGroup();
00354 sprintf(levelName, "/level_%i",a_level);
00355 error = a_handle.setGroup(currentGroup + levelName);
00356 if (error != 0) return 1;
00357
00358 HDF5HeaderData meta;
00359 meta.m_real["dx"] = a_dx;
00360 meta.m_real["dt"] = a_dt;
00361 meta.m_real["time"] = a_time;
00362 meta.m_box["prob_domain"] = a_domain;
00363 meta.m_int["ref_ratio"] = a_refRatio;
00364
00365 error = meta.writeToFile(a_handle);
00366 if (error != 0) return 2;
00367
00368 error = write(a_handle, a_data.boxLayout());
00369 if (error != 0) return 3;
00370
00371 error = blockWrite(a_handle, a_data, std::string("data"), a_outputGhost, a_comps);
00372 if (error != 0) return 4;
00373
00374 a_handle.setGroup(currentGroup);
00375
00376 return 0;
00377 }
00378
00379 template <class T> int
00380 blockReadLevel(HDF5Handle& a_handle,
00381 const int& a_level,
00382 LevelData<T>& a_data,
00383 Real& a_dx,
00384 Real& a_dt,
00385 Real& a_time,
00386 Box& a_domain,
00387 int& a_refRatio,
00388 const Interval& a_comps,
00389 bool a_setGhost)
00390 {
00391 HDF5HeaderData header;
00392 header.readFromFile(a_handle);
00393
00394
00395
00396 int error;
00397 char levelName[10];
00398 std::string currentGroup = a_handle.getGroup();
00399 sprintf(levelName, "/level_%i",a_level);
00400 error = a_handle.setGroup(currentGroup + levelName);
00401 if (error != 0) return 1;
00402
00403 HDF5HeaderData meta;
00404 error = meta.readFromFile(a_handle);
00405 if (error != 0) return 2;
00406 a_dx = meta.m_real["dx"];
00407 a_dt = meta.m_real["dt"];
00408 a_time = meta.m_real["time"];
00409 a_domain = meta.m_box["prob_domain"];
00410 a_refRatio = meta.m_int["ref_ratio"];
00411
00412
00413 Vector<Box> boxes;
00414 error = read(a_handle, boxes);
00415 Vector<int> procIDs;
00416 LoadBalance(procIDs, boxes);
00417
00418
00419 DisjointBoxLayout layout(boxes, procIDs);
00420
00421 layout.close();
00422 if (error != 0) return 3;
00423
00424 error = blockRead(a_handle, a_data, "data", layout, a_comps);
00425
00426 if (error != 0) return 4;
00427
00428
00429 a_handle.setGroup(currentGroup);
00430
00431 return 0;
00432 }
00433
00434
00435 template <class T> int
00436 blockRead(HDF5Handle& a_handle, LevelData<T>& a_data, const std::string& a_name,
00437 const DisjointBoxLayout& a_layout, const Interval& a_comps, bool a_redefineData)
00438 {
00439 if (a_redefineData)
00440 {
00441 HDF5HeaderData info;
00442 std::string group = a_handle.getGroup();
00443 if (a_handle.setGroup(group+"/"+a_name+"_attributes"))
00444 {
00445 std::string message = "error opening "
00446 +a_handle.getGroup()+"/"+a_name+"_attributes" ;
00447 MayDay::Warning(message.c_str());
00448 return 1;
00449 }
00450 info.readFromFile(a_handle);
00451 a_handle.setGroup(group);
00452 int ncomp = info.m_int["comps"];
00453 IntVect ghost = info.m_intvect["ghost"];
00454 if (a_comps.end() > 0 && ncomp < a_comps.end())
00455 {
00456 MayDay::Error("attempt to read component interval that is not available");
00457 }
00458 if (a_comps.size() == 0)
00459 a_data.define(a_layout, ncomp, ghost);
00460 else
00461 a_data.define(a_layout, a_comps.size(), ghost);
00462 }
00463 return blockRead(a_handle, (BoxLayoutData<T>&)a_data, a_name, a_layout, a_comps, false);
00464
00465 }
00466
00467
00468 template <class T>
00469 int
00470 blockRead(HDF5Handle& a_handle, BoxLayoutData<T>& a_data, const std::string& a_name,
00471 const BoxLayout& a_layout, const Interval& a_comps, bool a_redefineData)
00472 {
00473
00474 int ret = read(a_handle, a_data, a_name, a_layout, a_comps, a_redefineData);
00475 return ret;
00476 }
00477
00478 #endif