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 #include "Hdf5DataWriter.hpp"
00034
00035 #include "Exception.hpp"
00036 #include "OutputFileHandler.hpp"
00037 #include "PetscTools.hpp"
00038
00039
00040 Hdf5DataWriter::Hdf5DataWriter(DistributedVectorFactory& rVectorFactory,
00041 const std::string& rDirectory,
00042 const std::string& rBaseName,
00043 bool cleanDirectory)
00044 : mrVectorFactory(rVectorFactory),
00045 mDirectory(rDirectory),
00046 mBaseName(rBaseName),
00047 mCleanDirectory(cleanDirectory),
00048 mIsInDefineMode(true),
00049 mIsFixedDimensionSet(false),
00050 mIsUnlimitedDimensionSet(false),
00051 mFileFixedDimensionSize(0u),
00052 mDataFixedDimensionSize(0u),
00053 mLo(0u),
00054 mHi(0u),
00055 mNumberOwned(0u),
00056 mOffset(0u),
00057 mIsDataComplete(true),
00058 mNeedExtend(false),
00059 mCurrentTimeStep(0)
00060 {
00061 }
00062
00063 Hdf5DataWriter::~Hdf5DataWriter()
00064 {
00065 }
00066
00067 void Hdf5DataWriter::DefineFixedDimension(long dimensionSize)
00068 {
00069 if (!mIsInDefineMode)
00070 {
00071 EXCEPTION("Cannot define variables when not in Define mode");
00072 }
00073 if (dimensionSize < 1)
00074 {
00075 EXCEPTION("Fixed dimension must be at least 1 long");
00076 }
00077 if (mIsFixedDimensionSet)
00078 {
00079 EXCEPTION("Fixed dimension already set");
00080 }
00081
00082
00083 mLo = mrVectorFactory.GetLow();
00084 mHi = mrVectorFactory.GetHigh();
00085 mNumberOwned = mrVectorFactory.GetLocalOwnership();
00086 mOffset = mLo;
00087 mFileFixedDimensionSize = dimensionSize;
00088 mDataFixedDimensionSize = dimensionSize;
00089 mIsFixedDimensionSet = true;
00090 }
00091
00092 void Hdf5DataWriter::DefineFixedDimension(const std::vector<unsigned>& rNodesToOuput, long vecSize)
00093 {
00094 unsigned vector_size = rNodesToOuput.size();
00095
00096 for (unsigned index=0; index < vector_size-1; index++)
00097 {
00098 if (rNodesToOuput[index] >= rNodesToOuput[index+1])
00099 {
00100 EXCEPTION("Input should be monotonic increasing");
00101 }
00102 }
00103
00104 if ((int) rNodesToOuput.back() >= vecSize)
00105 {
00106 EXCEPTION("Vector size doesn't match nodes to output");
00107 }
00108
00109 DefineFixedDimension(vecSize);
00110
00111 mFileFixedDimensionSize = vector_size;
00112 mIsDataComplete = false;
00113 mIncompleteNodeIndices = rNodesToOuput;
00114 mOffset = 0;
00115 mNumberOwned = 0;
00116
00117
00118 for (unsigned i=0; i<mIncompleteNodeIndices.size(); i++)
00119 {
00120 if (mIncompleteNodeIndices[i] < mLo)
00121 {
00122 mOffset++;
00123 }
00124 else if (mIncompleteNodeIndices[i] < mHi)
00125 {
00126 mNumberOwned++;
00127 }
00128 }
00129 }
00130
00131 int Hdf5DataWriter::DefineVariable(const std::string& rVariableName,
00132 const std::string& rVariableUnits)
00133 {
00134 if (!mIsInDefineMode)
00135 {
00136 EXCEPTION("Cannot define variables when not in Define mode");
00137 }
00138
00139 CheckVariableName(rVariableName);
00140 CheckUnitsName(rVariableUnits);
00141
00142
00143 for (unsigned index=0; index<mVariables.size(); index++)
00144 {
00145 if (mVariables[index].mVariableName == rVariableName)
00146 {
00147 EXCEPTION("Variable name already exists");
00148 }
00149 }
00150
00151 DataWriterVariable new_variable;
00152 new_variable.mVariableName = rVariableName;
00153 new_variable.mVariableUnits = rVariableUnits;
00154 int variable_id;
00155
00156
00157 mVariables.push_back(new_variable);
00158
00159
00160
00161 variable_id = mVariables.size() - 1;
00162
00163 return variable_id;
00164 }
00165
00166 void Hdf5DataWriter::CheckVariableName(const std::string& rName)
00167 {
00168 if (rName.length() == 0)
00169 {
00170 EXCEPTION("Variable name not allowed: may not be blank.");
00171 }
00172 CheckUnitsName(rName);
00173 }
00174
00175 void Hdf5DataWriter::CheckUnitsName(const std::string& rName)
00176 {
00177 for (unsigned i=0; i<rName.length(); i++)
00178 {
00179 if (!isalnum(rName[i]) && !(rName[i]=='_'))
00180 {
00181 std::string error = "Variable name/units '" + rName + "' not allowed: may only contain alphanumeric characters or '_'.";
00182 EXCEPTION(error);
00183 }
00184 }
00185 }
00186
00187 void Hdf5DataWriter::EndDefineMode()
00188 {
00189
00190 if (mVariables.size() < 1)
00191 {
00192 EXCEPTION("Cannot end define mode. No variables have been defined.");
00193 }
00194
00195
00196 if (mIsFixedDimensionSet == false)
00197 {
00198 EXCEPTION("Cannot end define mode. One fixed dimension should be defined.");
00199 }
00200
00201 mIsInDefineMode = false;
00202
00203 OutputFileHandler output_file_handler(mDirectory, mCleanDirectory);
00204 std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();
00205 std::string file_name = results_dir + mBaseName + ".h5";
00206
00207
00208 hid_t property_list_id = H5Pcreate(H5P_FILE_ACCESS);
00209 H5Pset_fapl_mpio(property_list_id, PETSC_COMM_WORLD, MPI_INFO_NULL);
00210
00211
00212 mFileId = H5Fcreate(file_name.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, property_list_id);
00213 H5Pclose(property_list_id);
00214
00215
00216
00217
00218
00219 mDatasetDims[0] = 1;
00220 mDatasetDims[1] = mFileFixedDimensionSize;
00221 mDatasetDims[2] = mVariables.size();
00222
00223 hsize_t* max_dims = NULL;
00224 hsize_t dataset_max_dims[DATASET_DIMS];
00225
00226 hid_t cparms = H5P_DEFAULT;
00227
00228 if (mIsUnlimitedDimensionSet)
00229 {
00230 dataset_max_dims[0] = H5S_UNLIMITED;
00231 dataset_max_dims[1] = mDatasetDims[1];
00232 dataset_max_dims[2] = mDatasetDims[2];
00233 max_dims = dataset_max_dims;
00234
00235
00236 hsize_t chunk_dims[DATASET_DIMS] ={1, mDatasetDims[1], mDatasetDims[2]};
00237 cparms = H5Pcreate (H5P_DATASET_CREATE);
00238 H5Pset_chunk( cparms, DATASET_DIMS, chunk_dims);
00239 }
00240
00241 hid_t filespace = H5Screate_simple(DATASET_DIMS, mDatasetDims, max_dims);
00242
00243
00244 mDatasetId = H5Dcreate(mFileId, "Data", H5T_NATIVE_DOUBLE, filespace, cparms);
00245 H5Sclose(filespace);
00246
00247
00248 const unsigned MAX_STRING_SIZE = 100;
00249 hsize_t columns[1] = {mVariables.size()};
00250 hid_t colspace = H5Screate_simple(1, columns, NULL);
00251
00252
00253 char* col_data = (char*) malloc(mVariables.size() * sizeof(char) * MAX_STRING_SIZE);
00254
00255 char* col_data_offset = col_data;
00256 for (unsigned var=0; var<mVariables.size(); var++)
00257 {
00258 std::string full_name = mVariables[var].mVariableName + "(" + mVariables[var].mVariableUnits + ")";
00259 strcpy (col_data_offset, full_name.c_str());
00260 col_data_offset += sizeof(char) * MAX_STRING_SIZE;
00261 }
00262
00263
00264 hid_t string_type = H5Tcopy(H5T_C_S1);
00265 H5Tset_size(string_type, MAX_STRING_SIZE );
00266 hid_t attr = H5Acreate(mDatasetId, "Variable Details", string_type, colspace, H5P_DEFAULT);
00267
00268
00269 H5Awrite(attr, string_type, col_data);
00270
00271
00272 free(col_data);
00273 H5Sclose(colspace);
00274 H5Aclose(attr);
00275
00276
00277 columns[0] = 1;
00278 colspace = H5Screate_simple(1, columns, NULL);
00279 attr = H5Acreate(mDatasetId, "IsDataComplete", H5T_NATIVE_UINT, colspace, H5P_DEFAULT);
00280
00281
00282 unsigned is_data_complete= mIsDataComplete ? 1 : 0;
00283 H5Awrite(attr, H5T_NATIVE_UINT, &is_data_complete);
00284
00285 H5Sclose(colspace);
00286 H5Aclose(attr);
00287
00288 if (!mIsDataComplete)
00289 {
00290
00291
00292 columns[0] = mFileFixedDimensionSize;
00293 colspace = H5Screate_simple(1, columns, NULL);
00294 attr = H5Acreate(mDatasetId, "NodeMap", H5T_NATIVE_UINT, colspace, H5P_DEFAULT);
00295
00296
00297 H5Awrite(attr, H5T_NATIVE_UINT, &mIncompleteNodeIndices[0]);
00298
00299 H5Sclose(colspace);
00300 H5Aclose(attr);
00301 }
00302
00303
00304
00305
00306 if (mIsUnlimitedDimensionSet)
00307 {
00308 hsize_t time_dataset_dims[1] = {1};
00309 hsize_t time_dataset_max_dims[1] = {H5S_UNLIMITED};
00310
00311
00312 hsize_t time_chunk_dims[1] ={1};
00313 hid_t time_cparms = H5Pcreate (H5P_DATASET_CREATE);
00314 H5Pset_chunk( time_cparms, 1, time_chunk_dims);
00315
00316 hid_t time_filespace = H5Screate_simple(1, time_dataset_dims, time_dataset_max_dims);
00317
00318
00319 mTimeDatasetId = H5Dcreate(mFileId, mUnlimitedDimensionName.c_str(), H5T_NATIVE_DOUBLE, time_filespace, time_cparms);
00320
00321
00322 hsize_t one = 1;
00323 hid_t one_column_space = H5Screate_simple(1, &one, NULL);
00324
00325
00326 hid_t unit_attr = H5Acreate(mTimeDatasetId, "Unit", string_type, one_column_space, H5P_DEFAULT);
00327
00328
00329 char unit_string[MAX_STRING_SIZE];
00330 strcpy(unit_string, mUnlimitedDimensionUnit.c_str());
00331 H5Awrite(unit_attr, string_type, unit_string);
00332
00333
00334 H5Sclose(one_column_space);
00335 H5Aclose(unit_attr);
00336 H5Sclose(time_filespace);
00337 }
00338 }
00339
00340 void Hdf5DataWriter::PutVector(int variableID, Vec petscVector)
00341 {
00342 if (mIsInDefineMode)
00343 {
00344 EXCEPTION("Cannot write data while in define mode.");
00345 }
00346
00347 int vector_size;
00348 VecGetSize(petscVector, &vector_size);
00349
00350 if ((unsigned) vector_size != mDataFixedDimensionSize)
00351 {
00352 EXCEPTION("Vector size doesn't match fixed dimension");
00353 }
00354
00355
00356 PossiblyExtend();
00357
00358
00359 hid_t memspace=0;
00360 if (mNumberOwned !=0)
00361 {
00362 hsize_t v_size[1] = {mNumberOwned};
00363 memspace = H5Screate_simple(1, v_size, NULL);
00364 }
00365
00366 hsize_t count[DATASET_DIMS] = {1, mNumberOwned, 1};
00367 hsize_t offset_dims[DATASET_DIMS] = {mCurrentTimeStep, mOffset, variableID};
00368 hid_t file_dataspace = H5Dget_space(mDatasetId);
00369
00370
00371 hid_t property_list_id = H5Pcreate(H5P_DATASET_XFER);
00372 H5Pset_dxpl_mpio(property_list_id, H5FD_MPIO_COLLECTIVE);
00373
00374 H5Sselect_hyperslab(file_dataspace, H5S_SELECT_SET, offset_dims, NULL, count, NULL);
00375
00376 double *p_petsc_vector;
00377 VecGetArray(petscVector, &p_petsc_vector);
00378
00379 if (mIsDataComplete)
00380 {
00381 H5Dwrite(mDatasetId, H5T_NATIVE_DOUBLE, memspace, file_dataspace, property_list_id, p_petsc_vector);
00382 }
00383 else
00384 {
00385
00386 double local_data[mNumberOwned];
00387 for (unsigned i=0; i<mNumberOwned; i++)
00388 {
00389 local_data[i] = p_petsc_vector[ mIncompleteNodeIndices[mOffset+i]-mLo ];
00390
00391 }
00392 H5Dwrite(mDatasetId, H5T_NATIVE_DOUBLE, memspace, file_dataspace, property_list_id, local_data);
00393 }
00394
00395 VecRestoreArray(petscVector, &p_petsc_vector);
00396
00397 H5Pclose(property_list_id);
00398 H5Sclose(file_dataspace);
00399 if (mNumberOwned !=0)
00400 {
00401 H5Sclose(memspace);
00402 }
00403 }
00404
00405 void Hdf5DataWriter::PutStripedVector(int firstVariableID, int secondVariableID, Vec petscVector)
00406 {
00407 if (mIsInDefineMode)
00408 {
00409 EXCEPTION("Cannot write data while in define mode.");
00410 }
00411
00412 int NUM_STRIPES=2;
00413
00414
00415 if (secondVariableID-firstVariableID != 1)
00416 {
00417 EXCEPTION("Columns should be consecutive. Try reordering them.");
00418 }
00419
00420 int vector_size;
00421 VecGetSize(petscVector, &vector_size);
00422
00423 if ((unsigned) vector_size != NUM_STRIPES*mDataFixedDimensionSize)
00424 {
00425 EXCEPTION("Vector size doesn't match fixed dimension");
00426 }
00427
00428
00429 PossiblyExtend();
00430
00431
00432 hid_t memspace=0;
00433 if (mNumberOwned !=0)
00434 {
00435 hsize_t v_size[1] = {mNumberOwned*NUM_STRIPES};
00436 memspace = H5Screate_simple(1, v_size, NULL);
00437 }
00438
00439
00440 hsize_t start[DATASET_DIMS] = {mCurrentTimeStep, mOffset, firstVariableID};
00441 hsize_t stride[DATASET_DIMS] = {1, 1, secondVariableID-firstVariableID};
00442 hsize_t block_size[DATASET_DIMS] = {1, mNumberOwned, 1};
00443 hsize_t number_blocks[DATASET_DIMS] = {1, 1, NUM_STRIPES};
00444
00445 hid_t hyperslab_space = H5Dget_space(mDatasetId);
00446 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, start, stride, number_blocks, block_size);
00447
00448
00449 hid_t property_list_id = H5Pcreate(H5P_DATASET_XFER);
00450 H5Pset_dxpl_mpio(property_list_id, H5FD_MPIO_COLLECTIVE);
00451
00452 double *p_petsc_vector;
00453 VecGetArray(petscVector, &p_petsc_vector);
00454
00455 if (mIsDataComplete)
00456 {
00457 H5Dwrite(mDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, p_petsc_vector);
00458 }
00459 else
00460 {
00461
00462 double local_data[mNumberOwned*NUM_STRIPES];
00463 for (unsigned i=0; i<mNumberOwned; i++)
00464 {
00466 unsigned local_node_number=mIncompleteNodeIndices[mOffset+i] - mLo;
00467 local_data[NUM_STRIPES*i] = p_petsc_vector[ local_node_number*NUM_STRIPES ];
00468 local_data[NUM_STRIPES*i+1] = p_petsc_vector[ local_node_number*NUM_STRIPES + 1];
00469 }
00470 H5Dwrite(mDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, local_data);
00471 }
00472
00473 VecRestoreArray(petscVector, &p_petsc_vector);
00474
00475 H5Sclose(hyperslab_space);
00476 if (mNumberOwned != 0)
00477 {
00478 H5Sclose(memspace);
00479 }
00480 H5Pclose(property_list_id);
00481 }
00482
00483 void Hdf5DataWriter::PutUnlimitedVariable(double value)
00484 {
00485 if (mIsInDefineMode)
00486 {
00487 EXCEPTION("Cannot write data while in define mode.");
00488 }
00489
00490 if (!mIsUnlimitedDimensionSet)
00491 {
00492 EXCEPTION("PutUnlimitedVariable() called but no unlimited dimension has been set");
00493 }
00494
00495
00496 if (!PetscTools::AmMaster())
00497 {
00498 return;
00499 }
00500
00501
00502 PossiblyExtend();
00503
00504 hsize_t size[1] = {1};
00505 hid_t memspace = H5Screate_simple(1, size, NULL);
00506
00507
00508 hsize_t count[1] = {1};
00509 hsize_t offset[1] = {mCurrentTimeStep};
00510 hid_t hyperslab_space = H5Dget_space(mTimeDatasetId);
00511 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, offset, NULL, count, NULL);
00512
00513 H5Dwrite(mTimeDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, H5P_DEFAULT, &value);
00514
00515 H5Sclose(hyperslab_space);
00516 H5Sclose(memspace);
00517 }
00518
00519 void Hdf5DataWriter::Close()
00520 {
00521 if (mIsInDefineMode)
00522 {
00523 return;
00524 }
00525 H5Dclose(mDatasetId);
00526
00527 if (mIsUnlimitedDimensionSet)
00528 {
00529 H5Dclose(mTimeDatasetId);
00530 }
00531
00532 H5Fclose(mFileId);
00533 }
00534
00535 void Hdf5DataWriter::DefineUnlimitedDimension(const std::string& rVariableName,
00536 const std::string& rVariableUnits)
00537 {
00538 if (mIsUnlimitedDimensionSet)
00539 {
00540 EXCEPTION("Unlimited dimension already set. Cannot be defined twice");
00541 }
00542
00543 if (!mIsInDefineMode)
00544 {
00545 EXCEPTION("Cannot define variables when not in Define mode");
00546 }
00547
00548 mIsUnlimitedDimensionSet = true;
00549 mUnlimitedDimensionName = rVariableName;
00550 mUnlimitedDimensionUnit = rVariableUnits;
00551 }
00552
00553 void Hdf5DataWriter::AdvanceAlongUnlimitedDimension()
00554 {
00555 if (!mIsUnlimitedDimensionSet)
00556 {
00557 EXCEPTION("Trying to advance along an unlimited dimension without having defined any");
00558 }
00559
00560
00561 mDatasetDims[0]++;
00562 mNeedExtend = true;
00563
00564 mCurrentTimeStep++;
00565 }
00566
00567 void Hdf5DataWriter::PossiblyExtend()
00568 {
00569 if (mNeedExtend)
00570 {
00571 H5Dextend (mDatasetId, mDatasetDims);
00572 H5Dextend (mTimeDatasetId, mDatasetDims);
00573 }
00574 mNeedExtend = false;
00575 }