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 <set>
00034 #include <cstring>
00035
00036 #include "Hdf5DataWriter.hpp"
00037
00038 #include "Exception.hpp"
00039 #include "OutputFileHandler.hpp"
00040 #include "PetscTools.hpp"
00041 #include "Version.hpp"
00042
00043 Hdf5DataWriter::Hdf5DataWriter(DistributedVectorFactory& rVectorFactory,
00044 const std::string& rDirectory,
00045 const std::string& rBaseName,
00046 bool cleanDirectory,
00047 bool extendData)
00048 : mrVectorFactory(rVectorFactory),
00049 mDirectory(rDirectory),
00050 mBaseName(rBaseName),
00051 mCleanDirectory(cleanDirectory),
00052 mIsInDefineMode(true),
00053 mIsFixedDimensionSet(false),
00054 mIsUnlimitedDimensionSet(false),
00055 mEstimatedUnlimitedLength(1u),
00056 mFileFixedDimensionSize(0u),
00057 mDataFixedDimensionSize(0u),
00058 mLo(mrVectorFactory.GetLow()),
00059 mHi(mrVectorFactory.GetHigh()),
00060 mNumberOwned(0u),
00061 mOffset(0u),
00062 mIsDataComplete(true),
00063 mNeedExtend(false),
00064 mUseMatrixForIncompleteData(false),
00065 mCurrentTimeStep(0),
00066 mSinglePermutation(NULL),
00067 mDoublePermutation(NULL),
00068 mSingleIncompleteOutputMatrix(NULL),
00069 mDoubleIncompleteOutputMatrix(NULL),
00070 mUseOptimalChunkSizeAlgorithm(true),
00071 mFixedChunkSize(0)
00072 {
00073 if (extendData && cleanDirectory)
00074 {
00075 EXCEPTION("You are asking to delete a file and then extend it, change arguments to constructor.");
00076 }
00077
00078 if (extendData)
00079 {
00080
00081 OutputFileHandler output_file_handler(mDirectory, false);
00082 std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();
00083 std::string file_name = results_dir + mBaseName + ".h5";
00084
00085
00086 hid_t property_list_id = H5Pcreate(H5P_FILE_ACCESS);
00087 H5Pset_fapl_mpio(property_list_id, PETSC_COMM_WORLD, MPI_INFO_NULL);
00088
00089
00090 mFileId = H5Fopen(file_name.c_str(), H5F_ACC_RDWR, property_list_id);
00091 H5Pclose(property_list_id);
00092
00093 if (mFileId < 0)
00094 {
00095 mDatasetId = 0;
00096 EXCEPTION("Hdf5DataWriter could not open " + file_name);
00097 }
00098
00099
00100 mDatasetId = H5Dopen(mFileId, "Data");
00101 hid_t variables_dataspace = H5Dget_space(mDatasetId);
00102
00103 hsize_t dataset_max_sizes[DATASET_DIMS];
00104 H5Sget_simple_extent_dims(variables_dataspace, mDatasetDims, dataset_max_sizes);
00105 H5Sclose(variables_dataspace);
00106
00107
00108 if (dataset_max_sizes[0] != H5S_UNLIMITED)
00109 {
00110 H5Dclose(mDatasetId);
00111 H5Fclose(mFileId);
00112 EXCEPTION("Tried to open a datafile for extending which doesn't have an unlimited dimension.");
00113 }
00114 mIsUnlimitedDimensionSet = true;
00115
00116
00117 for (unsigned i=1; i<DATASET_DIMS; i++)
00118 {
00119 assert(mDatasetDims[i] == dataset_max_sizes[i]);
00120 }
00121 mFileFixedDimensionSize = mDatasetDims[1];
00122 mIsFixedDimensionSet = true;
00123 mVariables.reserve(mDatasetDims[2]);
00124
00125
00126 hid_t attribute_id = H5Aopen_name(mDatasetId, "Variable Details");
00127 hid_t attribute_type = H5Aget_type(attribute_id);
00128 hid_t attribute_space = H5Aget_space(attribute_id);
00129 hsize_t attr_dataspace_dim;
00130 H5Sget_simple_extent_dims(attribute_space, &attr_dataspace_dim, NULL);
00131 unsigned num_columns = H5Sget_simple_extent_npoints(attribute_space);
00132 assert(num_columns == mDatasetDims[2]);
00133
00134 char* string_array = (char *)malloc(sizeof(char)*MAX_STRING_SIZE*(int)num_columns);
00135 H5Aread(attribute_id, attribute_type, string_array);
00136
00137
00138 for (unsigned index=0; index<num_columns; index++)
00139 {
00140
00141 std::string column_name_unit(&string_array[MAX_STRING_SIZE*index]);
00142
00143
00144 size_t name_length = column_name_unit.find('(');
00145 size_t unit_length = column_name_unit.find(')') - name_length - 1;
00146
00147
00148 DataWriterVariable var;
00149 var.mVariableName = column_name_unit.substr(0, name_length);
00150 var.mVariableUnits = column_name_unit.substr(name_length+1, unit_length);
00151 mVariables.push_back(var);
00152 }
00153
00154
00155 free(string_array);
00156 H5Tclose(attribute_type);
00157 H5Sclose(attribute_space);
00158 H5Aclose(attribute_id);
00159
00160
00161 mUnlimitedDimensionName = "Time";
00162 mTimeDatasetId = H5Dopen(mFileId, mUnlimitedDimensionName.c_str());
00163 mUnlimitedDimensionUnit = "ms";
00164
00165
00166 hid_t timestep_dataspace = H5Dget_space(mTimeDatasetId);
00167 hsize_t num_timesteps;
00168 H5Sget_simple_extent_dims(timestep_dataspace, &num_timesteps, NULL);
00169 H5Sclose(timestep_dataspace);
00170 mCurrentTimeStep = (long)num_timesteps - 1;
00171
00172
00173 attribute_id = H5Aopen_name(mDatasetId, "IsDataComplete");
00174 if (attribute_id < 0)
00175 {
00176 #define COVERAGE_IGNORE
00177
00178 EXCEPTION("Extending old-format files isn't supported.");
00179 #undef COVERAGE_IGNORE
00180 }
00181 else
00182 {
00183 attribute_type = H5Aget_type(attribute_id);
00184 attribute_space = H5Aget_space(attribute_id);
00185 unsigned is_data_complete;
00186 H5Aread(attribute_id, H5T_NATIVE_UINT, &is_data_complete);
00187 mIsDataComplete = (is_data_complete == 1) ? true : false;
00188 H5Tclose(attribute_type);
00189 H5Sclose(attribute_space);
00190 H5Aclose(attribute_id);
00191 }
00192 if (mIsDataComplete)
00193 {
00194 mNumberOwned = mrVectorFactory.GetLocalOwnership();
00195 mOffset = mLo;
00196 mDataFixedDimensionSize = mFileFixedDimensionSize;
00197 }
00198 else
00199 {
00200
00201 attribute_id = H5Aopen_name(mDatasetId, "NodeMap");
00202 attribute_type = H5Aget_type(attribute_id);
00203 attribute_space = H5Aget_space(attribute_id);
00204
00205
00206 unsigned num_node_indices = H5Sget_simple_extent_npoints(attribute_space);
00207
00208
00209 mIncompleteNodeIndices.clear();
00210 mIncompleteNodeIndices.resize(num_node_indices);
00211 H5Aread(attribute_id, H5T_NATIVE_UINT, &mIncompleteNodeIndices[0]);
00212
00213
00214 H5Tclose(attribute_type);
00215 H5Sclose(attribute_space);
00216 H5Aclose(attribute_id);
00217
00218
00219 mNumberOwned = mrVectorFactory.GetLocalOwnership();
00220 ComputeIncompleteOffset();
00224 mDataFixedDimensionSize = UINT_MAX;
00225 H5Dclose(mDatasetId);
00226 H5Dclose(mTimeDatasetId);
00227 H5Fclose(mFileId);
00228 EXCEPTION("Unable to extend an incomplete data file at present.");
00229 }
00230
00231
00232 mIsInDefineMode = false;
00233 AdvanceAlongUnlimitedDimension();
00234 }
00235 }
00236
00237 Hdf5DataWriter::~Hdf5DataWriter()
00238 {
00239 Close();
00240
00241 if (mSinglePermutation)
00242 {
00243 MatDestroy(mSinglePermutation);
00244 }
00245 if (mDoublePermutation)
00246 {
00247 MatDestroy(mDoublePermutation);
00248 }
00249 if (mSingleIncompleteOutputMatrix)
00250 {
00251 MatDestroy(mSingleIncompleteOutputMatrix);
00252 }
00253 if (mDoubleIncompleteOutputMatrix)
00254 {
00255 MatDestroy(mDoubleIncompleteOutputMatrix);
00256 }
00257 }
00258
00259 void Hdf5DataWriter::DefineFixedDimension(long dimensionSize)
00260 {
00261 if (!mIsInDefineMode)
00262 {
00263 EXCEPTION("Cannot define variables when not in Define mode");
00264 }
00265 if (dimensionSize < 1)
00266 {
00267 EXCEPTION("Fixed dimension must be at least 1 long");
00268 }
00269 if (mIsFixedDimensionSet)
00270 {
00271 EXCEPTION("Fixed dimension already set");
00272 }
00273
00274
00275 mLo = mrVectorFactory.GetLow();
00276 mHi = mrVectorFactory.GetHigh();
00277 mNumberOwned = mrVectorFactory.GetLocalOwnership();
00278 mOffset = mLo;
00279 mFileFixedDimensionSize = dimensionSize;
00280 mDataFixedDimensionSize = dimensionSize;
00281 mIsFixedDimensionSet = true;
00282 }
00283
00284 void Hdf5DataWriter::DefineFixedDimension(const std::vector<unsigned>& rNodesToOuput, long vecSize)
00285 {
00286 unsigned vector_size = rNodesToOuput.size();
00287
00288 for (unsigned index=0; index < vector_size-1; index++)
00289 {
00290 if (rNodesToOuput[index] >= rNodesToOuput[index+1])
00291 {
00292 EXCEPTION("Input should be monotonic increasing");
00293 }
00294 }
00295
00296 if ((int) rNodesToOuput.back() >= vecSize)
00297 {
00298 EXCEPTION("Vector size doesn't match nodes to output");
00299 }
00300
00301 DefineFixedDimension(vecSize);
00302
00303 mFileFixedDimensionSize = vector_size;
00304 mIsDataComplete = false;
00305 mIncompleteNodeIndices = rNodesToOuput;
00306 ComputeIncompleteOffset();
00307 }
00308
00309 void Hdf5DataWriter::DefineFixedDimensionUsingMatrix(const std::vector<unsigned>& rNodesToOuput, long vecSize)
00310 {
00311 unsigned vector_size = rNodesToOuput.size();
00312
00313 for (unsigned index=0; index < vector_size-1; index++)
00314 {
00315 if (rNodesToOuput[index] >= rNodesToOuput[index+1])
00316 {
00317 EXCEPTION("Input should be monotonic increasing");
00318 }
00319 }
00320
00321 if ((int) rNodesToOuput.back() >= vecSize)
00322 {
00323 EXCEPTION("Vector size doesn't match nodes to output");
00324 }
00325
00326 DefineFixedDimension(vecSize);
00327
00328 mFileFixedDimensionSize = vector_size;
00329 mIsDataComplete = false;
00330 mIncompleteNodeIndices = rNodesToOuput;
00331 mUseMatrixForIncompleteData = true;
00332 ComputeIncompleteOffset();
00333
00334
00335 assert(mSingleIncompleteOutputMatrix == NULL);
00336 assert(mDoubleIncompleteOutputMatrix == NULL);
00337 PetscTools::SetupMat(mSingleIncompleteOutputMatrix, mFileFixedDimensionSize, mDataFixedDimensionSize, 2, mNumberOwned, mHi - mLo);
00338 PetscTools::SetupMat(mDoubleIncompleteOutputMatrix, 2*mFileFixedDimensionSize, 2*mDataFixedDimensionSize, 4, 2*mNumberOwned, 2*(mHi - mLo));
00339
00340
00341 for (unsigned row_index = mOffset; row_index < mOffset + mNumberOwned; row_index++)
00342 {
00343
00344 MatSetValue(mSingleIncompleteOutputMatrix, row_index, row_index, 0.0, INSERT_VALUES);
00345
00346
00347 MatSetValue(mSingleIncompleteOutputMatrix, row_index, rNodesToOuput[row_index], 1.0, INSERT_VALUES);
00348
00349 unsigned bi_index = 2*row_index;
00350 unsigned perm_index = 2*rNodesToOuput[row_index];
00351
00352
00353 MatSetValue(mDoubleIncompleteOutputMatrix, bi_index, bi_index, 0.0, INSERT_VALUES);
00354 MatSetValue(mDoubleIncompleteOutputMatrix, bi_index+1, bi_index+1, 0.0, INSERT_VALUES);
00355
00356
00357 MatSetValue(mDoubleIncompleteOutputMatrix, bi_index, perm_index, 1.0, INSERT_VALUES);
00358 MatSetValue(mDoubleIncompleteOutputMatrix, bi_index+1, perm_index+1, 1.0, INSERT_VALUES);
00359 }
00360 MatAssemblyBegin(mSingleIncompleteOutputMatrix, MAT_FINAL_ASSEMBLY);
00361 MatAssemblyBegin(mDoubleIncompleteOutputMatrix, MAT_FINAL_ASSEMBLY);
00362 MatAssemblyEnd(mSingleIncompleteOutputMatrix, MAT_FINAL_ASSEMBLY);
00363 MatAssemblyEnd(mDoubleIncompleteOutputMatrix, MAT_FINAL_ASSEMBLY);
00364
00365
00366 }
00367
00368 void Hdf5DataWriter::ComputeIncompleteOffset()
00369 {
00370 mOffset = 0;
00371 mNumberOwned = 0;
00372 for (unsigned i=0; i<mIncompleteNodeIndices.size(); i++)
00373 {
00374 if (mIncompleteNodeIndices[i] < mLo)
00375 {
00376 mOffset++;
00377 }
00378 else if (mIncompleteNodeIndices[i] < mHi)
00379 {
00380 mNumberOwned++;
00381 }
00382 }
00383 }
00384
00385 int Hdf5DataWriter::DefineVariable(const std::string& rVariableName,
00386 const std::string& rVariableUnits)
00387 {
00388 if (!mIsInDefineMode)
00389 {
00390 EXCEPTION("Cannot define variables when not in Define mode");
00391 }
00392
00393 CheckVariableName(rVariableName);
00394 CheckUnitsName(rVariableUnits);
00395
00396
00397 for (unsigned index=0; index<mVariables.size(); index++)
00398 {
00399 if (mVariables[index].mVariableName == rVariableName)
00400 {
00401 EXCEPTION("Variable name already exists");
00402 }
00403 }
00404
00405 DataWriterVariable new_variable;
00406 new_variable.mVariableName = rVariableName;
00407 new_variable.mVariableUnits = rVariableUnits;
00408 int variable_id;
00409
00410
00411 mVariables.push_back(new_variable);
00412
00413
00414
00415 variable_id = mVariables.size() - 1;
00416
00417 return variable_id;
00418 }
00419
00420 void Hdf5DataWriter::CheckVariableName(const std::string& rName)
00421 {
00422 if (rName.length() == 0)
00423 {
00424 EXCEPTION("Variable name not allowed: may not be blank.");
00425 }
00426 CheckUnitsName(rName);
00427 }
00428
00429 void Hdf5DataWriter::CheckUnitsName(const std::string& rName)
00430 {
00431 for (unsigned i=0; i<rName.length(); i++)
00432 {
00433 if (!isalnum(rName[i]) && !(rName[i]=='_'))
00434 {
00435 std::string error = "Variable name/units '" + rName + "' not allowed: may only contain alphanumeric characters or '_'.";
00436 EXCEPTION(error);
00437 }
00438 }
00439 }
00440
00441 void Hdf5DataWriter::EndDefineMode()
00442 {
00443
00444 if (mVariables.size() < 1)
00445 {
00446 EXCEPTION("Cannot end define mode. No variables have been defined.");
00447 }
00448
00449
00450 if (mIsFixedDimensionSet == false)
00451 {
00452 EXCEPTION("Cannot end define mode. One fixed dimension should be defined.");
00453 }
00454
00455 OutputFileHandler output_file_handler(mDirectory, mCleanDirectory);
00456 std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();
00457 std::string file_name = results_dir + mBaseName + ".h5";
00458
00459
00460 hid_t property_list_id = H5Pcreate(H5P_FILE_ACCESS);
00461 H5Pset_fapl_mpio(property_list_id, PETSC_COMM_WORLD, MPI_INFO_NULL);
00462
00463
00464 mFileId = H5Fcreate(file_name.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, property_list_id);
00465 H5Pclose(property_list_id);
00466 if (mFileId < 0)
00467 {
00468 EXCEPTION("Hdf5DataWriter could not create " + file_name);
00469 }
00470 mIsInDefineMode = false;
00471
00472
00473
00474
00475
00476
00477 mDatasetDims[0] = 1;
00478 mDatasetDims[1] = mFileFixedDimensionSize;
00479 mDatasetDims[2] = mVariables.size();
00480
00481 hsize_t* max_dims = NULL;
00482 hsize_t dataset_max_dims[DATASET_DIMS];
00483
00484 hid_t cparms = H5P_DEFAULT;
00485
00486 if (mIsUnlimitedDimensionSet)
00487 {
00488 dataset_max_dims[0] = H5S_UNLIMITED;
00489 dataset_max_dims[1] = mDatasetDims[1];
00490 dataset_max_dims[2] = mDatasetDims[2];
00491 max_dims = dataset_max_dims;
00492
00493 hsize_t chunk_size;
00494 if (mUseOptimalChunkSizeAlgorithm)
00495 {
00496
00497
00498
00499
00500
00501
00502
00503 chunk_size = mEstimatedUnlimitedLength/100;
00504 if (chunk_size < 100)
00505 {
00506 chunk_size = 100;
00507 }
00508 }
00509 else
00510 {
00511 chunk_size = mFixedChunkSize;
00512 }
00513
00514
00515
00516
00517
00518
00519 if (chunk_size * mDatasetDims[1] * mDatasetDims[2] > (uint64_t)0xffffffff)
00520 {
00521
00522
00523
00524
00525 mIsInDefineMode = true;
00526 H5Fclose(mFileId);
00527 EXCEPTION("HDF5 may be writing more than 4GB to disk at any time and would fail. It may be possible to tune the Chaste code to get around this");
00528 }
00529
00530 hsize_t chunk_dims[DATASET_DIMS] = {chunk_size, mDatasetDims[1], mDatasetDims[2]};
00531 cparms = H5Pcreate (H5P_DATASET_CREATE);
00532
00533 H5Pset_chunk( cparms, DATASET_DIMS, chunk_dims);
00534 }
00535
00536 hid_t filespace = H5Screate_simple(DATASET_DIMS, mDatasetDims, max_dims);
00537
00538
00539 mDatasetId = H5Dcreate(mFileId, "Data", H5T_NATIVE_DOUBLE, filespace, cparms);
00540 H5Sclose(filespace);
00541
00542
00543 const unsigned MAX_STRING_SIZE = 100;
00544 hsize_t columns[1] = {mVariables.size()};
00545 hid_t colspace = H5Screate_simple(1, columns, NULL);
00546
00547
00548 char* col_data = (char*) malloc(mVariables.size() * sizeof(char) * MAX_STRING_SIZE);
00549
00550 char* col_data_offset = col_data;
00551 for (unsigned var=0; var<mVariables.size(); var++)
00552 {
00553 std::string full_name = mVariables[var].mVariableName + "(" + mVariables[var].mVariableUnits + ")";
00554 strcpy (col_data_offset, full_name.c_str());
00555 col_data_offset += sizeof(char) * MAX_STRING_SIZE;
00556 }
00557
00558
00559 hid_t string_type = H5Tcopy(H5T_C_S1);
00560 H5Tset_size(string_type, MAX_STRING_SIZE );
00561 hid_t attr = H5Acreate(mDatasetId, "Variable Details", string_type, colspace, H5P_DEFAULT);
00562
00563
00564 H5Awrite(attr, string_type, col_data);
00565
00566
00567 free(col_data);
00568 H5Sclose(colspace);
00569 H5Aclose(attr);
00570
00571
00572 columns[0] = 1;
00573 colspace = H5Screate_simple(1, columns, NULL);
00574 attr = H5Acreate(mDatasetId, "IsDataComplete", H5T_NATIVE_UINT, colspace, H5P_DEFAULT);
00575
00576
00577 unsigned is_data_complete = mIsDataComplete ? 1 : 0;
00578 H5Awrite(attr, H5T_NATIVE_UINT, &is_data_complete);
00579
00580 H5Sclose(colspace);
00581 H5Aclose(attr);
00582
00583 if (!mIsDataComplete)
00584 {
00585
00586
00587 columns[0] = mFileFixedDimensionSize;
00588 colspace = H5Screate_simple(1, columns, NULL);
00589 attr = H5Acreate(mDatasetId, "NodeMap", H5T_NATIVE_UINT, colspace, H5P_DEFAULT);
00590
00591
00592 H5Awrite(attr, H5T_NATIVE_UINT, &mIncompleteNodeIndices[0]);
00593
00594 H5Sclose(colspace);
00595 H5Aclose(attr);
00596 }
00597
00598
00599
00600
00601 if (mIsUnlimitedDimensionSet)
00602 {
00603 hsize_t time_dataset_dims[1] = {1};
00604 hsize_t time_dataset_max_dims[1] = {H5S_UNLIMITED};
00605
00606
00607 hsize_t time_chunk_dims[1] ={1};
00608 hid_t time_cparms = H5Pcreate (H5P_DATASET_CREATE);
00609 H5Pset_chunk( time_cparms, 1, time_chunk_dims);
00610
00611 hid_t time_filespace = H5Screate_simple(1, time_dataset_dims, time_dataset_max_dims);
00612
00613
00614 mTimeDatasetId = H5Dcreate(mFileId, mUnlimitedDimensionName.c_str(), H5T_NATIVE_DOUBLE, time_filespace, time_cparms);
00615
00616
00617 hsize_t one = 1;
00618 hid_t one_column_space = H5Screate_simple(1, &one, NULL);
00619
00620
00621 hid_t unit_attr = H5Acreate(mTimeDatasetId, "Unit", string_type, one_column_space, H5P_DEFAULT);
00622
00623
00624 char unit_string[MAX_STRING_SIZE];
00625 strcpy(unit_string, mUnlimitedDimensionUnit.c_str());
00626 H5Awrite(unit_attr, string_type, unit_string);
00627
00628
00629 H5Sclose(one_column_space);
00630 H5Aclose(unit_attr);
00631 H5Sclose(time_filespace);
00632 }
00633
00634
00635
00636
00637
00638
00639 const unsigned MAX_PROVENANCE_STRING_SIZE = 1023;
00640 hid_t long_string_type = H5Tcopy(H5T_C_S1);
00641 H5Tset_size(long_string_type, MAX_PROVENANCE_STRING_SIZE );
00642 hsize_t prov_columns[1] = {1};
00643 hid_t provenance_space = H5Screate_simple(1, prov_columns, NULL);
00644 char* provenance_data = (char*) malloc(sizeof(char) * MAX_PROVENANCE_STRING_SIZE);
00645 assert( ChasteBuildInfo::GetProvenanceString().length() < MAX_PROVENANCE_STRING_SIZE);
00646
00647 strcpy(provenance_data, ChasteBuildInfo::GetProvenanceString().c_str());
00648 hid_t prov_attr = H5Acreate(mDatasetId, "Chaste Provenance", long_string_type, provenance_space, H5P_DEFAULT);
00649
00650
00651 H5Awrite(prov_attr, long_string_type, provenance_data);
00652
00653
00654 free(provenance_data);
00655 H5Sclose(provenance_space);
00656 H5Aclose(prov_attr);
00657 }
00658
00659 void Hdf5DataWriter::PutVector(int variableID, Vec petscVector)
00660 {
00661 if (mIsInDefineMode)
00662 {
00663 EXCEPTION("Cannot write data while in define mode.");
00664 }
00665
00666 int vector_size;
00667 VecGetSize(petscVector, &vector_size);
00668
00669 if ((unsigned) vector_size != mDataFixedDimensionSize)
00670 {
00671 EXCEPTION("Vector size doesn't match fixed dimension");
00672 }
00673
00674
00675 PossiblyExtend();
00676
00677 Vec output_petsc_vector;
00678
00679
00680 if (mSinglePermutation == NULL)
00681 {
00682
00683 output_petsc_vector = petscVector;
00684 }
00685 else
00686 {
00687 assert(mIsDataComplete);
00688
00689 VecDuplicate(petscVector, &output_petsc_vector);
00690
00691
00692 MatMult(mSinglePermutation, petscVector, output_petsc_vector);
00693 }
00694
00695
00696 hid_t memspace=0;
00697 if (mNumberOwned != 0)
00698 {
00699 hsize_t v_size[1] = {mNumberOwned};
00700 memspace = H5Screate_simple(1, v_size, NULL);
00701 }
00702
00703
00704 hsize_t count[DATASET_DIMS] = {1, mNumberOwned, 1};
00705 hsize_t offset_dims[DATASET_DIMS] = {mCurrentTimeStep, mOffset, variableID};
00706 hid_t file_dataspace = H5Dget_space(mDatasetId);
00707
00708
00709 hid_t property_list_id = H5Pcreate(H5P_DATASET_XFER);
00710 H5Pset_dxpl_mpio(property_list_id, H5FD_MPIO_COLLECTIVE);
00711
00712 H5Sselect_hyperslab(file_dataspace, H5S_SELECT_SET, offset_dims, NULL, count, NULL);
00713
00714 double* p_petsc_vector;
00715 VecGetArray(output_petsc_vector, &p_petsc_vector);
00716
00717 if (mIsDataComplete)
00718 {
00719 H5Dwrite(mDatasetId, H5T_NATIVE_DOUBLE, memspace, file_dataspace, property_list_id, p_petsc_vector);
00720 }
00721 else
00722 {
00723 if (mUseMatrixForIncompleteData)
00724 {
00725
00726 output_petsc_vector = PetscTools::CreateVec(mFileFixedDimensionSize, mNumberOwned);
00727
00728
00729 MatMult(mSingleIncompleteOutputMatrix, petscVector, output_petsc_vector);
00730
00731 double* p_petsc_vector_incomplete;
00732 VecGetArray(output_petsc_vector, &p_petsc_vector_incomplete);
00733 H5Dwrite(mDatasetId, H5T_NATIVE_DOUBLE, memspace, file_dataspace, property_list_id, p_petsc_vector_incomplete);
00734 }
00735 else
00736 {
00737
00738 double local_data[mNumberOwned];
00739 for (unsigned i=0; i<mNumberOwned; i++)
00740 {
00741 local_data[i] = p_petsc_vector[ mIncompleteNodeIndices[mOffset+i]-mLo ];
00742
00743 }
00744 H5Dwrite(mDatasetId, H5T_NATIVE_DOUBLE, memspace, file_dataspace, property_list_id, local_data);
00745 }
00746 }
00747
00748 VecRestoreArray(output_petsc_vector, &p_petsc_vector);
00749
00750 H5Pclose(property_list_id);
00751 H5Sclose(file_dataspace);
00752 if (mNumberOwned !=0)
00753 {
00754 H5Sclose(memspace);
00755 }
00756
00757 if (petscVector != output_petsc_vector)
00758 {
00759
00760 VecDestroy(output_petsc_vector);
00761 }
00762 }
00763
00764 void Hdf5DataWriter::PutStripedVector(std::vector<int> variableIDs, Vec petscVector)
00765 {
00766 if (mIsInDefineMode)
00767 {
00768 EXCEPTION("Cannot write data while in define mode.");
00769 }
00770
00771 if (variableIDs.size() <= 1)
00772 {
00773 EXCEPTION("The PutStripedVector method requires at least two variables ID. If only one is needed, use PutVector method instead");
00774 }
00775
00776 const int NUM_STRIPES=variableIDs.size();
00777
00778 int firstVariableID=variableIDs[0];
00779
00780
00781 for (unsigned i = 1; i < variableIDs.size(); i++)
00782 {
00783 if (variableIDs[i]-variableIDs[i-1] != 1)
00784 {
00785 EXCEPTION("Columns should be consecutive. Try reordering them.");
00786 }
00787 }
00788
00789 int vector_size;
00790 VecGetSize(petscVector, &vector_size);
00791
00792 if ((unsigned) vector_size != NUM_STRIPES*mDataFixedDimensionSize)
00793 {
00794 EXCEPTION("Vector size doesn't match fixed dimension");
00795 }
00796
00797
00798 PossiblyExtend();
00799
00800 Vec output_petsc_vector;
00801
00802
00803 if (mDoublePermutation == NULL)
00804 {
00805
00806 output_petsc_vector = petscVector;
00807 }
00808 else
00809 {
00810 assert(mIsDataComplete);
00811
00812 VecDuplicate(petscVector, &output_petsc_vector);
00813
00814
00815 MatMult(mDoublePermutation, petscVector, output_petsc_vector);
00816 }
00817
00818 hid_t memspace=0;
00819 if (mNumberOwned !=0)
00820 {
00821 hsize_t v_size[1] = {mNumberOwned*NUM_STRIPES};
00822 memspace = H5Screate_simple(1, v_size, NULL);
00823 }
00824
00825
00826 hsize_t start[DATASET_DIMS] = {mCurrentTimeStep, mOffset, firstVariableID};
00827 hsize_t stride[DATASET_DIMS] = {1, 1, 1};
00828 hsize_t block_size[DATASET_DIMS] = {1, mNumberOwned, 1};
00829 hsize_t number_blocks[DATASET_DIMS] = {1, 1, NUM_STRIPES};
00830
00831 hid_t hyperslab_space = H5Dget_space(mDatasetId);
00832 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, start, stride, number_blocks, block_size);
00833
00834
00835 hid_t property_list_id = H5Pcreate(H5P_DATASET_XFER);
00836 H5Pset_dxpl_mpio(property_list_id, H5FD_MPIO_COLLECTIVE);
00837
00838 double* p_petsc_vector;
00839 VecGetArray(output_petsc_vector, &p_petsc_vector);
00840
00841 if (mIsDataComplete)
00842 {
00843 H5Dwrite(mDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, p_petsc_vector);
00844 }
00845 else
00846 {
00847 if (variableIDs.size() < 3)
00848 {
00849 if (mUseMatrixForIncompleteData)
00850 {
00851
00852 output_petsc_vector = PetscTools::CreateVec(2*mFileFixedDimensionSize, 2*mNumberOwned);
00853
00854
00855 MatMult(mDoubleIncompleteOutputMatrix, petscVector, output_petsc_vector);
00856
00857 double* p_petsc_vector_incomplete;
00858 VecGetArray(output_petsc_vector, &p_petsc_vector_incomplete);
00859
00860 H5Dwrite(mDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, p_petsc_vector_incomplete);
00861 }
00862 else
00863 {
00864
00865 double local_data[mNumberOwned*NUM_STRIPES];
00866 for (unsigned i=0; i<mNumberOwned; i++)
00867 {
00868 unsigned local_node_number = mIncompleteNodeIndices[mOffset+i] - mLo;
00869 local_data[NUM_STRIPES*i] = p_petsc_vector[ local_node_number*NUM_STRIPES ];
00870 local_data[NUM_STRIPES*i+1] = p_petsc_vector[ local_node_number*NUM_STRIPES + 1];
00871 }
00872
00873 H5Dwrite(mDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, property_list_id, local_data);
00874 }
00875 }
00876 else
00877 {
00878 EXCEPTION("The PutStripedVector functionality for incomplete data is supported for only 2 stripes");
00879 }
00880 }
00881
00882 VecRestoreArray(output_petsc_vector, &p_petsc_vector);
00883
00884 H5Sclose(hyperslab_space);
00885 if (mNumberOwned != 0)
00886 {
00887 H5Sclose(memspace);
00888 }
00889 H5Pclose(property_list_id);
00890
00891 if (petscVector != output_petsc_vector)
00892 {
00893
00894 VecDestroy(output_petsc_vector);
00895 }
00896 }
00897
00898 void Hdf5DataWriter::PutUnlimitedVariable(double value)
00899 {
00900 if (mIsInDefineMode)
00901 {
00902 EXCEPTION("Cannot write data while in define mode.");
00903 }
00904
00905 if (!mIsUnlimitedDimensionSet)
00906 {
00907 EXCEPTION("PutUnlimitedVariable() called but no unlimited dimension has been set");
00908 }
00909
00910
00911 PossiblyExtend();
00912
00913
00914 if (!PetscTools::AmMaster())
00915 {
00916 return;
00917 }
00918
00919 hsize_t size[1] = {1};
00920 hid_t memspace = H5Screate_simple(1, size, NULL);
00921
00922
00923 hsize_t count[1] = {1};
00924 hsize_t offset[1] = {mCurrentTimeStep};
00925 hid_t hyperslab_space = H5Dget_space(mTimeDatasetId);
00926 H5Sselect_hyperslab(hyperslab_space, H5S_SELECT_SET, offset, NULL, count, NULL);
00927
00928 H5Dwrite(mTimeDatasetId, H5T_NATIVE_DOUBLE, memspace, hyperslab_space, H5P_DEFAULT, &value);
00929
00930 H5Sclose(hyperslab_space);
00931 H5Sclose(memspace);
00932 }
00933
00934 void Hdf5DataWriter::Close()
00935 {
00936 if (mIsInDefineMode)
00937 {
00938 return;
00939 }
00940
00941 H5Dclose(mDatasetId);
00942 if (mIsUnlimitedDimensionSet)
00943 {
00944 H5Dclose(mTimeDatasetId);
00945 }
00946 H5Fclose(mFileId);
00947
00948
00949 mIsInDefineMode = true;
00950 }
00951
00952 void Hdf5DataWriter::DefineUnlimitedDimension(const std::string& rVariableName,
00953 const std::string& rVariableUnits,
00954 unsigned estimatedLength)
00955 {
00956 if (mIsUnlimitedDimensionSet)
00957 {
00958 EXCEPTION("Unlimited dimension already set. Cannot be defined twice");
00959 }
00960
00961 if (!mIsInDefineMode)
00962 {
00963 EXCEPTION("Cannot define variables when not in Define mode");
00964 }
00965
00966 mIsUnlimitedDimensionSet = true;
00967 mUnlimitedDimensionName = rVariableName;
00968 mUnlimitedDimensionUnit = rVariableUnits;
00969 mEstimatedUnlimitedLength = estimatedLength;
00970 }
00971
00972 void Hdf5DataWriter::AdvanceAlongUnlimitedDimension()
00973 {
00974 if (!mIsUnlimitedDimensionSet)
00975 {
00976 EXCEPTION("Trying to advance along an unlimited dimension without having defined any");
00977 }
00978
00979 mCurrentTimeStep++;
00980
00981
00982
00983
00984
00985
00986
00987 if ( mEstimatedUnlimitedLength > mDatasetDims[0] )
00988 {
00989 mDatasetDims[0] = mEstimatedUnlimitedLength;
00990 mNeedExtend = true;
00991 }
00992
00993
00994 if ( mCurrentTimeStep >= (long) mEstimatedUnlimitedLength )
00995 {
00996 mDatasetDims[0]++;
00997 mNeedExtend = true;
00998 }
00999 }
01000
01001 void Hdf5DataWriter::PossiblyExtend()
01002 {
01003 if (mNeedExtend)
01004 {
01005 H5Dextend (mDatasetId, mDatasetDims);
01006 H5Dextend (mTimeDatasetId, mDatasetDims);
01007 }
01008 mNeedExtend = false;
01009 }
01010
01011 int Hdf5DataWriter::GetVariableByName(const std::string& rVariableName)
01012 {
01013 int id = -1;
01014
01015
01016 for (unsigned index=0; index<mVariables.size(); index++)
01017 {
01018 if (mVariables[index].mVariableName == rVariableName)
01019 {
01020 id = index;
01021 break;
01022 }
01023 }
01024 if (id == -1)
01025 {
01026 EXCEPTION("Variable does not exist in hdf5 definitions.");
01027 }
01028 return id;
01029 }
01030
01031 bool Hdf5DataWriter::ApplyPermutation(const std::vector<unsigned>& rPermutation)
01032 {
01033 if (!mIsInDefineMode)
01034 {
01035 EXCEPTION("Cannot define permutation when not in Define mode");
01036 }
01037
01038 if (rPermutation.empty())
01039 {
01040 return false;
01041 }
01042
01043 if (rPermutation.size() != mFileFixedDimensionSize ||
01044 rPermutation.size() != mDataFixedDimensionSize)
01045 {
01046 EXCEPTION("Permutation doesn't match the expected problem size");
01047 }
01048
01049
01050 std::set<unsigned> permutation_pigeon_hole;
01051
01052
01053 bool identity_map = true;
01054 for (unsigned i=0; i<mDataFixedDimensionSize; i++)
01055 {
01056 permutation_pigeon_hole.insert(rPermutation[i]);
01057 if (identity_map && i != rPermutation[i])
01058 {
01059 identity_map = false;
01060 }
01061 }
01062 if (identity_map)
01063 {
01064
01065 return false;
01066 }
01067
01068
01069
01070
01071
01072
01073 for (unsigned i=0; i<mDataFixedDimensionSize; i++)
01074 {
01075 if (permutation_pigeon_hole.count(i) != 1u)
01076 {
01077 EXCEPTION("Permutation vector doesn't contain a valid permutation");
01078 }
01079 }
01080
01081 assert(mSinglePermutation == NULL);
01082 assert(mDoublePermutation == NULL);
01083 PetscTools::SetupMat(mSinglePermutation, mDataFixedDimensionSize, mDataFixedDimensionSize, 2, mHi - mLo, mHi - mLo);
01084 PetscTools::SetupMat(mDoublePermutation, 2*mDataFixedDimensionSize, 2*mDataFixedDimensionSize, 4, 2*(mHi - mLo), 2*(mHi - mLo));
01085 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x
01086 MatSetOption(mSinglePermutation, MAT_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE);
01087 MatSetOption(mDoublePermutation, MAT_IGNORE_OFF_PROC_ENTRIES, PETSC_TRUE);
01088 #else
01089 MatSetOption(mSinglePermutation, MAT_IGNORE_OFF_PROC_ENTRIES);
01090 MatSetOption(mDoublePermutation, MAT_IGNORE_OFF_PROC_ENTRIES);
01091 #endif
01092
01093 for (unsigned row_index=mLo; row_index<mHi; row_index++)
01094 {
01095
01096 MatSetValue(mSinglePermutation, row_index, row_index, 0.0, INSERT_VALUES);
01097
01098
01099 MatSetValue(mSinglePermutation, row_index, rPermutation[row_index], 1.0, INSERT_VALUES);
01100
01101 unsigned bi_index = 2*row_index;
01102 unsigned perm_index = 2*rPermutation[row_index];
01103
01104
01105 MatSetValue(mDoublePermutation, bi_index, bi_index, 0.0, INSERT_VALUES);
01106 MatSetValue(mDoublePermutation, bi_index+1, bi_index+1, 0.0, INSERT_VALUES);
01107
01108
01109 MatSetValue(mDoublePermutation, bi_index, perm_index, 1.0, INSERT_VALUES);
01110 MatSetValue(mDoublePermutation, bi_index+1, perm_index+1, 1.0, INSERT_VALUES);
01111 }
01112 MatAssemblyBegin(mSinglePermutation, MAT_FINAL_ASSEMBLY);
01113 MatAssemblyBegin(mDoublePermutation, MAT_FINAL_ASSEMBLY);
01114 MatAssemblyEnd(mSinglePermutation, MAT_FINAL_ASSEMBLY);
01115 MatAssemblyEnd(mDoublePermutation, MAT_FINAL_ASSEMBLY);
01116 return true;
01117 }
01118
01119 void Hdf5DataWriter::SetFixedChunkSize(unsigned chunkSize)
01120 {
01121 assert(mIsInDefineMode);
01122
01123 mUseOptimalChunkSizeAlgorithm = false;
01124 mFixedChunkSize = chunkSize;
01125 }