From 6d9ae15afad578526e0e487b3d36f72e30f7fafb Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Sat, 7 Feb 2015 02:42:18 +0100 Subject: [PATCH 01/47] Close #152 Represent Bools as Enums --- src/include/splash/basetypes/ColTypeBool.hpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/include/splash/basetypes/ColTypeBool.hpp b/src/include/splash/basetypes/ColTypeBool.hpp index 045e8da..8fc49ac 100644 --- a/src/include/splash/basetypes/ColTypeBool.hpp +++ b/src/include/splash/basetypes/ColTypeBool.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013 Felix Schmitt, René Widera + * Copyright 2013, 2015 Felix Schmitt, René Widera, Axel Huebl * * This file is part of libSplash. * @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -18,7 +19,6 @@ * and the GNU Lesser General Public License along with libSplash. * If not, see . */ - #ifndef COLTYPEBOOL_H @@ -35,8 +35,15 @@ class ColTypeBool : public CollectionType ColTypeBool() { - const hsize_t dim[] = {sizeof (bool)}; - this->type = H5Tarray_create(H5T_NATIVE_B8, 1, dim); + // 8 bit (very) short int, see + // http://www.hdfgroup.org/HDF5/doc/RM/PredefDTypes.html + // this is a h5py compatible implementation for bool, see: + // http://docs.h5py.org/en/latest/faq.html + this->type = H5Tenum_create(H5T_NATIVE_INT8); + const char *names[2] = {"true", "false"}; + const int64_t val[2] = {1, 0}; + H5Tenum_insert(this->type, names[0], &val[0]); + H5Tenum_insert(this->type, names[1], &val[1]); } ~ColTypeBool() From c792c20e23f5f31dc5ebbd97e21164a55ab9476c Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Sat, 7 Feb 2015 02:43:22 +0100 Subject: [PATCH 02/47] Increase File Format to 3.0 - internal representation of bools changed with #152 --- src/include/splash/version.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/splash/version.hpp b/src/include/splash/version.hpp index bcaf99b..04fc3fb 100644 --- a/src/include/splash/version.hpp +++ b/src/include/splash/version.hpp @@ -31,7 +31,7 @@ /** we can always handle files from the same major release * changes in the minor number have to be backwards compatible */ -#define SPLASH_FILE_FORMAT_MAJOR 2 -#define SPLASH_FILE_FORMAT_MINOR 1 +#define SPLASH_FILE_FORMAT_MAJOR 3 +#define SPLASH_FILE_FORMAT_MINOR 0 #endif /* VERSION_HPP */ From 59d208798c74b46dc1d35844a80691db392a85da Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Mon, 9 Feb 2015 14:52:43 +0100 Subject: [PATCH 03/47] Add Bool SimpleTest - read/write a bool field in C++ - read a bool field with h5py - copy test scripts to build dir --- doc/INSTALL.md | 3 ++- tests/CMakeLists.txt | 5 +++++ tests/SimpleDataTest.cpp | 39 +++++++++++++++++++++++++++++++--- tests/include/SimpleDataTest.h | 3 ++- tests/readBool.py | 38 +++++++++++++++++++++++++++++++++ tests/run_tests | 1 + 6 files changed, 84 insertions(+), 5 deletions(-) create mode 100755 tests/readBool.py diff --git a/doc/INSTALL.md b/doc/INSTALL.md index cdcabf8..640817b 100644 --- a/doc/INSTALL.md +++ b/doc/INSTALL.md @@ -17,7 +17,8 @@ To use the CMakeLists.txt file which comes with the source code, you must have The splashtools and some tests also require an **MPI 2.2** compatible MPI library, e.g. **OpenMPI 1.5.1** or higher. -Tests require the development version of the **CppUnit** library. +Our *tests* require the development version of the **CppUnit** library and +python support for `h5py` & `numpy`. Compiling diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d37e177..c79cc02 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -108,3 +108,8 @@ FOREACH(TEST_FILE ${TEST_FILES}) TARGET_LINK_LIBRARIES(${FILE}.out ${LIBS}) ENDFOREACH() + +# copy scripts to "build" dir for easy testing +FILE(COPY readBool.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +FILE(COPY run_tests DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +FILE(COPY run_parallel_tests DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/tests/SimpleDataTest.cpp b/tests/SimpleDataTest.cpp index 4df28dc..acb286f 100644 --- a/tests/SimpleDataTest.cpp +++ b/tests/SimpleDataTest.cpp @@ -40,7 +40,8 @@ using namespace splash; SimpleDataTest::SimpleDataTest() : ctUInt32(), -ctUInt64() +ctUInt64(), +ctBool() { dataCollector = new SerialDataCollector(10); srand(time(NULL)); @@ -74,9 +75,13 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize // initial part of the test: data is written to the file, once with and once // without borders uint64_t *dataWrite = new uint64_t[bufferSize]; + bool *boolWrite = new bool[bufferSize]; for (uint64_t i = 0; i < bufferSize; i++) + { dataWrite[i] = i; + boolWrite[i] = ( i%2 == 0 ); + } dataCollector->write(10, ctUInt64, dimensions, Selection(gridSize), "deep/folders/data", dataWrite); datasetNames.insert("deep/folders/data"); @@ -85,6 +90,13 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize borderSize), "deep/folders/data_without_borders", dataWrite); datasetNames.insert("deep/folders/data_without_borders"); + dataCollector->write(10, ctBool, dimensions, Selection(gridSize), "deep/folders/data_bool", boolWrite); + datasetNames.insert("deep/folders/data_bool"); + + dataCollector->write(20, ctBool, dimensions, Selection(gridSize, smallGridSize, + borderSize), "deep/folders/data_bool_without_borders", boolWrite); + datasetNames.insert("deep/folders/data_bool_without_borders"); + dataCollector->close(); // first part of the test: read data with borders to a cleared @@ -103,6 +115,9 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize int32_t *ids = NULL; size_t numIDs = 0; dataCollector->getEntryIDs(NULL, &numIDs); +#if defined TESTS_DEBUG + printf("number of entry IDs=%d\n", numIDs); +#endif CPPUNIT_ASSERT(numIDs == 2); ids = new int32_t[numIDs]; dataCollector->getEntryIDs(ids, NULL); @@ -110,7 +125,7 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize for (uint32_t j = 0; j < numIDs; ++j) { dataCollector->getEntriesForID(ids[j], NULL, &numEntries); - CPPUNIT_ASSERT(numEntries == 1); + CPPUNIT_ASSERT(numEntries == 2); entries = new DataCollector::DCEntry[numEntries]; dataCollector->getEntriesForID(ids[j], entries, NULL); @@ -129,8 +144,12 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize delete[] ids; uint64_t *dataRead = new uint64_t[bufferSize]; + bool *boolRead = new bool[bufferSize]; for (uint64_t i = 0; i < bufferSize; i++) + { dataRead[i] = UINT64_MAX; + boolRead[i] = false; + } Dimensions resultSize; dataCollector->read(10, "deep/folders/data", resultSize, dataRead); @@ -138,17 +157,31 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize for (uint32_t i = 0; i < 3; i++) CPPUNIT_ASSERT(resultSize[i] == gridSize[i]); + dataCollector->read(10, "deep/folders/data_bool", resultSize, boolRead); + for (uint64_t i = 0; i < bufferSize; i++) + { if (dataRead[i] != dataWrite[i]) { #if defined TESTS_DEBUG - std::cout << i << ": " << dataRead[i] << " != exptected " << dataWrite[i] << std::endl; + std::cout << i << ": " << dataRead[i] << " != expected " << dataWrite[i] << std::endl; +#endif + resultsCorrect = false; + break; + } + if (boolRead[i] != boolWrite[i]) + { +#if defined TESTS_DEBUG + std::cout << i << ": " << boolRead[i] << " != expected " << boolWrite[i] << std::endl; #endif resultsCorrect = false; break; } + } delete[] dataRead; + delete[] boolRead; + delete[] boolWrite; CPPUNIT_ASSERT_MESSAGE("simple write/read failed", resultsCorrect); diff --git a/tests/include/SimpleDataTest.h b/tests/include/SimpleDataTest.h index fbde3f6..5152b53 100644 --- a/tests/include/SimpleDataTest.h +++ b/tests/include/SimpleDataTest.h @@ -34,8 +34,8 @@ class SimpleDataTest : public CPPUNIT_NS::TestFixture { CPPUNIT_TEST_SUITE(SimpleDataTest); - CPPUNIT_TEST(testWriteRead); CPPUNIT_TEST(testNullWrite); + CPPUNIT_TEST(testWriteRead); CPPUNIT_TEST_SUITE_END(); @@ -63,6 +63,7 @@ class SimpleDataTest : public CPPUNIT_NS::TestFixture ColTypeUInt32 ctUInt32; ColTypeUInt64 ctUInt64; + ColTypeBool ctBool; DataCollector *dataCollector; }; diff --git a/tests/readBool.py b/tests/readBool.py new file mode 100755 index 0000000..3f5e2cb --- /dev/null +++ b/tests/readBool.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +# +# Copyright 2015 Axel Huebl +# +# This file is part of libSplash. +# +# libSplash is free software: you can redistribute it and/or modify +# it under the terms of of either the GNU General Public License or +# the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# libSplash is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License and the GNU Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License +# and the GNU Lesser General Public License along with libSplash. +# If not, see . +# + +import h5py +import numpy as np + +f = h5py.File("h5/testWriteRead_0_0_0.h5", "r") +data = f["data/10/deep/folders/data_bool"] + +len = data.size +data1d = data[:,:,:].reshape(len) + +for i in np.arange(len): + val = ( i%2 == 0 ); + if data1d[i] != val: + exit(1) + +exit(0) diff --git a/tests/run_tests b/tests/run_tests index fe0f8b6..4bfa7f2 100755 --- a/tests/run_tests +++ b/tests/run_tests @@ -26,6 +26,7 @@ function testMPI() } testSerial ./SimpleDataTest.cpp.out "Testing simple data read/write..." +testSerial ./readBool.py "Testing h5py compatible read..." testSerial ./AttributesTest.cpp.out "Testing reading/writing attributes..." From fe01bae6b53944806ccd46ea6ea716e97c62d6eb Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Tue, 10 Feb 2015 11:11:07 +0100 Subject: [PATCH 04/47] Add h5py & numpy to travis --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index d2498e3..6130842 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,6 +42,7 @@ before_script: - lsb_release -a - echo "$SRC" - ls -hal $SRC + - ls -hal /usr/include # PPA providing hdf5 >= 1.8.6 and OpenMPI >= 1.5.1 # -> remove legacy hdf5 and mpi packages/deps from travis - sudo apt-get remove -qq libhdf5* libopenmpi* openmpi-bin @@ -58,4 +59,10 @@ before_script: - sudo apt-get install -qq -f libboost-program-options-dev - sudo apt-get -t o=LP-PPA-james-page-openmpi install -q -f $APTMPI - sudo apt-get -t o=LP-PPA-axel-huebl-libsplash install -q -f $APTHDF5 + - sudo apt-get install python-numpy cython + - sudo -H pip install --upgrade pip +# numpy and cython should be already satisfied + - export HDF5_DIR=/usr + - export C_INCLUDE_PATH=/usr/lib/openmpi/include + - pip install --user h5py - mkdir -p $BUILD ~/lib From da0390553e1988b8ded13a56cb3c7605b81d190a Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Wed, 11 Feb 2015 16:04:43 +0100 Subject: [PATCH 05/47] Move INSTALL.md to Root Dir Usually, one should find the install instructions in the root directory. --- doc/INSTALL.md => INSTALL.md | 0 README.md | 2 +- doc/manual/UserManual.pdf | Bin 229149 -> 235995 bytes doc/manual/UserManual.tex | 4 ++-- 4 files changed, 3 insertions(+), 3 deletions(-) rename doc/INSTALL.md => INSTALL.md (100%) diff --git a/doc/INSTALL.md b/INSTALL.md similarity index 100% rename from doc/INSTALL.md rename to INSTALL.md diff --git a/README.md b/README.md index e0c84c3..30786fe 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Licences can be found in [GPL](COPYING) or [LGPL](COPYING.LESSER), respectively. Install ------- -See our notes in [INSTALL.md](doc/INSTALL.md). +See our notes in [INSTALL.md](INSTALL.md). Usage diff --git a/doc/manual/UserManual.pdf b/doc/manual/UserManual.pdf index f56429bcd24ec16ebbdb0594eb08df33883e9649..1e56bd1b2874112f4e639d1501d8a03d876c349d 100644 GIT binary patch delta 32362 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 delta 25460 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 diff --git a/doc/manual/UserManual.tex b/doc/manual/UserManual.tex index e0655ce..a95d981 100644 --- a/doc/manual/UserManual.tex +++ b/doc/manual/UserManual.tex @@ -100,7 +100,7 @@ \section{Installation} \subsection{Requirements and Compiling} -Please see the file \path{doc/INSTALL.md} for details. +Please see the file \path{INSTALL.md} for details. \section{Usage} @@ -108,7 +108,7 @@ \subsection{Linking to your Project} We provide a \code{FindSplash.cmake} module that can be used in your codes\newline \path{CMakeLists.txt} file. Install instructions and further hints for non-cmake based -linking can be found in the file \path{doc/INSTALL.md} . +linking can be found in the file \path{INSTALL.md} . \subsection{Includes} From 690c9570eda276867d1883ec0b82f822a8d19d13 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Tue, 14 Apr 2015 19:39:56 +0200 Subject: [PATCH 06/47] Add Atomic Char Type Single char for all kinds of fields and attributes. Not NULL-terminated. --- .../splash/basetypes/basetypes_atomic.hpp | 9 ++++---- tests/AttributesTest.cpp | 15 ++++++++---- tests/CMakeLists.txt | 2 +- tests/Parallel_AttributesTest.cpp | 11 ++++++--- tests/include/AttributesTest.h | 3 ++- tests/include/Parallel_AttributesTest.h | 7 +++--- tests/{readBool.py => readBoolChar.py} | 23 +++++++++++++++++++ tests/run_tests | 2 +- 8 files changed, 54 insertions(+), 18 deletions(-) rename tests/{readBool.py => readBoolChar.py} (73%) diff --git a/src/include/splash/basetypes/basetypes_atomic.hpp b/src/include/splash/basetypes/basetypes_atomic.hpp index 76d9664..a3f173f 100644 --- a/src/include/splash/basetypes/basetypes_atomic.hpp +++ b/src/include/splash/basetypes/basetypes_atomic.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -28,7 +28,7 @@ namespace splash { - + #define TYPE_ATOMIC(_name, _h5_type, _real_type) \ class ColType##_name : public CollectionType \ { \ @@ -40,11 +40,12 @@ namespace splash size_t getSize() const \ { return sizeof (_real_type); } \ }; - + TYPE_ATOMIC(Float, H5T_NATIVE_FLOAT, float); TYPE_ATOMIC(Double, H5T_NATIVE_DOUBLE, double); TYPE_ATOMIC(Int, H5T_NATIVE_INT, int); +TYPE_ATOMIC(Char, H5T_NATIVE_CHAR, char); TYPE_ATOMIC(UInt8, H5T_INTEL_U8, uint8_t); TYPE_ATOMIC(UInt16, H5T_INTEL_U16, uint16_t); @@ -55,7 +56,7 @@ TYPE_ATOMIC(Int8, H5T_INTEL_I8, int8_t); TYPE_ATOMIC(Int16, H5T_INTEL_I16, int16_t); TYPE_ATOMIC(Int32, H5T_INTEL_I32, int32_t); TYPE_ATOMIC(Int64, H5T_INTEL_I64, int64_t); - + } #endif /* BASETYPES_ATOMIC_HPP */ diff --git a/tests/AttributesTest.cpp b/tests/AttributesTest.cpp index caed160..a26145c 100644 --- a/tests/AttributesTest.cpp +++ b/tests/AttributesTest.cpp @@ -90,9 +90,11 @@ void AttributesTest::testDataAttributes() dataCollector->writeAttribute(0, ctInt, "datasets/my_dataset", "sum", &sum); int neg_sum = -sum; dataCollector->writeAttribute(0, ctInt, "datasets/my_dataset", "neg_sum", &neg_sum); - + + char c = 'Y'; dataCollector->writeAttribute(0, ctInt, "datasets", "sum_at_group", &sum); - + dataCollector->writeAttribute(0, ctChar, "datasets", "my_char", &c); + delete[] dummy_data; dummy_data = NULL; @@ -127,16 +129,19 @@ void AttributesTest::testDataAttributes() sum = 0; neg_sum = 0; + c = 'A'; dataCollector->readAttribute(0, "datasets/my_dataset", "sum", &sum); dataCollector->readAttribute(0, "datasets/my_dataset", "neg_sum", &neg_sum); CPPUNIT_ASSERT(sum == old_sum); CPPUNIT_ASSERT(neg_sum == -old_sum); - + dataCollector->readAttribute(0, "datasets", "sum_at_group", &sum); - + dataCollector->readAttribute(0, "datasets", "my_char", &c); + CPPUNIT_ASSERT(sum == old_sum); - + CPPUNIT_ASSERT(c == 'Y'); + dataCollector->close(); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c79cc02..3528dd0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -110,6 +110,6 @@ FOREACH(TEST_FILE ${TEST_FILES}) ENDFOREACH() # copy scripts to "build" dir for easy testing -FILE(COPY readBool.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +FILE(COPY readBoolChar.py DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) FILE(COPY run_tests DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) FILE(COPY run_parallel_tests DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/tests/Parallel_AttributesTest.cpp b/tests/Parallel_AttributesTest.cpp index 7f39b64..7630878 100644 --- a/tests/Parallel_AttributesTest.cpp +++ b/tests/Parallel_AttributesTest.cpp @@ -90,8 +90,10 @@ void Parallel_AttributesTest::testDataAttributes() dataCollector->writeAttribute(0, ctInt, "attr/attr2/attr3/data", "sum", &sum); int neg_sum = -sum; dataCollector->writeAttribute(0, ctInt, "attr/attr2/attr3/data", "neg_sum", &neg_sum); - + dataCollector->writeAttribute(0, ctInt, "attr/attr2/attr3", "sum_at_group", &sum); + char c = 'Y'; + dataCollector->writeAttribute(0, ctChar, "attr/attr2/attr3", "my_char", &c); delete[] dummy_data; dummy_data = NULL; @@ -110,6 +112,7 @@ void Parallel_AttributesTest::testDataAttributes() sum = 0; neg_sum = 0; + c = 'A'; dataCollector->readAttribute(0, "attr/attr2/attr3/data", "sum", &sum); dataCollector->readAttribute(0, "attr/attr2/attr3/data", "neg_sum", &neg_sum); @@ -117,10 +120,12 @@ void Parallel_AttributesTest::testDataAttributes() CPPUNIT_ASSERT(sum == old_sum); CPPUNIT_ASSERT(neg_sum == -old_sum); - + dataCollector->readAttribute(0, "attr/attr2/attr3", "sum_at_group", &sum); - + dataCollector->readAttribute(0, "attr/attr2/attr3", "my_char", &c); + CPPUNIT_ASSERT(sum == old_sum); + CPPUNIT_ASSERT(c == 'Y'); dataCollector->finalize(); dataCollector->close(); diff --git a/tests/include/AttributesTest.h b/tests/include/AttributesTest.h index 6bf0310..13f53da 100644 --- a/tests/include/AttributesTest.h +++ b/tests/include/AttributesTest.h @@ -44,7 +44,8 @@ class AttributesTest : public CPPUNIT_NS::TestFixture private: void testDataAttributes(); void testArrayTypes(); - + + ColTypeChar ctChar; ColTypeInt ctInt; ColTypeInt2 ctInt2; ColTypeInt3Array ctInt3Array; diff --git a/tests/include/Parallel_AttributesTest.h b/tests/include/Parallel_AttributesTest.h index df97037..c807295 100644 --- a/tests/include/Parallel_AttributesTest.h +++ b/tests/include/Parallel_AttributesTest.h @@ -1,5 +1,5 @@ /** - * Copyright 2013 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -43,12 +43,13 @@ class Parallel_AttributesTest : public CPPUNIT_NS::TestFixture private: void testDataAttributes(); void testArrayTypes(); - + + ColTypeChar ctChar; ColTypeInt ctInt; ColTypeInt2 ctInt2; ColTypeInt3Array ctInt3Array; ColTypeDimArray ctDimArray; - + int mpiRank; }; diff --git a/tests/readBool.py b/tests/readBoolChar.py similarity index 73% rename from tests/readBool.py rename to tests/readBoolChar.py index 3f5e2cb..d53b29f 100755 --- a/tests/readBool.py +++ b/tests/readBoolChar.py @@ -24,6 +24,7 @@ import h5py import numpy as np +# bool compatible data sets f = h5py.File("h5/testWriteRead_0_0_0.h5", "r") data = f["data/10/deep/folders/data_bool"] @@ -35,4 +36,26 @@ if data1d[i] != val: exit(1) +f.close() + +# single char compatible attributes +f = h5py.File("h5/attributes_0_0_0.h5", "r") +c = f["data/0/datasets"].attrs["my_char"] + +# h5py, as of 2.5.0, does not know char and +# identifies H5T_NATIVE_CHAR as INT8 +print(c, type(c)) + +# is... +if type(c) is np.int8: + if not c == 89: + exit(1) + +# should be... +if type(c) is np.char: + if not c == "Y": + exit(1) + +f.close() + exit(0) diff --git a/tests/run_tests b/tests/run_tests index 4bfa7f2..a586483 100755 --- a/tests/run_tests +++ b/tests/run_tests @@ -26,9 +26,9 @@ function testMPI() } testSerial ./SimpleDataTest.cpp.out "Testing simple data read/write..." -testSerial ./readBool.py "Testing h5py compatible read..." testSerial ./AttributesTest.cpp.out "Testing reading/writing attributes..." +testSerial ./readBoolChar.py "Testing h5py compatible read..." testSerial ./AppendTest.cpp.out "Testing append data..." From 3b2d4b40613aca8784b2d739f9a77c62a584faed Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Tue, 14 Apr 2015 20:36:44 +0200 Subject: [PATCH 07/47] Tests: Bash Output Improvement Print line after failed command to increase readability. --- tests/run_parallel_tests | 12 ++++++------ tests/run_tests | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/tests/run_parallel_tests b/tests/run_parallel_tests index 2430520..a37ea34 100755 --- a/tests/run_parallel_tests +++ b/tests/run_parallel_tests @@ -8,12 +8,10 @@ mkdir $dir/h5 cd $dir OK=0 -function testSerial() +function testLast() { - if [ -e "$1" ]; then - echo -e "\n$2\n" - $1 - OK=$(( OK + $? )) + if [ $1 -ne 0 ]; then + echo "An error occured in $2..." fi } function testMPI() @@ -21,7 +19,9 @@ function testMPI() if [ -e "$1" ]; then echo -e "\n$3\n" mpirun -n $2 $1 - OK=$(( OK + $? )) + last=$? + testLast $last $1 + OK=$(( OK + $last )) fi } diff --git a/tests/run_tests b/tests/run_tests index 4bfa7f2..1179949 100755 --- a/tests/run_tests +++ b/tests/run_tests @@ -8,12 +8,20 @@ mkdir $dir/h5 cd $dir OK=0 +function testLast() +{ + if [ $1 -ne 0 ]; then + echo "An error occured in $2..." + fi +} function testSerial() { if [ -e "$1" ]; then echo -e "\n$2\n" $1 - OK=$(( OK + $? )) + last=$? + testLast $last $1 + OK=$(( OK + $last )) fi } function testMPI() @@ -21,7 +29,9 @@ function testMPI() if [ -e "$1" ]; then echo -e "\n$3\n" mpirun -n $2 $1 - OK=$(( OK + $? )) + last=$? + testLast $last $1 + OK=$(( OK + $last )) fi } From 046f45b467d33cadb379bb4f2e3b6fdd81b885c9 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Tue, 14 Apr 2015 23:09:34 +0200 Subject: [PATCH 08/47] Add Variable and Fixed Length Strings - new collection type ColTypeString - h5py equivalents: - `str`: variable length string - `np.string_`: fixed length string - tests for attributes added (data sets untested) --- .../splash/basetypes/ColTypeString.hpp | 75 +++++++++++++++++++ src/include/splash/basetypes/basetypes.hpp | 3 +- tests/AttributesTest.cpp | 27 +++++-- tests/include/AttributesTest.h | 4 +- tests/readBoolChar.py | 21 ++++++ 5 files changed, 123 insertions(+), 7 deletions(-) create mode 100644 src/include/splash/basetypes/ColTypeString.hpp diff --git a/src/include/splash/basetypes/ColTypeString.hpp b/src/include/splash/basetypes/ColTypeString.hpp new file mode 100644 index 0000000..79fd1e7 --- /dev/null +++ b/src/include/splash/basetypes/ColTypeString.hpp @@ -0,0 +1,75 @@ +/** + * Copyright 2013-2015 Felix Schmitt, Axel Huebl + * + * This file is part of libSplash. + * + * libSplash is free software: you can redistribute it and/or modify + * it under the terms of of either the GNU General Public License or + * the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * libSplash is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser General Public License along with libSplash. + * If not, see . + */ + +#ifndef COLTYPESTRING_H +#define COLTYPESTRING_H + +#include "splash/CollectionType.hpp" + +namespace splash +{ + /** Variable and fixed length strings + * + * Since C-strings are NULL-terminated, len must be +1 + * of the actual length of the string for fixed length strings. + * + * \see http://hdfgroup.org/HDF5/doc/RM/RM_H5T.html#CreateVLString + */ + class ColTypeString : public CollectionType + { + public: + + ColTypeString() : + mySize(H5T_VARIABLE) + { + this->type = H5Tcopy(H5T_C_S1); + H5Tset_size(this->type, H5T_VARIABLE); + } + + ColTypeString(size_t len) : + mySize(len) + { + this->type = H5Tcopy(H5T_C_S1); + H5Tset_size(this->type, len); + } + + ~ColTypeString() + { + H5Tclose(this->type); + } + + size_t getSize() const + { + // for H5T_VARIABLE irrelevant ? + if( mySize != H5T_VARIABLE ) + return sizeof(char) * mySize; //H5Tget_size(this->type); + else + return sizeof(char); + } + + private: + size_t mySize; + }; + +} + +#endif /* COLTYPESTRING_H */ + diff --git a/src/include/splash/basetypes/basetypes.hpp b/src/include/splash/basetypes/basetypes.hpp index c949887..16d6b72 100644 --- a/src/include/splash/basetypes/basetypes.hpp +++ b/src/include/splash/basetypes/basetypes.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -29,6 +29,7 @@ #include "splash/basetypes/ColTypeBool.hpp" #include "splash/basetypes/ColTypeDim.hpp" #include "splash/basetypes/ColTypeDimArray.hpp" +#include "splash/basetypes/ColTypeString.hpp" #endif /* BASETYPES_HPP */ diff --git a/tests/AttributesTest.cpp b/tests/AttributesTest.cpp index a26145c..feaa4ca 100644 --- a/tests/AttributesTest.cpp +++ b/tests/AttributesTest.cpp @@ -1,5 +1,5 @@ /** - * Copyright 2013-2014 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -27,6 +27,7 @@ #include #include #include +#include #include CPPUNIT_TEST_SUITE_REGISTRATION(AttributesTest); @@ -37,10 +38,11 @@ using namespace splash; #define TEST_FILE "h5/attributes" #define TEST_FILE2 "h5/attributes_array" -AttributesTest::AttributesTest() +AttributesTest::AttributesTest() : +ctString5(5) { srand(time(NULL)); - + dataCollector = new SerialDataCollector(10); } @@ -76,7 +78,14 @@ void AttributesTest::testDataAttributes() sum2 = sum; dataCollector->writeAttribute(10, ctInt, NULL, "timestep", &sum2); - + + /* variable length string */ + const char *string_attr = {"My first c-string."}; + dataCollector->writeAttribute(10, ctString, NULL, "my_string", &string_attr); + /* fixed length string */ + const char string_attr5[5] = {"ABCD"}; + dataCollector->writeAttribute(10, ctString5, NULL, "my_string5", &string_attr5); + CPPUNIT_ASSERT_THROW(dataCollector->writeAttribute(10, ctInt, NULL, NULL, &sum2), DCException); CPPUNIT_ASSERT_THROW(dataCollector->writeAttribute(10, ctInt, NULL, "", &sum2), @@ -112,7 +121,15 @@ void AttributesTest::testDataAttributes() dataCollector->open(TEST_FILE, attr); dataCollector->readAttribute(10, NULL, "timestep", &sum2); - + + char* string_read; + dataCollector->readAttribute(10, NULL, "my_string", &string_read); + char string_read5[5]; + dataCollector->readAttribute(10, NULL, "my_string5", &string_read5); + + CPPUNIT_ASSERT(strcmp(string_read, string_attr) == 0); + CPPUNIT_ASSERT(strcmp(string_read5, string_attr5) == 0); + Dimensions src_data; dataCollector->read(0, "datasets/my_dataset", src_data, dummy_data); diff --git a/tests/include/AttributesTest.h b/tests/include/AttributesTest.h index 13f53da..50a52c6 100644 --- a/tests/include/AttributesTest.h +++ b/tests/include/AttributesTest.h @@ -1,5 +1,5 @@ /** - * Copyright 2013 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -50,6 +50,8 @@ class AttributesTest : public CPPUNIT_NS::TestFixture ColTypeInt2 ctInt2; ColTypeInt3Array ctInt3Array; ColTypeDimArray ctDimArray; + ColTypeString ctString; + ColTypeString ctString5; DataCollector *dataCollector; }; diff --git a/tests/readBoolChar.py b/tests/readBoolChar.py index d53b29f..048c94c 100755 --- a/tests/readBoolChar.py +++ b/tests/readBoolChar.py @@ -56,6 +56,27 @@ if not c == "Y": exit(1) +# variable length string compatible attributes +s = f["/data/10"].attrs["my_string"] +print(s, type(s)) + +if not s == "My first c-string.": + exit(1) + +if not type(s) is str: + exit(1) + +# fixed length string compatible attributes +s5 = f["/data/10"].attrs["my_string5"] +print(s5, type(s5), s5.dtype) + +if not s5 == "ABCD": + exit(1) + +if not type(s5) is np.string_: + exit(1) + + f.close() exit(0) From 2e08bcdb4903823fa3c108fa8d53c3c441361d12 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Wed, 15 Apr 2015 00:10:16 +0200 Subject: [PATCH 09/47] Add Fixed-Size String Data-Set Tests --- .../splash/basetypes/ColTypeString.hpp | 15 ++++---- tests/SimpleDataTest.cpp | 34 +++++++++++++++++-- tests/include/SimpleDataTest.h | 1 + 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/include/splash/basetypes/ColTypeString.hpp b/src/include/splash/basetypes/ColTypeString.hpp index 79fd1e7..207c927 100644 --- a/src/include/splash/basetypes/ColTypeString.hpp +++ b/src/include/splash/basetypes/ColTypeString.hpp @@ -37,15 +37,13 @@ namespace splash { public: - ColTypeString() : - mySize(H5T_VARIABLE) + ColTypeString() { this->type = H5Tcopy(H5T_C_S1); H5Tset_size(this->type, H5T_VARIABLE); } - ColTypeString(size_t len) : - mySize(len) + ColTypeString(size_t len) { this->type = H5Tcopy(H5T_C_S1); H5Tset_size(this->type, len); @@ -58,15 +56,14 @@ namespace splash size_t getSize() const { + size_t myElements = H5Tget_size(this->type); + // for H5T_VARIABLE irrelevant ? - if( mySize != H5T_VARIABLE ) - return sizeof(char) * mySize; //H5Tget_size(this->type); + if( myElements != H5T_VARIABLE ) + return sizeof(char) * myElements; else return sizeof(char); } - - private: - size_t mySize; }; } diff --git a/tests/SimpleDataTest.cpp b/tests/SimpleDataTest.cpp index acb286f..9671bdf 100644 --- a/tests/SimpleDataTest.cpp +++ b/tests/SimpleDataTest.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "SimpleDataTest.h" @@ -41,7 +42,8 @@ using namespace splash; SimpleDataTest::SimpleDataTest() : ctUInt32(), ctUInt64(), -ctBool() +ctBool(), +ctString3(3) { dataCollector = new SerialDataCollector(10); srand(time(NULL)); @@ -76,11 +78,16 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize // without borders uint64_t *dataWrite = new uint64_t[bufferSize]; bool *boolWrite = new bool[bufferSize]; + typedef char ccc[3]; + ccc *strWrite = new ccc[bufferSize]; for (uint64_t i = 0; i < bufferSize; i++) { dataWrite[i] = i; boolWrite[i] = ( i%2 == 0 ); + strWrite[i][0] = 'A'; + strWrite[i][1] = 'B'; + strWrite[i][2] = '\0'; } dataCollector->write(10, ctUInt64, dimensions, Selection(gridSize), "deep/folders/data", dataWrite); @@ -97,6 +104,13 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize borderSize), "deep/folders/data_bool_without_borders", boolWrite); datasetNames.insert("deep/folders/data_bool_without_borders"); + dataCollector->write(10, ctString3, dimensions, Selection(gridSize), "deep/folders/data_str", strWrite); + datasetNames.insert("deep/folders/data_str"); + + dataCollector->write(20, ctString3, dimensions, Selection(gridSize, smallGridSize, + borderSize), "deep/folders/data_str_without_borders", strWrite); + datasetNames.insert("deep/folders/data_str_without_borders"); + dataCollector->close(); // first part of the test: read data with borders to a cleared @@ -125,7 +139,7 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize for (uint32_t j = 0; j < numIDs; ++j) { dataCollector->getEntriesForID(ids[j], NULL, &numEntries); - CPPUNIT_ASSERT(numEntries == 2); + CPPUNIT_ASSERT(numEntries == 3); entries = new DataCollector::DCEntry[numEntries]; dataCollector->getEntriesForID(ids[j], entries, NULL); @@ -145,10 +159,14 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize uint64_t *dataRead = new uint64_t[bufferSize]; bool *boolRead = new bool[bufferSize]; + ccc *strRead = new ccc[bufferSize]; for (uint64_t i = 0; i < bufferSize; i++) { dataRead[i] = UINT64_MAX; boolRead[i] = false; + strRead[i][0] = 'Q'; + strRead[i][1] = 'P'; + strRead[i][2] = '\0'; } Dimensions resultSize; @@ -159,6 +177,8 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize dataCollector->read(10, "deep/folders/data_bool", resultSize, boolRead); + dataCollector->read(10, "deep/folders/data_str", resultSize, strRead); + for (uint64_t i = 0; i < bufferSize; i++) { if (dataRead[i] != dataWrite[i]) @@ -173,6 +193,14 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize { #if defined TESTS_DEBUG std::cout << i << ": " << boolRead[i] << " != expected " << boolWrite[i] << std::endl; +#endif + resultsCorrect = false; + break; + } + if (strcmp(strRead[i], strWrite[i]) != 0) + { +#if defined TESTS_DEBUG + std::cout << i << ": " << strRead[i] << " != expected " << strWrite[i] << std::endl; #endif resultsCorrect = false; break; @@ -182,6 +210,8 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize delete[] dataRead; delete[] boolRead; delete[] boolWrite; + delete[] strRead; + delete[] strWrite; CPPUNIT_ASSERT_MESSAGE("simple write/read failed", resultsCorrect); diff --git a/tests/include/SimpleDataTest.h b/tests/include/SimpleDataTest.h index 5152b53..f4192e4 100644 --- a/tests/include/SimpleDataTest.h +++ b/tests/include/SimpleDataTest.h @@ -64,6 +64,7 @@ class SimpleDataTest : public CPPUNIT_NS::TestFixture ColTypeUInt32 ctUInt32; ColTypeUInt64 ctUInt64; ColTypeBool ctBool; + ColTypeString ctString3; DataCollector *dataCollector; }; From 5a019c43030c374fabdfe752cb2c77b23407289a Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Wed, 15 Apr 2015 00:20:05 +0200 Subject: [PATCH 10/47] Add Parallel VL String Attr Write The note in https://www.hdfgroup.org/hdf5-quest.html#pvl seems only to apply for data sets: "Does Parallel HDF5 support variable length datatypes ? Currently, it does NOT." --- tests/Parallel_AttributesTest.cpp | 18 +++++++++++++++++- tests/include/Parallel_AttributesTest.h | 2 ++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/Parallel_AttributesTest.cpp b/tests/Parallel_AttributesTest.cpp index 7630878..2fa92cb 100644 --- a/tests/Parallel_AttributesTest.cpp +++ b/tests/Parallel_AttributesTest.cpp @@ -38,7 +38,8 @@ using namespace splash; #define MPI_SIZE_X 2 #define MPI_SIZE_Y 2 -Parallel_AttributesTest::Parallel_AttributesTest() +Parallel_AttributesTest::Parallel_AttributesTest() : + ctString5(5) { srand(time(NULL)); @@ -95,6 +96,13 @@ void Parallel_AttributesTest::testDataAttributes() char c = 'Y'; dataCollector->writeAttribute(0, ctChar, "attr/attr2/attr3", "my_char", &c); + /* variable length string */ + const char *string_attr = {"My first c-string."}; + dataCollector->writeAttribute(0, ctString, NULL, "my_string", &string_attr); + /* fixed length string */ + const char string_attr5[5] = {"ABCD"}; + dataCollector->writeAttribute(0, ctString5, NULL, "my_string5", &string_attr5); + delete[] dummy_data; dummy_data = NULL; @@ -127,6 +135,14 @@ void Parallel_AttributesTest::testDataAttributes() CPPUNIT_ASSERT(sum == old_sum); CPPUNIT_ASSERT(c == 'Y'); + char* string_read; + dataCollector->readAttribute(0, NULL, "my_string", &string_read); + char string_read5[5]; + dataCollector->readAttribute(0, NULL, "my_string5", &string_read5); + + CPPUNIT_ASSERT(strcmp(string_read, string_attr) == 0); + CPPUNIT_ASSERT(strcmp(string_read5, string_attr5) == 0); + dataCollector->finalize(); dataCollector->close(); delete dataCollector; diff --git a/tests/include/Parallel_AttributesTest.h b/tests/include/Parallel_AttributesTest.h index c807295..bb3da8f 100644 --- a/tests/include/Parallel_AttributesTest.h +++ b/tests/include/Parallel_AttributesTest.h @@ -49,6 +49,8 @@ class Parallel_AttributesTest : public CPPUNIT_NS::TestFixture ColTypeInt2 ctInt2; ColTypeInt3Array ctInt3Array; ColTypeDimArray ctDimArray; + ColTypeString ctString; + ColTypeString ctString5; int mpiRank; }; From dbe598f0d78a291ed2391e59f07421a7b7df40fd Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Wed, 15 Apr 2015 00:23:10 +0200 Subject: [PATCH 11/47] Bump File Format to 3.1 3.0 was not released outside of `dev` making minor change which is for all but reading the new types compatible adequate. --- src/include/splash/version.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/splash/version.hpp b/src/include/splash/version.hpp index 04fc3fb..32200aa 100644 --- a/src/include/splash/version.hpp +++ b/src/include/splash/version.hpp @@ -32,6 +32,6 @@ * changes in the minor number have to be backwards compatible */ #define SPLASH_FILE_FORMAT_MAJOR 3 -#define SPLASH_FILE_FORMAT_MINOR 0 +#define SPLASH_FILE_FORMAT_MINOR 1 #endif /* VERSION_HPP */ From 7752518ea375493160444f0f1ac7880891ddb670 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Wed, 15 Apr 2015 09:52:24 +0200 Subject: [PATCH 12/47] Parallel_AttributesTest: Add missing include `#include ` for `strcmp` --- tests/Parallel_AttributesTest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Parallel_AttributesTest.cpp b/tests/Parallel_AttributesTest.cpp index 2fa92cb..5f0c4ca 100644 --- a/tests/Parallel_AttributesTest.cpp +++ b/tests/Parallel_AttributesTest.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include CPPUNIT_TEST_SUITE_REGISTRATION(Parallel_AttributesTest); From 1b9b28b5f4db089eed6ca46b4629bab1ed1cba82 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Thu, 30 Apr 2015 19:41:17 +0200 Subject: [PATCH 13/47] Define Length of ColTypeString as in strlen() thx for @f-schmitt-zih for the feedback! also: adds more comments to the tests about the absolutely necessary '\0' terminator for HDF5 (tested: fails without it!) as described in https://hdfgroup.org/HDF5/doc/RM/RM_H5T.html#Datatype-SetSize --- .travis.yml | 2 ++ src/include/splash/basetypes/ColTypeString.hpp | 12 ++++++++---- tests/AttributesTest.cpp | 16 ++++++++-------- tests/Parallel_AttributesTest.cpp | 16 ++++++++-------- tests/SimpleDataTest.cpp | 13 ++++++++++--- tests/include/AttributesTest.h | 2 +- tests/include/Parallel_AttributesTest.h | 2 +- tests/include/SimpleDataTest.h | 2 +- tests/readBoolChar.py | 8 ++++---- 9 files changed, 43 insertions(+), 30 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6130842..5801f3a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,4 +65,6 @@ before_script: - export HDF5_DIR=/usr - export C_INCLUDE_PATH=/usr/lib/openmpi/include - pip install --user h5py + - python -c "import numpy; print(numpy.version.version)" + - python -c "import h5py; print(h5py.version.version)" - mkdir -p $BUILD ~/lib diff --git a/src/include/splash/basetypes/ColTypeString.hpp b/src/include/splash/basetypes/ColTypeString.hpp index 207c927..b6cfdc1 100644 --- a/src/include/splash/basetypes/ColTypeString.hpp +++ b/src/include/splash/basetypes/ColTypeString.hpp @@ -28,9 +28,12 @@ namespace splash { /** Variable and fixed length strings * - * Since C-strings are NULL-terminated, len must be +1 - * of the actual length of the string for fixed length strings. + * Do not forget that C-strings are NULL-terminated. + * As in 's strlen() our length in the API + * does not count the terminator, but c-strings still MUST + * end with it, else HDF5 write/reads will fail. * + * \see https://hdfgroup.org/HDF5/doc/RM/RM_H5T.html#Datatype-SetSize * \see http://hdfgroup.org/HDF5/doc/RM/RM_H5T.html#CreateVLString */ class ColTypeString : public CollectionType @@ -46,7 +49,9 @@ namespace splash ColTypeString(size_t len) { this->type = H5Tcopy(H5T_C_S1); - H5Tset_size(this->type, len); + /* HDF5 requires space for the \0-terminator character, + * otherwise it will not be stored or retrieved */ + H5Tset_size(this->type, len + 1); } ~ColTypeString() @@ -69,4 +74,3 @@ namespace splash } #endif /* COLTYPESTRING_H */ - diff --git a/tests/AttributesTest.cpp b/tests/AttributesTest.cpp index feaa4ca..adc3887 100644 --- a/tests/AttributesTest.cpp +++ b/tests/AttributesTest.cpp @@ -39,7 +39,7 @@ using namespace splash; #define TEST_FILE2 "h5/attributes_array" AttributesTest::AttributesTest() : -ctString5(5) +ctString4(4) { srand(time(NULL)); @@ -79,12 +79,12 @@ void AttributesTest::testDataAttributes() dataCollector->writeAttribute(10, ctInt, NULL, "timestep", &sum2); - /* variable length string */ + /* variable length string, '\0' terminated */ const char *string_attr = {"My first c-string."}; dataCollector->writeAttribute(10, ctString, NULL, "my_string", &string_attr); - /* fixed length string */ - const char string_attr5[5] = {"ABCD"}; - dataCollector->writeAttribute(10, ctString5, NULL, "my_string5", &string_attr5); + /* fixed length string, '\0' terminated */ + const char string_attr4[5] = {"ABCD"}; + dataCollector->writeAttribute(10, ctString4, NULL, "my_string4", &string_attr4); CPPUNIT_ASSERT_THROW(dataCollector->writeAttribute(10, ctInt, NULL, NULL, &sum2), DCException); @@ -124,11 +124,11 @@ void AttributesTest::testDataAttributes() char* string_read; dataCollector->readAttribute(10, NULL, "my_string", &string_read); - char string_read5[5]; - dataCollector->readAttribute(10, NULL, "my_string5", &string_read5); + char string_read4[5]; + dataCollector->readAttribute(10, NULL, "my_string4", &string_read4); CPPUNIT_ASSERT(strcmp(string_read, string_attr) == 0); - CPPUNIT_ASSERT(strcmp(string_read5, string_attr5) == 0); + CPPUNIT_ASSERT(strcmp(string_read4, string_attr4) == 0); Dimensions src_data; dataCollector->read(0, "datasets/my_dataset", src_data, dummy_data); diff --git a/tests/Parallel_AttributesTest.cpp b/tests/Parallel_AttributesTest.cpp index 5f0c4ca..cbaa54d 100644 --- a/tests/Parallel_AttributesTest.cpp +++ b/tests/Parallel_AttributesTest.cpp @@ -40,7 +40,7 @@ using namespace splash; #define MPI_SIZE_Y 2 Parallel_AttributesTest::Parallel_AttributesTest() : - ctString5(5) + ctString4(4) { srand(time(NULL)); @@ -97,12 +97,12 @@ void Parallel_AttributesTest::testDataAttributes() char c = 'Y'; dataCollector->writeAttribute(0, ctChar, "attr/attr2/attr3", "my_char", &c); - /* variable length string */ + /* variable length string, '\0' terminated */ const char *string_attr = {"My first c-string."}; dataCollector->writeAttribute(0, ctString, NULL, "my_string", &string_attr); - /* fixed length string */ - const char string_attr5[5] = {"ABCD"}; - dataCollector->writeAttribute(0, ctString5, NULL, "my_string5", &string_attr5); + /* fixed length string, '\0' terminated */ + const char string_attr4[5] = {"ABCD"}; + dataCollector->writeAttribute(0, ctString4, NULL, "my_string4", &string_attr4); delete[] dummy_data; dummy_data = NULL; @@ -138,11 +138,11 @@ void Parallel_AttributesTest::testDataAttributes() char* string_read; dataCollector->readAttribute(0, NULL, "my_string", &string_read); - char string_read5[5]; - dataCollector->readAttribute(0, NULL, "my_string5", &string_read5); + char string_read4[5]; + dataCollector->readAttribute(0, NULL, "my_string4", &string_read4); CPPUNIT_ASSERT(strcmp(string_read, string_attr) == 0); - CPPUNIT_ASSERT(strcmp(string_read5, string_attr5) == 0); + CPPUNIT_ASSERT(strcmp(string_read4, string_attr4) == 0); dataCollector->finalize(); dataCollector->close(); diff --git a/tests/SimpleDataTest.cpp b/tests/SimpleDataTest.cpp index 9671bdf..a074406 100644 --- a/tests/SimpleDataTest.cpp +++ b/tests/SimpleDataTest.cpp @@ -43,7 +43,7 @@ SimpleDataTest::SimpleDataTest() : ctUInt32(), ctUInt64(), ctBool(), -ctString3(3) +ctString2(2) { dataCollector = new SerialDataCollector(10); srand(time(NULL)); @@ -88,6 +88,13 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize strWrite[i][0] = 'A'; strWrite[i][1] = 'B'; strWrite[i][2] = '\0'; + /* the NULL terminator is EXTREMELY important for HDF5, else the data + * will not be written/read correctly. Its the same for 's + * strlen() function - make sure strWrite[i] is a valid '\0' terminated + * c-string! + * + * \see https://hdfgroup.org/HDF5/doc/RM/RM_H5T.html#Datatype-SetSize */ + CPPUNIT_ASSERT(strlen(strWrite[i]) == 2); } dataCollector->write(10, ctUInt64, dimensions, Selection(gridSize), "deep/folders/data", dataWrite); @@ -104,10 +111,10 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize borderSize), "deep/folders/data_bool_without_borders", boolWrite); datasetNames.insert("deep/folders/data_bool_without_borders"); - dataCollector->write(10, ctString3, dimensions, Selection(gridSize), "deep/folders/data_str", strWrite); + dataCollector->write(10, ctString2, dimensions, Selection(gridSize), "deep/folders/data_str", strWrite); datasetNames.insert("deep/folders/data_str"); - dataCollector->write(20, ctString3, dimensions, Selection(gridSize, smallGridSize, + dataCollector->write(20, ctString2, dimensions, Selection(gridSize, smallGridSize, borderSize), "deep/folders/data_str_without_borders", strWrite); datasetNames.insert("deep/folders/data_str_without_borders"); diff --git a/tests/include/AttributesTest.h b/tests/include/AttributesTest.h index 50a52c6..65fd676 100644 --- a/tests/include/AttributesTest.h +++ b/tests/include/AttributesTest.h @@ -51,7 +51,7 @@ class AttributesTest : public CPPUNIT_NS::TestFixture ColTypeInt3Array ctInt3Array; ColTypeDimArray ctDimArray; ColTypeString ctString; - ColTypeString ctString5; + ColTypeString ctString4; DataCollector *dataCollector; }; diff --git a/tests/include/Parallel_AttributesTest.h b/tests/include/Parallel_AttributesTest.h index bb3da8f..07bfa43 100644 --- a/tests/include/Parallel_AttributesTest.h +++ b/tests/include/Parallel_AttributesTest.h @@ -50,7 +50,7 @@ class Parallel_AttributesTest : public CPPUNIT_NS::TestFixture ColTypeInt3Array ctInt3Array; ColTypeDimArray ctDimArray; ColTypeString ctString; - ColTypeString ctString5; + ColTypeString ctString4; int mpiRank; }; diff --git a/tests/include/SimpleDataTest.h b/tests/include/SimpleDataTest.h index f4192e4..552c510 100644 --- a/tests/include/SimpleDataTest.h +++ b/tests/include/SimpleDataTest.h @@ -64,7 +64,7 @@ class SimpleDataTest : public CPPUNIT_NS::TestFixture ColTypeUInt32 ctUInt32; ColTypeUInt64 ctUInt64; ColTypeBool ctBool; - ColTypeString ctString3; + ColTypeString ctString2; DataCollector *dataCollector; }; diff --git a/tests/readBoolChar.py b/tests/readBoolChar.py index 048c94c..2ff24cb 100755 --- a/tests/readBoolChar.py +++ b/tests/readBoolChar.py @@ -67,13 +67,13 @@ exit(1) # fixed length string compatible attributes -s5 = f["/data/10"].attrs["my_string5"] -print(s5, type(s5), s5.dtype) +s4 = f["/data/10"].attrs["my_string4"] +print(s4, type(s4), s4.dtype) -if not s5 == "ABCD": +if not s4 == "ABCD": exit(1) -if not type(s5) is np.string_: +if not type(s4) is np.string_: exit(1) From faf7583945a2d3d41936f97a57b7c38590b31de2 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Thu, 30 Apr 2015 21:06:49 +0200 Subject: [PATCH 14/47] ColTypeString::getSize() as strlen() make getSize for fixed length strings to behave like strlen() so setting and getting the length of a c-string is defined in the same way. for variable length string, we forward the behaviour of HDF5, which returns the size of a char pointer for all lengths. also, we need to use the API H5Tis_variable_str to check the type correctly (the previous check was wrong). --- src/include/splash/basetypes/ColTypeString.hpp | 9 +++++---- tests/SimpleDataTest.cpp | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/include/splash/basetypes/ColTypeString.hpp b/src/include/splash/basetypes/ColTypeString.hpp index b6cfdc1..6084fc1 100644 --- a/src/include/splash/basetypes/ColTypeString.hpp +++ b/src/include/splash/basetypes/ColTypeString.hpp @@ -63,11 +63,12 @@ namespace splash { size_t myElements = H5Tget_size(this->type); - // for H5T_VARIABLE irrelevant ? - if( myElements != H5T_VARIABLE ) - return sizeof(char) * myElements; + /* for variable length string the size is first known after reading + * the actual data or attribute, so we forward HDF5's behaviour */ + if( H5Tis_variable_str(this->type) ) + return myElements; /* == sizeof(char*) see H5Tget_size description */ else - return sizeof(char); + return sizeof(char) * (myElements - 1); /* just as strlen() */ } }; diff --git a/tests/SimpleDataTest.cpp b/tests/SimpleDataTest.cpp index a074406..9907663 100644 --- a/tests/SimpleDataTest.cpp +++ b/tests/SimpleDataTest.cpp @@ -171,9 +171,9 @@ bool SimpleDataTest::subtestWriteRead(Dimensions gridSize, Dimensions borderSize { dataRead[i] = UINT64_MAX; boolRead[i] = false; - strRead[i][0] = 'Q'; - strRead[i][1] = 'P'; - strRead[i][2] = '\0'; + strRead[i][0] = 'P'; + strRead[i][1] = 'Q'; + strRead[i][2] = 'R'; /* reads should write a '\0' in here */ } Dimensions resultSize; From e0639d89e942a6335cf1e5d3ddc31d7d2f24e0df Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Thu, 30 Apr 2015 21:14:13 +0200 Subject: [PATCH 15/47] CMake: Add minimum version of HDF5 Let CMake check the version of HDF5. --- CMakeLists.txt | 2 +- examples/CMakeLists.txt | 2 +- tests/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 11fe54d..7d6dce7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,7 +70,7 @@ MESSAGE(STATUS "Building libSplash version ${SPLASH_VERSION}") #------------------------------------------------------------------------------- # HDF5 is required package -FIND_PACKAGE(HDF5 REQUIRED) +FIND_PACKAGE(HDF5 1.8.6 REQUIRED) INCLUDE_DIRECTORIES(SYSTEM ${HDF5_INCLUDE_DIR}) # check if static version of HDF5 is used diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a13f5e8..8668198 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -52,7 +52,7 @@ ENDFOREACH() #------------------------------------------------------------------------------- # HDF5 is required -FIND_PACKAGE(HDF5 REQUIRED) +FIND_PACKAGE(HDF5 1.8.6 REQUIRED) INCLUDE_DIRECTORIES(${HDF5_INCLUDE_DIR}) SET(LIBS ${LIBS} ${HDF5_LIBRARIES}) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c79cc02..659e090 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -35,7 +35,7 @@ OPTION(WITH_MPI "use MPI-based tests" OFF) #------------------------------------------------------------------------------- # HDF5 is required package -FIND_PACKAGE(HDF5 REQUIRED) +FIND_PACKAGE(HDF5 1.8.6 REQUIRED) INCLUDE_DIRECTORIES(${HDF5_INCLUDE_DIR}) IF(WITH_MPI) From c8dac8b881ba32c6b7cacbb56b43c41608813464 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Mon, 4 May 2015 19:33:43 +0200 Subject: [PATCH 16/47] Travis: Run tests in "script" After-Script non-zero return types do NOT mark the build as failed: http://docs.travis-ci.com/user/build-lifecycle/ --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5801f3a..09bc161 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,8 +32,7 @@ script: # compile and run tests/ - cmake -DWITH_MPI=$SPLASHMPI $SRC/tests - make - -after_script: +# run tests - $SRC/tests/run_tests $BUILD - $SRC/tests/run_parallel_tests $BUILD From a379a452c3b134de439d8ef2e410b8566cfac77b Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Mon, 4 May 2015 20:33:54 +0200 Subject: [PATCH 17/47] Use the define DSP_DIM_MAX instead of 3 Reduce magic numbers by using the actual define of `DSP_DIM_MAX`. Even if that does not itself increase flexibility, it should already help reducing the cost if someone wants to generalize the implementation in the future (and: `DSP_DIM_MAX` was basically unused so far). --- src/DomainCollector.cpp | 19 ++++++++-------- src/ParallelDataCollector.cpp | 23 ++++++++++---------- src/SerialDataCollector.cpp | 2 +- src/include/splash/Dimensions.hpp | 11 +++++----- src/include/splash/core/DCHelper.hpp | 5 +++-- src/include/splash/domains/DataContainer.hpp | 7 +++--- 6 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/DomainCollector.cpp b/src/DomainCollector.cpp index 8ddb6fd..186f821 100644 --- a/src/DomainCollector.cpp +++ b/src/DomainCollector.cpp @@ -1,5 +1,5 @@ /** - * Copyright 2013-2014 Felix Schmitt, Axel Huebl + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -504,7 +505,7 @@ namespace splash minDom.getOffset().toString().c_str(), maxDom.getOffset().toString().c_str()); - for (size_t i = 0; i < 3; ++i) + for (size_t i = 0; i < DSP_DIM_MAX; ++i) { // zero still between min and max? if (minDom.getOffset()[i] > maxDom.getOffset()[i]) @@ -531,7 +532,7 @@ namespace splash Domain lastDom; readDomainInfoForRank(mpi_size - Dimensions(1, 1, 1), id, name, Domain(Dimensions(0, 0, 0), Dimensions(0, 0, 0)), lastDom); - for (size_t i = 0; i < 3; ++i) + for (size_t i = 0; i < DSP_DIM_MAX; ++i) { if (request_offset[i] <= lastDom.getBack()[i]) { @@ -564,7 +565,7 @@ namespace splash last_mpi_pos = current_mpi_pos; // set current_mpi_pos to be the 'center' between min_dims and max_dims - for (size_t i = 0; i < 3; ++i) + for (size_t i = 0; i < DSP_DIM_MAX; ++i) { current_mpi_pos[i] = min_dims[i] + ceil(((double) max_dims[i] - (double) min_dims[i]) / 2.0); @@ -577,7 +578,7 @@ namespace splash break; } - for (size_t i = 0; i < 3; ++i) + for (size_t i = 0; i < DSP_DIM_MAX; ++i) { if (request_offset[i] >= file_domain.getOffset()[i]) min_dims[i] = current_mpi_pos[i]; @@ -599,7 +600,7 @@ namespace splash // the file domain is added to the DataContainer. // set new min_dims to top-left corner - for (size_t i = 0; i < 3; ++i) + for (size_t i = 0; i < DSP_DIM_MAX; ++i) max_dims[i] = (current_mpi_pos[i] + mpi_size[i] - 1) % mpi_size[i]; min_dims = current_mpi_pos; @@ -794,10 +795,10 @@ namespace splash readAttribute(id, dataName, DOMCOL_ATTR_GLOBAL_SIZE, data, mpiPosition); } catch (DCException) { - hsize_t local_size[3]; + hsize_t local_size[DSP_DIM_MAX]; readAttribute(id, dataName, DOMCOL_ATTR_SIZE, local_size, mpiPosition); - for (int i = 0; i < 3; ++i) + for (int i = 0; i < DSP_DIM_MAX; ++i) data[i] = mpiTopology[i] * local_size[i]; } } @@ -813,7 +814,7 @@ namespace splash readAttribute(id, dataName, DOMCOL_ATTR_GLOBAL_OFFSET, data, mpiPosition); } catch (DCException) { - for (int i = 0; i < 3; ++i) + for (int i = 0; i < DSP_DIM_MAX; ++i) data[i] = 0; } } diff --git a/src/ParallelDataCollector.cpp b/src/ParallelDataCollector.cpp index 186ad57..6b34d23 100644 --- a/src/ParallelDataCollector.cpp +++ b/src/ParallelDataCollector.cpp @@ -1,5 +1,5 @@ /** - * Copyright 2013-2014 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -544,7 +545,7 @@ namespace splash if (fileStatus == FST_CLOSED || fileStatus == FST_READING) throw DCException(getExceptionString("write", "this access is not permitted")); - if (ndims < 1 || ndims > 3) + if (ndims < 1 || ndims > DSP_DIM_MAX) throw DCException(getExceptionString("write", "maximum dimension is invalid")); // create group for this id/iteration @@ -571,7 +572,7 @@ namespace splash if (fileStatus == FST_CLOSED || fileStatus == FST_READING) throw DCException(getExceptionString("write", "this access is not permitted")); - if (ndims < 1 || ndims > 3) + if (ndims < 1 || ndims > DSP_DIM_MAX) throw DCException(getExceptionString("write", "maximum dimension is invalid")); reserveInternal(id, globalSize, ndims, type, name); @@ -591,7 +592,7 @@ namespace splash if (fileStatus == FST_CLOSED || fileStatus == FST_READING) throw DCException(getExceptionString("write", "this access is not permitted")); - if (ndims < 1 || ndims > 3) + if (ndims < 1 || ndims > DSP_DIM_MAX) throw DCException(getExceptionString("write", "maximum dimension is invalid")); Dimensions global_size, global_offset; @@ -619,7 +620,7 @@ namespace splash if (fileStatus == FST_CLOSED || fileStatus == FST_READING) throw DCException(getExceptionString("append", "this access is not permitted")); - if (ndims < 1 || ndims > 3) + if (ndims < 1 || ndims > DSP_DIM_MAX) throw DCException(getExceptionString("append", "maximum dimension is invalid")); // create group for this id/iteration @@ -928,14 +929,14 @@ namespace splash Dimensions &globalSize, Dimensions &globalOffset) throw (DCException) { - uint64_t write_sizes[options.mpiSize * 3]; - uint64_t local_write_size[3] = {localSize[0], localSize[1], localSize[2]}; + uint64_t write_sizes[options.mpiSize * DSP_DIM_MAX]; + uint64_t local_write_size[DSP_DIM_MAX] = {localSize[0], localSize[1], localSize[2]}; globalSize.set(1, 1, 1); globalOffset.set(0, 0, 0); - if (MPI_Allgather(local_write_size, 3, MPI_UNSIGNED_LONG_LONG, - write_sizes, 3, MPI_UNSIGNED_LONG_LONG, options.mpiComm) != MPI_SUCCESS) + if (MPI_Allgather(local_write_size, DSP_DIM_MAX, MPI_UNSIGNED_LONG_LONG, + write_sizes, DSP_DIM_MAX, MPI_UNSIGNED_LONG_LONG, options.mpiComm) != MPI_SUCCESS) throw DCException(getExceptionString("gatherMPIWrites", "MPI_Allgather failed", NULL)); @@ -971,9 +972,9 @@ namespace splash index = dim * tmp_mpi_topology[0] * tmp_mpi_topology[1]; } - globalSize[i] += write_sizes[index * 3 + i]; + globalSize[i] += write_sizes[index * DSP_DIM_MAX + i]; if (dim < tmp_mpi_pos[i]) - globalOffset[i] += write_sizes[index * 3 + i]; + globalOffset[i] += write_sizes[index * DSP_DIM_MAX + i]; } } } diff --git a/src/SerialDataCollector.cpp b/src/SerialDataCollector.cpp index f304999..7dd22c7 100644 --- a/src/SerialDataCollector.cpp +++ b/src/SerialDataCollector.cpp @@ -404,7 +404,7 @@ namespace splash if (fileStatus == FST_CLOSED || fileStatus == FST_READING || fileStatus == FST_MERGING) throw DCException(getExceptionString("write", "this access is not permitted")); - if (ndims < 1 || ndims > 3) + if (ndims < 1 || ndims > DSP_DIM_MAX) throw DCException(getExceptionString("write", "maximum dimension is invalid")); if (id > this->maxID) diff --git a/src/include/splash/Dimensions.hpp b/src/include/splash/Dimensions.hpp index e1914d5..75f6899 100644 --- a/src/include/splash/Dimensions.hpp +++ b/src/include/splash/Dimensions.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013 Felix Schmitt, Axel Huebl + * Copyright 2013, 2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -37,7 +38,7 @@ namespace splash class Dimensions { private: - hsize_t s[3]; + hsize_t s[DSP_DIM_MAX]; public: /** @@ -208,7 +209,7 @@ namespace splash */ inline static size_t getSize() { - return 3 * sizeof (hsize_t); + return DSP_DIM_MAX * sizeof (hsize_t); } /** @@ -250,7 +251,7 @@ namespace splash */ inline uint32_t getDims(void) const { - uint32_t dims = 3; + uint32_t dims = DSP_DIM_MAX; if (s[2] == 1) { dims = 2; @@ -268,7 +269,7 @@ namespace splash void swapDims(uint32_t dims) { hsize_t tmp1 = s[0]; - hsize_t tmp2[3] = {s[2], s[1], s[0]}; + hsize_t tmp2[DSP_DIM_MAX] = {s[2], s[1], s[0]}; switch (dims) { diff --git a/src/include/splash/core/DCHelper.hpp b/src/include/splash/core/DCHelper.hpp index bdf682d..f4f55cb 100644 --- a/src/include/splash/core/DCHelper.hpp +++ b/src/include/splash/core/DCHelper.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013 Felix Schmitt + * Copyright 2013, 2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -65,7 +66,7 @@ namespace splash return; hsize_t tmp1; - hsize_t tmp3[3]; + hsize_t tmp3[DSP_DIM_MAX]; switch (rank) { diff --git a/src/include/splash/domains/DataContainer.hpp b/src/include/splash/domains/DataContainer.hpp index 75331b7..eae7595 100644 --- a/src/include/splash/domains/DataContainer.hpp +++ b/src/include/splash/domains/DataContainer.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013 Felix Schmitt + * Copyright 2013, 2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -7,7 +7,8 @@ * it under the terms of of either the GNU General Public License or * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -82,7 +83,7 @@ namespace splash const Dimensions &entryOffset = entry->getOffset(); const Dimensions entryBack = entry->getBack(); // last index INSIDE - for (uint32_t i = 0; i < 3; ++i) + for (uint32_t i = 0; i < DSP_DIM_MAX; ++i) { offset[i] = std::min(entryOffset[i], offset[i]); size[i] = std::max(entryBack[i] + 1 - offset[i], size[i]); From 65e73573da0721fa4fde86596cc835c963fe568d Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Wed, 6 May 2015 15:59:59 +0200 Subject: [PATCH 18/47] Move DSP_DIM_MAX to Dimensions.hpp It all originates here :) --- src/include/splash/Dimensions.hpp | 2 ++ src/include/splash/sdc_defines.hpp | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/splash/Dimensions.hpp b/src/include/splash/Dimensions.hpp index 75f6899..4be9208 100644 --- a/src/include/splash/Dimensions.hpp +++ b/src/include/splash/Dimensions.hpp @@ -28,6 +28,8 @@ #include #include +#define DSP_DIM_MAX 3 + namespace splash { diff --git a/src/include/splash/sdc_defines.hpp b/src/include/splash/sdc_defines.hpp index fcad15f..330904c 100644 --- a/src/include/splash/sdc_defines.hpp +++ b/src/include/splash/sdc_defines.hpp @@ -39,8 +39,6 @@ namespace splash #define SDC_ATTR_GRID_SIZE "grid_size" #define SDC_ATTR_SIZE "client_size" #define SDC_ATTR_COMPRESSION "compression" - -#define DSP_DIM_MAX 3 } #endif /* SDC_DEFINES_H */ From df4fbb85fde350d7cd1dcffa3a89be16eef9f5fe Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Mon, 4 May 2015 15:40:01 +0200 Subject: [PATCH 19/47] Close #170 Simple Dataspaces for Attributes Close #170 by implementing additional interfaces to write attributes (global and per iteration) that can be used with simple HDF5 dataspaces. --- src/DCAttribute.cpp | 25 ++++++++++-- src/ParallelDataCollector.cpp | 32 +++++++++++++-- src/SerialDataCollector.cpp | 33 ++++++++++++++-- src/include/splash/DataCollector.hpp | 39 ++++++++++++++++++- src/include/splash/IParallelDataCollector.hpp | 17 +++++++- src/include/splash/ParallelDataCollector.hpp | 26 ++++++++++++- src/include/splash/SerialDataCollector.hpp | 16 +++++++- src/include/splash/core/DCAttribute.hpp | 24 +++++++++++- tests/AttributesTest.cpp | 14 ++++++- tests/Parallel_AttributesTest.cpp | 10 +++-- tests/include/AttributesTest.h | 1 + tests/readBoolChar.py | 24 +++++++++++- 12 files changed, 236 insertions(+), 25 deletions(-) diff --git a/src/DCAttribute.cpp b/src/DCAttribute.cpp index aa7e3f6..0e2e2f1 100644 --- a/src/DCAttribute.cpp +++ b/src/DCAttribute.cpp @@ -1,5 +1,5 @@ /** - * Copyright 2013 Felix Schmitt + * Copyright 2013, 2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -61,15 +61,27 @@ namespace splash H5Aclose(attr); } - void DCAttribute::writeAttribute(const char* name, const hid_t type, hid_t parent, const void* src) + void DCAttribute::writeAttribute(const char* name, const hid_t type, hid_t parent, + uint32_t ndims, const Dimensions dims, const void* src) throw (DCException) { + if (name == NULL) + throw DCException(getExceptionString("attribute", "parameter name is NULL")); + + if (ndims < 1u || ndims > 3u) + throw DCException(getExceptionString(name, "maximum dimension is invalid")); + hid_t attr = -1; if (H5Aexists(parent, name)) attr = H5Aopen(parent, name, H5P_DEFAULT); else { - hid_t dsp = H5Screate(H5S_SCALAR); + hid_t dsp; + if( ndims == 1 && dims.getScalarSize() == 1 ) + dsp = H5Screate(H5S_SCALAR); + else + dsp = H5Screate_simple( ndims, dims.getPointer(), dims.getPointer() ); + attr = H5Acreate(parent, name, type, dsp, H5P_DEFAULT, H5P_DEFAULT); H5Sclose(dsp); } @@ -86,4 +98,11 @@ namespace splash H5Aclose(attr); } + void DCAttribute::writeAttribute(const char* name, const hid_t type, hid_t parent, const void* src) + throw (DCException) + { + const Dimensions dims(1, 1, 1); + writeAttribute(name, type, parent, 1u, dims, src); + } + } diff --git a/src/ParallelDataCollector.cpp b/src/ParallelDataCollector.cpp index 6b34d23..7cb1a69 100644 --- a/src/ParallelDataCollector.cpp +++ b/src/ParallelDataCollector.cpp @@ -339,6 +339,18 @@ namespace splash const char *name, const void* data) throw (DCException) + { + const Dimensions dims(1, 1, 1); + writeGlobalAttribute(id, type, name, 1u, dims, data); + } + + void ParallelDataCollector::writeGlobalAttribute(int32_t id, + const CollectionType& type, + const char *name, + uint32_t ndims, + const Dimensions dims, + const void* data) + throw (DCException) { if (name == NULL || data == NULL) throw DCException(getExceptionString("writeGlobalAttribute", "a parameter was null")); @@ -351,7 +363,7 @@ namespace splash try { - DCAttribute::writeAttribute(name, type.getDataType(), group_custom.getHandle(), data); + DCAttribute::writeAttribute(name, type.getDataType(), group_custom.getHandle(), ndims, dims, data); } catch (DCException e) { log_msg(0, "Exception: %s", e.what()); @@ -421,6 +433,20 @@ namespace splash const char *attrName, const void* data) throw (DCException) + { + const Dimensions dims(1, 1, 1); + writeAttribute( id, type, dataName, attrName, + 1u, dims, data); + } + + void ParallelDataCollector::writeAttribute(int32_t id, + const CollectionType& type, + const char *dataName, + const char *attrName, + uint32_t ndims, + const Dimensions dims, + const void* data) + throw (DCException) { if (attrName == NULL || data == NULL) throw DCException(getExceptionString("writeAttribute", "a parameter was null")); @@ -455,7 +481,7 @@ namespace splash try { - DCAttribute::writeAttribute(attrName, type.getDataType(), obj_id, data); + DCAttribute::writeAttribute(attrName, type.getDataType(), obj_id, ndims, dims, data); } catch (DCException) { H5Oclose(obj_id); @@ -466,7 +492,7 @@ namespace splash { // attach attribute to the iteration group.openCreate(handles.get(id), group_path); - DCAttribute::writeAttribute(attrName, type.getDataType(), group.getHandle(), data); + DCAttribute::writeAttribute(attrName, type.getDataType(), group.getHandle(), ndims, dims, data); } } diff --git a/src/SerialDataCollector.cpp b/src/SerialDataCollector.cpp index 7dd22c7..d01df24 100644 --- a/src/SerialDataCollector.cpp +++ b/src/SerialDataCollector.cpp @@ -1,5 +1,5 @@ /** - * Copyright 2013-2014 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -229,6 +229,17 @@ namespace splash const char* name, const void* data) throw (DCException) + { + const Dimensions dims(1, 1, 1); + writeGlobalAttribute(type, name, 1u, dims, data); + } + + void SerialDataCollector::writeGlobalAttribute(const CollectionType& type, + const char* name, + uint32_t ndims, + const Dimensions dims, + const void* data) + throw (DCException) { if (name == NULL || data == NULL) throw DCException(getExceptionString("writeGlobalAttribute", "a parameter was null")); @@ -241,7 +252,7 @@ namespace splash try { - DCAttribute::writeAttribute(name, type.getDataType(), group_custom.getHandle(), data); + DCAttribute::writeAttribute(name, type.getDataType(), group_custom.getHandle(), ndims, dims, data); } catch (DCException e) { std::cerr << e.what() << std::endl; @@ -319,6 +330,20 @@ namespace splash const char *attrName, const void* data) throw (DCException) + { + const Dimensions dims(1, 1, 1); + SerialDataCollector::writeAttribute( id, type, dataName, attrName, + 1u, dims, data); + } + + void SerialDataCollector::writeAttribute(int32_t id, + const CollectionType& type, + const char *dataName, + const char *attrName, + uint32_t ndims, + const Dimensions dims, + const void* data) + throw (DCException) { if (attrName == NULL || data == NULL) throw DCException(getExceptionString("writeAttribute", "a parameter was null")); @@ -354,7 +379,7 @@ namespace splash try { - DCAttribute::writeAttribute(attrName, type.getDataType(), obj_id, data); + DCAttribute::writeAttribute(attrName, type.getDataType(), obj_id, ndims, dims, data); } catch (DCException) { H5Oclose(obj_id); @@ -365,7 +390,7 @@ namespace splash { // attach attribute to the iteration group group.openCreate(handles.get(0), group_path); - DCAttribute::writeAttribute(attrName, type.getDataType(), group.getHandle(), data); + DCAttribute::writeAttribute(attrName, type.getDataType(), group.getHandle(), ndims, dims, data); } } diff --git a/src/include/splash/DataCollector.hpp b/src/include/splash/DataCollector.hpp index f9dcca3..1b80216 100644 --- a/src/include/splash/DataCollector.hpp +++ b/src/include/splash/DataCollector.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013-2014 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -319,6 +319,21 @@ namespace splash const char *name, const void* buf) = 0; + /** + * Writes global attribute to HDF5 file (default group). + * + * @param type Type information for data. + * @param name Name of the attribute. + * @param ndims Number of dimensions (1-3) + * @param dims Number of elements + * @param buf Buffer to be written as attribute. + */ + virtual void writeGlobalAttribute(const CollectionType& type, + const char *name, + uint32_t ndims, + const Dimensions dims, + const void* buf) = 0; + /** * Reads an attribute from a single dataset. * @@ -352,7 +367,27 @@ namespace splash const char *dataName, const char *attrName, const void *buf) = 0; - + + /** + * Writes an attribute to a single dataset. + * + * @param id ID for iteration. + * @param type Type information for data. + * @param dataName Name of the dataset in group \p id to write attribute to. + * If dataName is NULL, the attribute is written for the iteration group. + * @param attrName Name of the attribute. + * @param ndims Number of dimensions (1-3) + * @param dims Number of elements + * @param buf Buffer to be written as attribute. + */ + virtual void writeAttribute(int32_t id, + const CollectionType& type, + const char *dataName, + const char *attrName, + uint32_t ndims, + const Dimensions dims, + const void *buf) = 0; + /** * Reads data from HDF5 file. * If data is to be read (instead of only its size in the file), diff --git a/src/include/splash/IParallelDataCollector.hpp b/src/include/splash/IParallelDataCollector.hpp index 2767b72..98668e6 100644 --- a/src/include/splash/IParallelDataCollector.hpp +++ b/src/include/splash/IParallelDataCollector.hpp @@ -125,7 +125,14 @@ namespace splash const CollectionType& type, const char *name, const void* buf) = 0; - + + virtual void writeGlobalAttribute(int32_t id, + const CollectionType& type, + const char *name, + uint32_t ndims, + const Dimensions dims, + const void* buf) = 0; + virtual void readGlobalAttribute(const char *name, void* buf, Dimensions *mpiPosition = NULL) = 0; @@ -133,7 +140,13 @@ namespace splash virtual void writeGlobalAttribute(const CollectionType& type, const char *name, const void* buf) = 0; - + + virtual void writeGlobalAttribute(const CollectionType& type, + const char *name, + uint32_t ndims, + const Dimensions dims, + const void* buf) = 0; + /** * Appends (1-3) dimensional data to a dataset created with * \ref IParallelDataCollector::reserve. diff --git a/src/include/splash/ParallelDataCollector.hpp b/src/include/splash/ParallelDataCollector.hpp index 90736a3..191e56b 100644 --- a/src/include/splash/ParallelDataCollector.hpp +++ b/src/include/splash/ParallelDataCollector.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013-2014 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -272,6 +272,13 @@ namespace splash const char *name, const void* buf) throw (DCException); + void writeGlobalAttribute(int32_t id, + const CollectionType& type, + const char *name, + uint32_t ndims, + const Dimensions dims, + const void* buf) throw (DCException); + void readAttribute(int32_t id, const char *dataName, const char *attrName, @@ -284,6 +291,14 @@ namespace splash const char *attrName, const void *buf) throw (DCException); + void writeAttribute(int32_t id, + const CollectionType& type, + const char *dataName, + const char *attrName, + uint32_t ndims, + const Dimensions dims, + const void *buf) throw (DCException); + void read(int32_t id, const char* name, Dimensions &sizeRead, @@ -356,6 +371,15 @@ namespace splash } + void writeGlobalAttribute(const CollectionType& /*type*/, + const char* /*name*/, + uint32_t /*ndims*/, + const Dimensions /*dims*/, + const void* /*data*/) + { + + } + void append(int32_t /*id*/, const CollectionType& /*type*/, size_t /*count*/, diff --git a/src/include/splash/SerialDataCollector.hpp b/src/include/splash/SerialDataCollector.hpp index 840b4bf..51f73af 100644 --- a/src/include/splash/SerialDataCollector.hpp +++ b/src/include/splash/SerialDataCollector.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013-2014 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -284,6 +284,12 @@ namespace splash const char *name, const void* data) throw (DCException); + void writeGlobalAttribute(const CollectionType& type, + const char *name, + uint32_t ndims, + const Dimensions dims, + const void* data) throw (DCException); + void readAttribute(int32_t id, const char *dataName, const char *attrName, @@ -296,6 +302,14 @@ namespace splash const char *attrName, const void *data) throw (DCException); + void writeAttribute(int32_t id, + const CollectionType& type, + const char *dataName, + const char *attrName, + uint32_t ndims, + const Dimensions dims, + const void *data) throw (DCException); + void read(int32_t id, const char* name, Dimensions &sizeRead, diff --git a/src/include/splash/core/DCAttribute.hpp b/src/include/splash/core/DCAttribute.hpp index ad2ddcb..f2785e3 100644 --- a/src/include/splash/core/DCAttribute.hpp +++ b/src/include/splash/core/DCAttribute.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013 Felix Schmitt + * Copyright 2013, 2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -27,6 +27,7 @@ #include #include "splash/DCException.hpp" +#include "splash/Dimensions.hpp" namespace splash { @@ -50,16 +51,35 @@ namespace splash /** * Basic static method for writing an attribute. - * + * + * @param name name of the attribute + * @param type datatype information of the attribute + * @param parent parent object to add attribute to + * @param src buffer with value + */ + static void writeAttribute(const char *name, + const hid_t type, + hid_t parent, + const void *src) throw (DCException); + + + /** + * Basic static method for writing an attribute. + * * @param name name of the attribute * @param type datatype information of the attribute * @param parent parent object to add attribute to + * @param ndims Number of dimensions (1-3) + * @param dims Number of elements * @param src buffer with value */ static void writeAttribute(const char *name, const hid_t type, hid_t parent, + uint32_t ndims, + const Dimensions dims, const void *src) throw (DCException); + private: DCAttribute(); diff --git a/tests/AttributesTest.cpp b/tests/AttributesTest.cpp index adc3887..dc49609 100644 --- a/tests/AttributesTest.cpp +++ b/tests/AttributesTest.cpp @@ -101,8 +101,10 @@ void AttributesTest::testDataAttributes() dataCollector->writeAttribute(0, ctInt, "datasets/my_dataset", "neg_sum", &neg_sum); char c = 'Y'; + double d[7] = {-3.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0}; dataCollector->writeAttribute(0, ctInt, "datasets", "sum_at_group", &sum); dataCollector->writeAttribute(0, ctChar, "datasets", "my_char", &c); + dataCollector->writeAttribute(0, ctDouble, "datasets", "unitDimension", 1u, Dimensions(7,0,0), d); delete[] dummy_data; dummy_data = NULL; @@ -153,11 +155,15 @@ void AttributesTest::testDataAttributes() CPPUNIT_ASSERT(sum == old_sum); CPPUNIT_ASSERT(neg_sum == -old_sum); + double dr[7] = {0., 0., 0., 0., 0., 0., 0.}; dataCollector->readAttribute(0, "datasets", "sum_at_group", &sum); dataCollector->readAttribute(0, "datasets", "my_char", &c); + dataCollector->readAttribute(0, "datasets", "unitDimension", dr); CPPUNIT_ASSERT(sum == old_sum); CPPUNIT_ASSERT(c == 'Y'); + for (int i = 0; i < 7; i++) + CPPUNIT_ASSERT(dr[i] == d[i]); dataCollector->close(); } @@ -172,22 +178,26 @@ void AttributesTest::testArrayTypes() Dimensions dim_write(104, 0, 2); dataCollector->open(TEST_FILE2, attr); - dataCollector->writeGlobalAttribute(ctInt3Array, "testposition", array_data_write); + dataCollector->writeGlobalAttribute(ctInt3Array, "testpositionArray", array_data_write); + dataCollector->writeGlobalAttribute(ctInt, "testposition", 1u, Dimensions(3, 1, 1), array_data_write); dataCollector->writeGlobalAttribute(ctDimArray, "testdim", dim_write.getPointer()); dataCollector->close(); int array_data_read[3] = {0, 0, 0}; + int data_read[3] = {0, 0, 0}; Dimensions dim_read; attr.fileAccType = DataCollector::FAT_READ; dataCollector->open(TEST_FILE2, attr); - dataCollector->readGlobalAttribute("testposition", array_data_read); + dataCollector->readGlobalAttribute("testpositionArray", array_data_read); + dataCollector->readGlobalAttribute("testposition", data_read); dataCollector->readGlobalAttribute("testdim", dim_read.getPointer()); dataCollector->close(); for (int i = 0; i < 3; i++) { CPPUNIT_ASSERT(array_data_read[i] == array_data_write[i]); + CPPUNIT_ASSERT(data_read[i] == array_data_write[i]); CPPUNIT_ASSERT(dim_write[i] == dim_read[i]); } } diff --git a/tests/Parallel_AttributesTest.cpp b/tests/Parallel_AttributesTest.cpp index cbaa54d..dd27045 100644 --- a/tests/Parallel_AttributesTest.cpp +++ b/tests/Parallel_AttributesTest.cpp @@ -1,5 +1,5 @@ /** - * Copyright 2013-2014 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -161,22 +161,26 @@ void Parallel_AttributesTest::testArrayTypes() MPI_COMM_WORLD, MPI_INFO_NULL, Dimensions(MPI_SIZE_X, MPI_SIZE_Y, 1), 1); dataCollector->open(TEST_FILE2, attr); - dataCollector->writeGlobalAttribute(10, ctInt3Array, "testposition", array_data_write); + dataCollector->writeGlobalAttribute(10, ctInt3Array, "testpositionArray", array_data_write); + dataCollector->writeGlobalAttribute(10, ctInt, "testposition", 1u, Dimensions(3, 1, 1), array_data_write); dataCollector->writeGlobalAttribute(20, ctDimArray, "testdim", dim_write.getPointer()); dataCollector->close(); int array_data_read[3] = {0, 0, 0}; + int data_read[3] = {0, 0, 0}; Dimensions dim_read; attr.fileAccType = DataCollector::FAT_READ; dataCollector->open(TEST_FILE2, attr); - dataCollector->readGlobalAttribute(10, "testposition", array_data_read); + dataCollector->readGlobalAttribute(10, "testpositionArray", array_data_read); + dataCollector->readGlobalAttribute(10, "testposition", data_read); dataCollector->readGlobalAttribute(20, "testdim", dim_read.getPointer()); dataCollector->close(); for (int i = 0; i < 3; i++) { CPPUNIT_ASSERT(array_data_read[i] == array_data_write[i]); + CPPUNIT_ASSERT(data_read[i] == array_data_write[i]); CPPUNIT_ASSERT(dim_write[i] == dim_read[i]); } diff --git a/tests/include/AttributesTest.h b/tests/include/AttributesTest.h index 65fd676..342d9ba 100644 --- a/tests/include/AttributesTest.h +++ b/tests/include/AttributesTest.h @@ -46,6 +46,7 @@ class AttributesTest : public CPPUNIT_NS::TestFixture void testArrayTypes(); ColTypeChar ctChar; + ColTypeDouble ctDouble; ColTypeInt ctInt; ColTypeInt2 ctInt2; ColTypeInt3Array ctInt3Array; diff --git a/tests/readBoolChar.py b/tests/readBoolChar.py index 2ff24cb..93bb478 100755 --- a/tests/readBoolChar.py +++ b/tests/readBoolChar.py @@ -24,7 +24,7 @@ import h5py import numpy as np -# bool compatible data sets +# bool compatible data sets ################################################### f = h5py.File("h5/testWriteRead_0_0_0.h5", "r") data = f["data/10/deep/folders/data_bool"] @@ -38,8 +38,28 @@ f.close() -# single char compatible attributes +# compatible attributes ####################################################### +f = h5py.File("h5/attributes_array_0_0_0.h5", "r") + +# array attributes +dg = f["custom"].attrs["testposition"] +print(dg, type(dg), dg.dtype) + +ref_dg = np.array([17, 12, -99], dtype="int") +if not np.array_equal(dg, ref_dg): + exit(1) + +f.close() f = h5py.File("h5/attributes_0_0_0.h5", "r") + +d = f["data/0/datasets"].attrs["unitDimension"] +print(d, type(d), d.dtype) + +ref_d = np.array([-3., 0., 1., 1., 0., 0., 0.], dtype="float64") +if not np.array_equal(d, ref_d): + exit(1) + +# single char compatible attributes c = f["data/0/datasets"].attrs["my_char"] # h5py, as of 2.5.0, does not know char and From c549285b60c08a96670a61708de5c213793538c0 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Thu, 7 May 2015 09:28:35 +0200 Subject: [PATCH 20/47] File Format Minor Increase: 3.2 for Dataspace Attributes --- src/include/splash/version.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/splash/version.hpp b/src/include/splash/version.hpp index 32200aa..879c92f 100644 --- a/src/include/splash/version.hpp +++ b/src/include/splash/version.hpp @@ -32,6 +32,6 @@ * changes in the minor number have to be backwards compatible */ #define SPLASH_FILE_FORMAT_MAJOR 3 -#define SPLASH_FILE_FORMAT_MINOR 1 +#define SPLASH_FILE_FORMAT_MINOR 2 #endif /* VERSION_HPP */ From 35c290dcce425e48e02e658b5feda6f00123d4bf Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Thu, 7 May 2015 09:44:26 +0200 Subject: [PATCH 21/47] Dimensionality Check: Move to User Interfaces --- src/DCAttribute.cpp | 6 ------ src/ParallelDataCollector.cpp | 6 ++++++ src/SerialDataCollector.cpp | 6 ++++++ tests/AttributesTest.cpp | 5 ++++- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/DCAttribute.cpp b/src/DCAttribute.cpp index 0e2e2f1..cff84ee 100644 --- a/src/DCAttribute.cpp +++ b/src/DCAttribute.cpp @@ -65,12 +65,6 @@ namespace splash uint32_t ndims, const Dimensions dims, const void* src) throw (DCException) { - if (name == NULL) - throw DCException(getExceptionString("attribute", "parameter name is NULL")); - - if (ndims < 1u || ndims > 3u) - throw DCException(getExceptionString(name, "maximum dimension is invalid")); - hid_t attr = -1; if (H5Aexists(parent, name)) attr = H5Aopen(parent, name, H5P_DEFAULT); diff --git a/src/ParallelDataCollector.cpp b/src/ParallelDataCollector.cpp index 7cb1a69..3ba60ec 100644 --- a/src/ParallelDataCollector.cpp +++ b/src/ParallelDataCollector.cpp @@ -358,6 +358,9 @@ namespace splash if (fileStatus == FST_CLOSED || fileStatus == FST_READING) throw DCException(getExceptionString("writeGlobalAttribute", "this access is not permitted")); + if (ndims < 1u || ndims > DSP_DIM_MAX) + throw DCException(getExceptionString("writeGlobalAttribute", "maximum dimension `ndims` is invalid")); + DCParallelGroup group_custom; group_custom.open(handles.get(id), SDC_GROUP_CUSTOM); @@ -461,6 +464,9 @@ namespace splash if (fileStatus == FST_CLOSED || fileStatus == FST_READING) throw DCException(getExceptionString("writeAttribute", "this access is not permitted")); + if (ndims < 1u || ndims > DSP_DIM_MAX) + throw DCException(getExceptionString("writeAttribute", "maximum dimension `ndims` is invalid")); + std::string group_path, obj_name; std::string dataNameInternal = ""; if (dataName) diff --git a/src/SerialDataCollector.cpp b/src/SerialDataCollector.cpp index d01df24..c8b6a77 100644 --- a/src/SerialDataCollector.cpp +++ b/src/SerialDataCollector.cpp @@ -247,6 +247,9 @@ namespace splash if (fileStatus == FST_CLOSED || fileStatus == FST_READING || fileStatus == FST_MERGING) throw DCException(getExceptionString("writeGlobalAttribute", "this access is not permitted")); + if (ndims < 1u || ndims > DSP_DIM_MAX) + throw DCException(getExceptionString("writeGlobalAttribute", "maximum dimension `ndims` is invalid")); + DCGroup group_custom; group_custom.open(handles.get(0), SDC_GROUP_CUSTOM); @@ -358,6 +361,9 @@ namespace splash if (fileStatus == FST_CLOSED || fileStatus == FST_READING || fileStatus == FST_MERGING) throw DCException(getExceptionString("writeAttribute", "this access is not permitted")); + if (ndims < 1u || ndims > DSP_DIM_MAX) + throw DCException(getExceptionString("writeAttribute", "maximum dimension `ndims` is invalid")); + std::string group_path, obj_name; std::string dataNameInternal = ""; if (dataName) diff --git a/tests/AttributesTest.cpp b/tests/AttributesTest.cpp index dc49609..57a2212 100644 --- a/tests/AttributesTest.cpp +++ b/tests/AttributesTest.cpp @@ -92,7 +92,7 @@ void AttributesTest::testDataAttributes() DCException); CPPUNIT_ASSERT_THROW(dataCollector->writeAttribute(10, ctInt, "", "", &sum2), DCException); - + dataCollector->write(0, ctInt2, 1, Selection(Dimensions(BUF_SIZE, 1, 1)), "datasets/my_dataset", dummy_data); @@ -106,6 +106,9 @@ void AttributesTest::testDataAttributes() dataCollector->writeAttribute(0, ctChar, "datasets", "my_char", &c); dataCollector->writeAttribute(0, ctDouble, "datasets", "unitDimension", 1u, Dimensions(7,0,0), d); + CPPUNIT_ASSERT_THROW(dataCollector->writeAttribute(0, ctDouble, "datasets", + "invalnDims", 4u, Dimensions(7,0,0), d), DCException); + delete[] dummy_data; dummy_data = NULL; From 6c8b281077fcdf6b390d475612fc16012b7b374d Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Fri, 8 May 2015 14:58:31 +0200 Subject: [PATCH 22/47] CMake: Add Original FindHDF5.cmake From cmake master, commit ee1ddec4c19488216289dfd26998091b695bf3ee --- cmake/FindHDF5.cmake | 364 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 cmake/FindHDF5.cmake diff --git a/cmake/FindHDF5.cmake b/cmake/FindHDF5.cmake new file mode 100644 index 0000000..0d58e13 --- /dev/null +++ b/cmake/FindHDF5.cmake @@ -0,0 +1,364 @@ +#.rst: +# FindHDF5 +# -------- +# +# Find HDF5, a library for reading and writing self describing array data. +# +# +# +# This module invokes the HDF5 wrapper compiler that should be installed +# alongside HDF5. Depending upon the HDF5 Configuration, the wrapper +# compiler is called either h5cc or h5pcc. If this succeeds, the module +# will then call the compiler with the -show argument to see what flags +# are used when compiling an HDF5 client application. +# +# The module will optionally accept the COMPONENTS argument. If no +# COMPONENTS are specified, then the find module will default to finding +# only the HDF5 C library. If one or more COMPONENTS are specified, the +# module will attempt to find the language bindings for the specified +# components. The only valid components are C, CXX, Fortran, HL, and +# Fortran_HL. If the COMPONENTS argument is not given, the module will +# attempt to find only the C bindings. +# +# On UNIX systems, this module will read the variable +# HDF5_USE_STATIC_LIBRARIES to determine whether or not to prefer a +# static link to a dynamic link for HDF5 and all of it's dependencies. +# To use this feature, make sure that the HDF5_USE_STATIC_LIBRARIES +# variable is set before the call to find_package. +# +# To provide the module with a hint about where to find your HDF5 +# installation, you can set the environment variable HDF5_ROOT. The +# Find module will then look in this path when searching for HDF5 +# executables, paths, and libraries. +# +# In addition to finding the includes and libraries required to compile +# an HDF5 client application, this module also makes an effort to find +# tools that come with the HDF5 distribution that may be useful for +# regression testing. +# +# This module will define the following variables: +# +# :: +# +# HDF5_INCLUDE_DIRS - Location of the hdf5 includes +# HDF5_INCLUDE_DIR - Location of the hdf5 includes (deprecated) +# HDF5_DEFINITIONS - Required compiler definitions for HDF5 +# HDF5_C_LIBRARIES - Required libraries for the HDF5 C bindings. +# HDF5_CXX_LIBRARIES - Required libraries for the HDF5 C++ bindings +# HDF5_Fortran_LIBRARIES - Required libraries for the HDF5 Fortran bindings +# HDF5_HL_LIBRARIES - Required libraries for the HDF5 high level API +# HDF5_Fortran_HL_LIBRARIES - Required libraries for the high level Fortran +# bindings. +# HDF5_LIBRARIES - Required libraries for all requested bindings +# HDF5_FOUND - true if HDF5 was found on the system +# HDF5_LIBRARY_DIRS - the full set of library directories +# HDF5_IS_PARALLEL - Whether or not HDF5 was found with parallel IO support +# HDF5_C_COMPILER_EXECUTABLE - the path to the HDF5 C wrapper compiler +# HDF5_CXX_COMPILER_EXECUTABLE - the path to the HDF5 C++ wrapper compiler +# HDF5_Fortran_COMPILER_EXECUTABLE - the path to the HDF5 Fortran wrapper compiler +# HDF5_DIFF_EXECUTABLE - the path to the HDF5 dataset comparison tool + +#============================================================================= +# Copyright 2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +# This module is maintained by Will Dicharry . + +include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + +# List of the valid HDF5 components +set( HDF5_VALID_COMPONENTS + C + CXX + Fortran + HL + Fortran_HL +) + +# Validate the list of find components. +if( NOT HDF5_FIND_COMPONENTS ) + set( HDF5_LANGUAGE_BINDINGS "C" ) +else() + # add the extra specified components, ensuring that they are valid. + foreach( component ${HDF5_FIND_COMPONENTS} ) + list( FIND HDF5_VALID_COMPONENTS ${component} component_location ) + if( ${component_location} EQUAL -1 ) + message( FATAL_ERROR + "\"${component}\" is not a valid HDF5 component." ) + else() + list( APPEND HDF5_LANGUAGE_BINDINGS ${component} ) + endif() + endforeach() +endif() + +# try to find the HDF5 wrapper compilers +find_program( HDF5_C_COMPILER_EXECUTABLE + NAMES h5cc h5pcc + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 Wrapper compiler. Used only to detect HDF5 compile flags." ) +mark_as_advanced( HDF5_C_COMPILER_EXECUTABLE ) + +find_program( HDF5_CXX_COMPILER_EXECUTABLE + NAMES h5c++ h5pc++ + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 C++ Wrapper compiler. Used only to detect HDF5 compile flags." ) +mark_as_advanced( HDF5_CXX_COMPILER_EXECUTABLE ) + +find_program( HDF5_Fortran_COMPILER_EXECUTABLE + NAMES h5fc h5pfc + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 Fortran Wrapper compiler. Used only to detect HDF5 compile flags." ) +mark_as_advanced( HDF5_Fortran_COMPILER_EXECUTABLE ) + +find_program( HDF5_DIFF_EXECUTABLE + NAMES h5diff + HINTS ENV HDF5_ROOT + PATH_SUFFIXES bin Bin + DOC "HDF5 file differencing tool." ) +mark_as_advanced( HDF5_DIFF_EXECUTABLE ) + +# Invoke the HDF5 wrapper compiler. The compiler return value is stored to the +# return_value argument, the text output is stored to the output variable. +macro( _HDF5_invoke_compiler language output return_value ) + if( HDF5_${language}_COMPILER_EXECUTABLE ) + exec_program( ${HDF5_${language}_COMPILER_EXECUTABLE} + ARGS -show + OUTPUT_VARIABLE ${output} + RETURN_VALUE ${return_value} + ) + if( ${${return_value}} EQUAL 0 ) + # do nothing + else() + message( STATUS + "Unable to determine HDF5 ${language} flags from HDF5 wrapper." ) + endif() + endif() +endmacro() + +# Parse a compile line for definitions, includes, library paths, and libraries. +macro( _HDF5_parse_compile_line + compile_line_var + include_paths + definitions + library_paths + libraries ) + + # Match the include paths + string( REGEX MATCHALL "-I([^\" ]+)" include_path_flags + "${${compile_line_var}}" + ) + foreach( IPATH ${include_path_flags} ) + string( REGEX REPLACE "^-I" "" IPATH ${IPATH} ) + string( REPLACE "//" "/" IPATH ${IPATH} ) + list( APPEND ${include_paths} ${IPATH} ) + endforeach() + + # Match the definitions + string( REGEX MATCHALL "-D[^ ]*" definition_flags "${${compile_line_var}}" ) + foreach( DEF ${definition_flags} ) + list( APPEND ${definitions} ${DEF} ) + endforeach() + + # Match the library paths + string( REGEX MATCHALL "-L([^\" ]+|\"[^\"]+\")" library_path_flags + "${${compile_line_var}}" + ) + + foreach( LPATH ${library_path_flags} ) + string( REGEX REPLACE "^-L" "" LPATH ${LPATH} ) + string( REPLACE "//" "/" LPATH ${LPATH} ) + list( APPEND ${library_paths} ${LPATH} ) + endforeach() + + # now search for the library names specified in the compile line (match -l...) + # match only -l's preceded by a space or comma + # this is to exclude directory names like xxx-linux/ + string( REGEX MATCHALL "[, ]-l([^\", ]+)" library_name_flags + "${${compile_line_var}}" ) + # strip the -l from all of the library flags and add to the search list + foreach( LIB ${library_name_flags} ) + string( REGEX REPLACE "^[, ]-l" "" LIB ${LIB} ) + list( APPEND ${libraries} ${LIB} ) + endforeach() +endmacro() + +# Try to find HDF5 using an installed hdf5-config.cmake +if( NOT HDF5_FOUND ) + find_package( HDF5 QUIET NO_MODULE ) + if( HDF5_FOUND ) + set( HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR} ) + set( HDF5_LIBRARIES ) + set( HDF5_C_TARGET hdf5 ) + set( HDF5_CXX_TARGET hdf5_cpp ) + set( HDF5_HL_TARGET hdf5_hl ) + set( HDF5_Fortran_TARGET hdf5_fortran ) + set( HDF5_Fortran_HL_TARGET hdf5_hl_fortran ) + foreach( _component ${HDF5_LANGUAGE_BINDINGS} ) + list( FIND HDF5_VALID_COMPONENTS ${_component} _component_location ) + get_target_property( _comp_location ${HDF5_${_component}_TARGET} LOCATION ) + if( _comp_location ) + set( HDF5_${_component}_LIBRARY ${_comp_location} CACHE PATH + "HDF5 ${_component} library" ) + mark_as_advanced( HDF5_${_component}_LIBRARY ) + list( APPEND HDF5_LIBRARIES ${HDF5_${_component}_LIBRARY} ) + endif() + endforeach() + endif() +endif() + +if( NOT HDF5_FOUND ) + _HDF5_invoke_compiler( C HDF5_C_COMPILE_LINE HDF5_C_RETURN_VALUE ) + _HDF5_invoke_compiler( CXX HDF5_CXX_COMPILE_LINE HDF5_CXX_RETURN_VALUE ) + _HDF5_invoke_compiler( Fortran HDF5_Fortran_COMPILE_LINE HDF5_Fortran_RETURN_VALUE ) + + # seed the initial lists of libraries to find with items we know we need + set( HDF5_C_LIBRARY_NAMES_INIT hdf5 ) + set( HDF5_HL_LIBRARY_NAMES_INIT hdf5_hl ${HDF5_C_LIBRARY_NAMES_INIT} ) + set( HDF5_CXX_LIBRARY_NAMES_INIT hdf5_cpp ${HDF5_C_LIBRARY_NAMES_INIT} ) + set( HDF5_Fortran_LIBRARY_NAMES_INIT hdf5_fortran + ${HDF5_C_LIBRARY_NAMES_INIT} ) + set( HDF5_Fortran_HL_LIBRARY_NAMES_INIT hdf5hl_fortran + ${HDF5_Fortran_LIBRARY_NAMES_INIT} ) + + foreach( LANGUAGE ${HDF5_LANGUAGE_BINDINGS} ) + if( HDF5_${LANGUAGE}_COMPILE_LINE ) + _HDF5_parse_compile_line( HDF5_${LANGUAGE}_COMPILE_LINE + HDF5_${LANGUAGE}_INCLUDE_FLAGS + HDF5_${LANGUAGE}_DEFINITIONS + HDF5_${LANGUAGE}_LIBRARY_DIRS + HDF5_${LANGUAGE}_LIBRARY_NAMES + ) + + # take a guess that the includes may be in the 'include' sibling + # directory of a library directory. + foreach( dir ${HDF5_${LANGUAGE}_LIBRARY_DIRS} ) + list( APPEND HDF5_${LANGUAGE}_INCLUDE_FLAGS ${dir}/../include ) + endforeach() + endif() + + # set the definitions for the language bindings. + list( APPEND HDF5_DEFINITIONS ${HDF5_${LANGUAGE}_DEFINITIONS} ) + + # find the HDF5 include directories + if(${LANGUAGE} MATCHES "Fortran") + set(HDF5_INCLUDE_FILENAME hdf5.mod) + else() + set(HDF5_INCLUDE_FILENAME hdf5.h) + endif() + + find_path( HDF5_${LANGUAGE}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME} + HINTS + ${HDF5_${LANGUAGE}_INCLUDE_FLAGS} + ENV + HDF5_ROOT + PATHS + $ENV{HOME}/.local/include + PATH_SUFFIXES + include + Include + ) + mark_as_advanced( HDF5_${LANGUAGE}_INCLUDE_DIR ) + list( APPEND HDF5_INCLUDE_DIRS ${HDF5_${LANGUAGE}_INCLUDE_DIR} ) + + set( HDF5_${LANGUAGE}_LIBRARY_NAMES + ${HDF5_${LANGUAGE}_LIBRARY_NAMES_INIT} + ${HDF5_${LANGUAGE}_LIBRARY_NAMES} ) + + # find the HDF5 libraries + foreach( LIB ${HDF5_${LANGUAGE}_LIBRARY_NAMES} ) + if( UNIX AND HDF5_USE_STATIC_LIBRARIES ) + # According to bug 1643 on the CMake bug tracker, this is the + # preferred method for searching for a static library. + # See http://www.cmake.org/Bug/view.php?id=1643. We search + # first for the full static library name, but fall back to a + # generic search on the name if the static search fails. + set( THIS_LIBRARY_SEARCH_DEBUG lib${LIB}d.a ${LIB}d ) + set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a ${LIB} ) + else() + set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d ) + set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} ) + endif() + find_library( HDF5_${LIB}_LIBRARY_DEBUG + NAMES ${THIS_LIBRARY_SEARCH_DEBUG} + HINTS ${HDF5_${LANGUAGE}_LIBRARY_DIRS} + ENV HDF5_ROOT + PATH_SUFFIXES lib Lib ) + find_library( HDF5_${LIB}_LIBRARY_RELEASE + NAMES ${THIS_LIBRARY_SEARCH_RELEASE} + HINTS ${HDF5_${LANGUAGE}_LIBRARY_DIRS} + ENV HDF5_ROOT + PATH_SUFFIXES lib Lib ) + select_library_configurations( HDF5_${LIB} ) + list(APPEND HDF5_${LANGUAGE}_LIBRARIES ${HDF5_${LIB}_LIBRARY}) + endforeach() + list( APPEND HDF5_LIBRARY_DIRS ${HDF5_${LANGUAGE}_LIBRARY_DIRS} ) + + # Append the libraries for this language binding to the list of all + # required libraries. + list(APPEND HDF5_LIBRARIES ${HDF5_${LANGUAGE}_LIBRARIES}) + endforeach() + + # We may have picked up some duplicates in various lists during the above + # process for the language bindings (both the C and C++ bindings depend on + # libz for example). Remove the duplicates. It appears that the default + # CMake behavior is to remove duplicates from the end of a list. However, + # for link lines, this is incorrect since unresolved symbols are searched + # for down the link line. Therefore, we reverse the list, remove the + # duplicates, and then reverse it again to get the duplicates removed from + # the beginning. + macro( _remove_duplicates_from_beginning _list_name ) + list( REVERSE ${_list_name} ) + list( REMOVE_DUPLICATES ${_list_name} ) + list( REVERSE ${_list_name} ) + endmacro() + + if( HDF5_INCLUDE_DIRS ) + _remove_duplicates_from_beginning( HDF5_INCLUDE_DIRS ) + endif() + if( HDF5_LIBRARY_DIRS ) + _remove_duplicates_from_beginning( HDF5_LIBRARY_DIRS ) + endif() + + # If the HDF5 include directory was found, open H5pubconf.h to determine if + # HDF5 was compiled with parallel IO support + set( HDF5_IS_PARALLEL FALSE ) + foreach( _dir IN LISTS HDF5_INCLUDE_DIRS ) + if( EXISTS "${_dir}/H5pubconf.h" ) + file( STRINGS "${_dir}/H5pubconf.h" + HDF5_HAVE_PARALLEL_DEFINE + REGEX "HAVE_PARALLEL 1" ) + if( HDF5_HAVE_PARALLEL_DEFINE ) + set( HDF5_IS_PARALLEL TRUE ) + endif() + endif() + endforeach() + set( HDF5_IS_PARALLEL ${HDF5_IS_PARALLEL} CACHE BOOL + "HDF5 library compiled with parallel IO support" ) + mark_as_advanced( HDF5_IS_PARALLEL ) + + # For backwards compatibility we set HDF5_INCLUDE_DIR to the value of + # HDF5_INCLUDE_DIRS + if( HDF5_INCLUDE_DIRS ) + set( HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIRS}" ) + endif() + +endif() + +find_package_handle_standard_args( HDF5 DEFAULT_MSG + HDF5_LIBRARIES + HDF5_INCLUDE_DIRS +) + From b585cf25581a270962779910506b4ffc757b2ce0 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Fri, 8 May 2015 14:59:28 +0200 Subject: [PATCH 23/47] CMake: Add HDF5 Version Support --- CMakeLists.txt | 3 +++ cmake/FindHDF5.cmake | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d6dce7..17ea062 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,9 @@ PROJECT(libSplash) SET(CMAKE_PREFIX_PATH "/usr/lib/x86_64-linux-gnu/" "$ENV{MPI_ROOT}" "$ENV{HDF5_ROOT}") +# own modules for find_packages +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/ ${CMAKE_MODULE_PATH}) + #------------------------------------------------------------------------------- # install prefix diff --git a/cmake/FindHDF5.cmake b/cmake/FindHDF5.cmake index 0d58e13..d9785ee 100644 --- a/cmake/FindHDF5.cmake +++ b/cmake/FindHDF5.cmake @@ -51,6 +51,7 @@ # bindings. # HDF5_LIBRARIES - Required libraries for all requested bindings # HDF5_FOUND - true if HDF5 was found on the system +# HDF5_VERSION - HDF5 Version in format Major.Minor.Release # HDF5_LIBRARY_DIRS - the full set of library directories # HDF5_IS_PARALLEL - Whether or not HDF5 was found with parallel IO support # HDF5_C_COMPILER_EXECUTABLE - the path to the HDF5 C wrapper compiler @@ -60,6 +61,7 @@ #============================================================================= # Copyright 2009 Kitware, Inc. +# 2015 Axel Huebl, Helmholtz-Zentrum Dresden - Rossendorf # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. @@ -73,8 +75,8 @@ # This module is maintained by Will Dicharry . -include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +include(SelectLibraryConfigurations) +include(FindPackageHandleStandardArgs) # List of the valid HDF5 components set( HDF5_VALID_COMPONENTS @@ -340,6 +342,11 @@ if( NOT HDF5_FOUND ) file( STRINGS "${_dir}/H5pubconf.h" HDF5_HAVE_PARALLEL_DEFINE REGEX "HAVE_PARALLEL 1" ) + file( STRINGS "${_dir}/H5pubconf.h" + HDF5_VERSION_DEFINE + REGEX "#define H5_VERSION" ) + string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" + HDF5_VERSION ${HDF5_VERSION_DEFINE}) if( HDF5_HAVE_PARALLEL_DEFINE ) set( HDF5_IS_PARALLEL TRUE ) endif() @@ -357,8 +364,8 @@ if( NOT HDF5_FOUND ) endif() -find_package_handle_standard_args( HDF5 DEFAULT_MSG - HDF5_LIBRARIES - HDF5_INCLUDE_DIRS +find_package_handle_standard_args( HDF5 + REQUIRED_VARS HDF5_LIBRARIES HDF5_INCLUDE_DIRS + VERSION_VAR HDF5_VERSION ) From 2b780888ea107e68432373c93bd2e952fed8d0f8 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Fri, 8 May 2015 19:16:10 +0200 Subject: [PATCH 24/47] Improve with feedback from - Brad King - Rolf Eike Beer --- cmake/FindHDF5.cmake | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/cmake/FindHDF5.cmake b/cmake/FindHDF5.cmake index d9785ee..227bb24 100644 --- a/cmake/FindHDF5.cmake +++ b/cmake/FindHDF5.cmake @@ -51,7 +51,7 @@ # bindings. # HDF5_LIBRARIES - Required libraries for all requested bindings # HDF5_FOUND - true if HDF5 was found on the system -# HDF5_VERSION - HDF5 Version in format Major.Minor.Release +# HDF5_VERSION - HDF5 version in format Major.Minor.Release # HDF5_LIBRARY_DIRS - the full set of library directories # HDF5_IS_PARALLEL - Whether or not HDF5 was found with parallel IO support # HDF5_C_COMPILER_EXECUTABLE - the path to the HDF5 C wrapper compiler @@ -337,19 +337,25 @@ if( NOT HDF5_FOUND ) # If the HDF5 include directory was found, open H5pubconf.h to determine if # HDF5 was compiled with parallel IO support set( HDF5_IS_PARALLEL FALSE ) + set( HDF5_VERSION "" ) foreach( _dir IN LISTS HDF5_INCLUDE_DIRS ) if( EXISTS "${_dir}/H5pubconf.h" ) file( STRINGS "${_dir}/H5pubconf.h" HDF5_HAVE_PARALLEL_DEFINE REGEX "HAVE_PARALLEL 1" ) - file( STRINGS "${_dir}/H5pubconf.h" - HDF5_VERSION_DEFINE - REGEX "#define H5_VERSION" ) - string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" - HDF5_VERSION ${HDF5_VERSION_DEFINE}) if( HDF5_HAVE_PARALLEL_DEFINE ) set( HDF5_IS_PARALLEL TRUE ) endif() + unset(HDF5_HAVE_PARALLEL_DEFINE) + + file( STRINGS "${_dir}/H5pubconf.h" + HDF5_VERSION_DEFINE + REGEX "^[ \t]*#[ \t]*define[ \t]+H5_VERSION[ \t]+" ) + if( "${HDF5_VERSION_DEFINE}" MATCHES + "H5_VERSION[ \t]+\"([0-9]+\\.[0-9]+\\.[0-9]+)\"" ) + set( HDF5_VERSION "${CMAKE_MATCH_1}" ) + endif() + unset(HDF5_VERSION_DEFINE) endif() endforeach() set( HDF5_IS_PARALLEL ${HDF5_IS_PARALLEL} CACHE BOOL From 1af3a8431d4eba25fa8b74cc2334c9f490387fe2 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Mon, 11 May 2015 10:08:27 +0200 Subject: [PATCH 25/47] Doxygen: Project Name libSplash --- doc/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Doxyfile b/doc/Doxyfile index 0d1f23c..739129a 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -4,7 +4,7 @@ # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = libDataCollector +PROJECT_NAME = libSplash PROJECT_NUMBER = OUTPUT_DIRECTORY = doxygenDoku CREATE_SUBDIRS = NO From fc087865dbd8b9135dc0f421f04613ff3aac6961 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Mon, 11 May 2015 10:31:46 +0200 Subject: [PATCH 26/47] FindHDF5: Match C-String, Ignore Subrelease Version allows subreleases of form `X.Y.Z-subrelease` without breaking find_package. Subreleases after the patch (`Z`) level are ignored/cropped. --- cmake/FindHDF5.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindHDF5.cmake b/cmake/FindHDF5.cmake index 227bb24..59705f4 100644 --- a/cmake/FindHDF5.cmake +++ b/cmake/FindHDF5.cmake @@ -352,7 +352,7 @@ if( NOT HDF5_FOUND ) HDF5_VERSION_DEFINE REGEX "^[ \t]*#[ \t]*define[ \t]+H5_VERSION[ \t]+" ) if( "${HDF5_VERSION_DEFINE}" MATCHES - "H5_VERSION[ \t]+\"([0-9]+\\.[0-9]+\\.[0-9]+)\"" ) + "H5_VERSION[ \t]+\"([0-9]+\\.[0-9]+\\.[0-9]+).*\"" ) set( HDF5_VERSION "${CMAKE_MATCH_1}" ) endif() unset(HDF5_VERSION_DEFINE) From 9603ce1731b9c60c8d11bc47e7c3fcc84b54ee5d Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Fri, 8 May 2015 15:18:38 +0200 Subject: [PATCH 27/47] Remember HDF5 Version This commit adds support to libSplash to remember the HDF5 version it was build against. This is interesting, since depending software usually does not include `` and can not query the version of HDF5 directly via the includes. That does not prevent users to compile HDF5 and libSplash both with shared libs and to mix various versions, but the `SPLASH_HDF_VERSION` will still point to the version Splash was originially build (and should be used) with. --- CMakeLists.txt | 7 +++++++ src/include/splash/version.hpp | 3 +++ 2 files changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 17ea062..c38c10f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,8 +172,15 @@ INSTALL(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/include/." PATTERN ".svn" EXCLUDE PATTERN ".git" EXCLUDE PATTERN "splash_*.h" EXCLUDE + PATTERN "version.hpp" EXCLUDE ) +# version.hpp file with SPLASH_HDF5_VERSION set accordingly +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/include/splash/version.hpp + ${CMAKE_CURRENT_BINARY_DIR}/splash/version.hpp ) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/splash/version.hpp + DESTINATION include/splash) + # install correct splash header file # (will be executed after the POST_BUILD copies of splash.h) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/splash/splash.h diff --git a/src/include/splash/version.hpp b/src/include/splash/version.hpp index 879c92f..91dda60 100644 --- a/src/include/splash/version.hpp +++ b/src/include/splash/version.hpp @@ -34,4 +34,7 @@ #define SPLASH_FILE_FORMAT_MAJOR 3 #define SPLASH_FILE_FORMAT_MINOR 2 +/** The version of HDF5 that was used to compile splash */ +#define SPLASH_HDF5_VERSION "${HDF5_VERSION}" + #endif /* VERSION_HPP */ From 515cfa32c977c82578864ae8107975d5c54bd64c Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Mon, 10 Aug 2015 17:22:13 +0200 Subject: [PATCH 28/47] Close #173: Parallel Write of Global Attributes When writing global attributes in parallel mode, one would expect them to be under the root `/` path (and to be identical for each rank). This closes #173 and is a requirement to allow implementations to fulfill the openPMD standard. Serial writes are not affected and still write to `/custom` (each of the ranks). A later refactoring could consider just to let one rank write to `/` here, too (and to ingore the others assuming an actual "global" == identical value). --- src/ParallelDataCollector.cpp | 6 +++--- src/include/splash/ParallelDataCollector.hpp | 1 + src/include/splash/pdc_defines.hpp | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ParallelDataCollector.cpp b/src/ParallelDataCollector.cpp index 3ba60ec..92c24b2 100644 --- a/src/ParallelDataCollector.cpp +++ b/src/ParallelDataCollector.cpp @@ -322,7 +322,7 @@ namespace splash throw DCException(getExceptionString("readGlobalAttribute", "this access is not permitted")); DCParallelGroup group_custom; - group_custom.open(handles.get(id), SDC_GROUP_CUSTOM); + group_custom.open(handles.get(id), PDC_GROUP_CUSTOM); try { @@ -362,7 +362,7 @@ namespace splash throw DCException(getExceptionString("writeGlobalAttribute", "maximum dimension `ndims` is invalid")); DCParallelGroup group_custom; - group_custom.open(handles.get(id), SDC_GROUP_CUSTOM); + group_custom.open(handles.get(id), PDC_GROUP_CUSTOM); try { @@ -795,7 +795,7 @@ namespace splash // the custom group holds user-specified attributes DCParallelGroup group; - group.create(handle, SDC_GROUP_CUSTOM); + group.create(handle, PDC_GROUP_CUSTOM); group.close(); // the data group holds the actual simulation data diff --git a/src/include/splash/ParallelDataCollector.hpp b/src/include/splash/ParallelDataCollector.hpp index 191e56b..1224b84 100644 --- a/src/include/splash/ParallelDataCollector.hpp +++ b/src/include/splash/ParallelDataCollector.hpp @@ -33,6 +33,7 @@ #include "splash/DCException.hpp" #include "splash/sdc_defines.hpp" +#include "splash/pdc_defines.hpp" #include "splash/core/HandleMgr.hpp" namespace splash diff --git a/src/include/splash/pdc_defines.hpp b/src/include/splash/pdc_defines.hpp index 471cd79..171eefb 100644 --- a/src/include/splash/pdc_defines.hpp +++ b/src/include/splash/pdc_defines.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -24,6 +25,7 @@ namespace splash { +#define PDC_GROUP_CUSTOM "/" #define PDC_ATTR_APPEND "pdc_fillsize" } From 8232c999711d20dc3c6cd7bd4c0e5f10d25d4366 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Mon, 10 Aug 2015 21:32:42 +0200 Subject: [PATCH 29/47] Close #180: Write Splash Version & Format Closes issue #180: create two string attributes under `/header` `splashVersion` and `splashFormat` so people know what kind of files they are dealing with. --- CMakeLists.txt | 4 +- src/ParallelDataCollector.cpp | 23 ++++- src/SDCHelper.cpp | 139 ++++++++++++++++++++++++++ src/include/splash/core/SDCHelper.hpp | 131 +++++------------------- src/include/splash/sdc_defines.hpp | 5 +- 5 files changed, 192 insertions(+), 110 deletions(-) create mode 100644 src/SDCHelper.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c38c10f..1004db7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # - # Copyright 2013-2014 Felix Schmitt, Axel Huebl + # Copyright 2013-2015 Felix Schmitt, Axel Huebl # # This file is part of libSplash. # @@ -112,7 +112,7 @@ ENDIF(NOT SPLASH_RELEASE) SET(SPLASH_LIBS z ${HDF5_LIBRARIES}) # serial or parallel version of libSplash -SET(SPLASH_CLASSES logging DCAttribute DCDataSet DCGroup HandleMgr SerialDataCollector DomainCollector) +SET(SPLASH_CLASSES logging DCAttribute DCDataSet DCGroup HandleMgr SerialDataCollector DomainCollector SDCHelper) IF(HDF5_IS_PARALLEL) #parallel version MESSAGE(STATUS "Parallel HDF5 found. Building parallel version") diff --git a/src/ParallelDataCollector.cpp b/src/ParallelDataCollector.cpp index 3ba60ec..594743e 100644 --- a/src/ParallelDataCollector.cpp +++ b/src/ParallelDataCollector.cpp @@ -25,8 +25,12 @@ #include #include #include +#include +#include "splash/version.hpp" #include "splash/ParallelDataCollector.hpp" +#include "splash/basetypes/ColTypeDim.hpp" +#include "splash/basetypes/ColTypeString.hpp" #include "splash/core/DCParallelDataSet.hpp" #include "splash/core/DCAttribute.hpp" #include "splash/core/DCParallelGroup.hpp" @@ -821,10 +825,19 @@ namespace splash DCParallelGroup group; group.create(fHandle, SDC_GROUP_HEADER); - ColTypeDim dim_t; - int32_t index = id; bool compression = enableCompression; + std::stringstream splashVersion; + splashVersion << SPLASH_VERSION_MAJOR << "." + << SPLASH_VERSION_MINOR << "." + << SPLASH_VERSION_PATCH; + std::stringstream splashFormat; + splashFormat << SPLASH_FILE_FORMAT_MAJOR << "." + << SPLASH_FILE_FORMAT_MINOR; + + ColTypeDim dim_t; + ColTypeString ctStringVersion(splashVersion.str().length()); + ColTypeString ctStringFormat(splashFormat.str().length()); // create master specific header attributes DCAttribute::writeAttribute(SDC_ATTR_MAX_ID, H5T_NATIVE_INT32, @@ -835,6 +848,12 @@ namespace splash DCAttribute::writeAttribute(SDC_ATTR_MPI_SIZE, dim_t.getDataType(), group.getHandle(), mpiTopology.getPointer()); + + DCAttribute::writeAttribute(SDC_ATTR_VERSION, ctStringVersion.getDataType(), + group.getHandle(), splashVersion.str().c_str()); + + DCAttribute::writeAttribute(SDC_ATTR_FORMAT, ctStringFormat.getDataType(), + group.getHandle(), splashFormat.str().c_str()); } void ParallelDataCollector::openCreate(const char *filename, diff --git a/src/SDCHelper.cpp b/src/SDCHelper.cpp new file mode 100644 index 0000000..c979c61 --- /dev/null +++ b/src/SDCHelper.cpp @@ -0,0 +1,139 @@ +/** + * Copyright 2013-2015 Felix Schmitt, Axel Huebl + * + * This file is part of libSplash. + * + * libSplash is free software: you can redistribute it and/or modify + * it under the terms of of either the GNU General Public License or + * the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libSplash is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser General Public License along with libSplash. + * If not, see . + */ + +#include "splash/core/SDCHelper.hpp" + +#include "splash/version.hpp" +#include "splash/basetypes/ColTypeDim.hpp" +#include "splash/basetypes/ColTypeString.hpp" +#include "splash/core/DCAttribute.hpp" +#include "splash/core/logging.hpp" + +#include + +namespace splash +{ + + std::string SDCHelper::getExceptionString(std::string msg) + { + return (std::string("Exception for [SDCHelper] ") + msg); + } + + void SDCHelper::getReferenceData(const char* filename, int32_t* maxID, Dimensions *mpiSize) + throw (DCException) + { + log_msg(1, "loading reference data from %s", filename); + + // open the file to get reference data from + hid_t reference_file = H5Fopen(filename, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT); + if (reference_file < 0) + throw DCException(getExceptionString(std::string("Failed to open reference file ") + + std::string(filename))); + + // reference data is located in the header only + hid_t group_header = H5Gopen(reference_file, SDC_GROUP_HEADER, H5P_DEFAULT); + if (group_header < 0) { + H5Fclose(reference_file); + throw DCException(getExceptionString( + std::string("Failed to open header group in reference file ") + + std::string(filename))); + } + + try { + if (maxID != NULL) { + DCAttribute::readAttribute(SDC_ATTR_MAX_ID, + group_header, maxID); + } + + if (mpiSize != NULL) { + ColTypeDim dim_t; + DCAttribute::readAttribute(SDC_ATTR_MPI_SIZE, + group_header, mpiSize->getPointer()); + } + + } catch (DCException attr_exception) { + H5Fclose(reference_file); + throw DCException(getExceptionString( + std::string("Failed to read attributes from reference file ") + + std::string(filename))); + } + + // cleanup + H5Gclose(group_header); + H5Fclose(reference_file); + } + + void SDCHelper::writeHeader(hid_t file, Dimensions mpiPosition, + int32_t *maxID, bool *enableCompression, Dimensions *mpiSize, + bool master) + throw (DCException) + { + // create group for header information (position, grid size, ...) + hid_t group_header = H5Gcreate(file, SDC_GROUP_HEADER, H5P_LINK_CREATE_DEFAULT, + H5P_GROUP_CREATE_DEFAULT, H5P_GROUP_ACCESS_DEFAULT); + if (group_header < 0) + throw DCException(getExceptionString("Failed to create header group in reference file")); + + try { + std::stringstream splashVersion; + splashVersion << SPLASH_VERSION_MAJOR << "." + << SPLASH_VERSION_MINOR << "." + << SPLASH_VERSION_PATCH; + std::stringstream splashFormat; + splashFormat << SPLASH_FILE_FORMAT_MAJOR << "." + << SPLASH_FILE_FORMAT_MINOR; + + ColTypeDim dim_t; + ColTypeString ctStringVersion(splashVersion.str().length()); + ColTypeString ctStringFormat(splashFormat.str().length()); + + // create master specific header attributes + if (master) { + DCAttribute::writeAttribute(SDC_ATTR_MAX_ID, H5T_NATIVE_INT32, + group_header, maxID); + } else { + DCAttribute::writeAttribute(SDC_ATTR_MPI_POSITION, dim_t.getDataType(), + group_header, mpiPosition.getPointer()); + } + + DCAttribute::writeAttribute(SDC_ATTR_COMPRESSION, H5T_NATIVE_HBOOL, + group_header, enableCompression); + + DCAttribute::writeAttribute(SDC_ATTR_MPI_SIZE, dim_t.getDataType(), + group_header, mpiSize->getPointer()); + + DCAttribute::writeAttribute(SDC_ATTR_VERSION, ctStringVersion.getDataType(), + group_header, splashVersion.str().c_str()); + + DCAttribute::writeAttribute(SDC_ATTR_FORMAT, ctStringFormat.getDataType(), + group_header, splashFormat.str().c_str()); + + } catch (DCException attr_error) { + throw DCException(getExceptionString( + std::string("Failed to write header attribute in reference file. Error was: ") + + std::string(attr_error.what()))); + } + + H5Gclose(group_header); + } + +} /* namespace splash */ diff --git a/src/include/splash/core/SDCHelper.hpp b/src/include/splash/core/SDCHelper.hpp index b2904c2..2dfc91a 100644 --- a/src/include/splash/core/SDCHelper.hpp +++ b/src/include/splash/core/SDCHelper.hpp @@ -1,35 +1,34 @@ /** - * Copyright 2013 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * - * This file is part of libSplash. - * - * libSplash is free software: you can redistribute it and/or modify - * it under the terms of of either the GNU General Public License or - * the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * libSplash is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License and the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * and the GNU Lesser General Public License along with libSplash. - * If not, see . - */ - - + * This file is part of libSplash. + * + * libSplash is free software: you can redistribute it and/or modify + * it under the terms of of either the GNU General Public License or + * the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libSplash is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser General Public License along with libSplash. + * If not, see . + */ #ifndef SDCHELPER_H -#define SDCHELPER_H +#define SDCHELPER_H -#include "splash/basetypes/ColTypeDim.hpp" #include "splash/sdc_defines.hpp" -#include "splash/core/DCAttribute.hpp" -#include "splash/core/logging.hpp" +#include "splash/Dimensions.hpp" #include "splash/DCException.hpp" +#include + namespace splash { @@ -41,10 +40,7 @@ namespace splash private: SDCHelper(); - static std::string getExceptionString(std::string msg) - { - return (std::string("Exception for [SDCHelper] ") + msg); - } + static std::string getExceptionString(std::string msg); public: @@ -56,48 +52,7 @@ namespace splash * @param mpiSize pointer to hold size of mpi grid. can be NULL */ static void getReferenceData(const char* filename, int32_t* maxID, Dimensions *mpiSize) - throw (DCException) - { - log_msg(1, "loading reference data from %s", filename); - - // open the file to get reference data from - hid_t reference_file = H5Fopen(filename, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT); - if (reference_file < 0) - throw DCException(getExceptionString(std::string("Failed to open reference file ") + - std::string(filename))); - - // reference data is located in the header only - hid_t group_header = H5Gopen(reference_file, SDC_GROUP_HEADER, H5P_DEFAULT); - if (group_header < 0) { - H5Fclose(reference_file); - throw DCException(getExceptionString( - std::string("Failed to open header group in reference file ") + - std::string(filename))); - } - - try { - if (maxID != NULL) { - DCAttribute::readAttribute(SDC_ATTR_MAX_ID, - group_header, maxID); - } - - if (mpiSize != NULL) { - ColTypeDim dim_t; - DCAttribute::readAttribute(SDC_ATTR_MPI_SIZE, - group_header, mpiSize->getPointer()); - } - - } catch (DCException attr_exception) { - H5Fclose(reference_file); - throw DCException(getExceptionString( - std::string("Failed to read attributes from reference file ") + - std::string(filename))); - } - - // cleanup - H5Gclose(group_header); - H5Fclose(reference_file); - } + throw (DCException); /** * Writes header information to file. @@ -112,42 +67,8 @@ namespace splash static void writeHeader(hid_t file, Dimensions mpiPosition, int32_t *maxID, bool *enableCompression, Dimensions *mpiSize, bool master = false) - throw (DCException) - { - // create group for header information (position, grid size, ...) - hid_t group_header = H5Gcreate(file, SDC_GROUP_HEADER, H5P_LINK_CREATE_DEFAULT, - H5P_GROUP_CREATE_DEFAULT, H5P_GROUP_ACCESS_DEFAULT); - if (group_header < 0) - throw DCException(getExceptionString("Failed to create header group in reference file")); - - try { - ColTypeDim dim_t; - - // create master specific header attributes - if (master) { - DCAttribute::writeAttribute(SDC_ATTR_MAX_ID, H5T_NATIVE_INT32, - group_header, maxID); - } else { - DCAttribute::writeAttribute(SDC_ATTR_MPI_POSITION, dim_t.getDataType(), - group_header, mpiPosition.getPointer()); - } - - DCAttribute::writeAttribute(SDC_ATTR_COMPRESSION, H5T_NATIVE_HBOOL, - group_header, enableCompression); - - DCAttribute::writeAttribute(SDC_ATTR_MPI_SIZE, dim_t.getDataType(), - group_header, mpiSize->getPointer()); - - } catch (DCException attr_error) { - throw DCException(getExceptionString( - std::string("Failed to write header attribute in reference file. Error was: ") + - std::string(attr_error.what()))); - } - - H5Gclose(group_header); - } + throw (DCException); }; } #endif /* SDCHELPER_H */ - diff --git a/src/include/splash/sdc_defines.hpp b/src/include/splash/sdc_defines.hpp index 330904c..2d92748 100644 --- a/src/include/splash/sdc_defines.hpp +++ b/src/include/splash/sdc_defines.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -39,6 +40,8 @@ namespace splash #define SDC_ATTR_GRID_SIZE "grid_size" #define SDC_ATTR_SIZE "client_size" #define SDC_ATTR_COMPRESSION "compression" +#define SDC_ATTR_VERSION "splashVersion" +#define SDC_ATTR_FORMAT "splashFormat" } #endif /* SDC_DEFINES_H */ From dd30e7744ee140bb792284219f25c94588dbf572 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Mon, 10 Aug 2015 21:35:21 +0200 Subject: [PATCH 30/47] h5py tests: print version/format in serial file --- tests/readBoolChar.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/readBoolChar.py b/tests/readBoolChar.py index 93bb478..08c502c 100755 --- a/tests/readBoolChar.py +++ b/tests/readBoolChar.py @@ -26,6 +26,12 @@ # bool compatible data sets ################################################### f = h5py.File("h5/testWriteRead_0_0_0.h5", "r") + +# print version +print("Splash version: {}".format(f["header"].attrs["splashVersion"])) +print("Splash format: {}".format(f["header"].attrs["splashFormat"])) + +# read data set data = f["data/10/deep/folders/data_bool"] len = data.size From ee2dc4232da710a32394526e4ae58279b48a8391 Mon Sep 17 00:00:00 2001 From: PrometheusPi Date: Tue, 18 Aug 2015 20:35:54 +0200 Subject: [PATCH 31/47] add warning to test run scripts if no build directory is given --- tests/run_parallel_tests | 6 ++++++ tests/run_tests | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/tests/run_parallel_tests b/tests/run_parallel_tests index a37ea34..ed821b4 100755 --- a/tests/run_parallel_tests +++ b/tests/run_parallel_tests @@ -1,5 +1,11 @@ #!/bin/bash +if [ $# -eq 0 ]; then + echo " WARNING:" + echo " No path for build director was given." + echo " Will use \"build\" instead." +fi + dir=${1:-build} rm -rf $dir/h5 diff --git a/tests/run_tests b/tests/run_tests index ceb7578..fef41a1 100755 --- a/tests/run_tests +++ b/tests/run_tests @@ -1,5 +1,11 @@ #!/bin/bash +if [ $# -eq 0 ]; then + echo " WARNING:" + echo " No path for build director was given." + echo " Will use \"build\" instead." +fi + dir=${1:-build} rm -rf $dir/h5 From 9f7cf45ba3a73aecf19e632b87edc33612957acb Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Fri, 21 Aug 2015 01:35:38 -0700 Subject: [PATCH 32/47] Update Manual: Iterations Related to #157 --- doc/manual/UserManual.pdf | Bin 235995 -> 236124 bytes doc/manual/UserManual.tex | 10 ++++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/manual/UserManual.pdf b/doc/manual/UserManual.pdf index 1e56bd1b2874112f4e639d1501d8a03d876c349d..e7037193679cb75853edd949a498b6ab75f8240f 100644 GIT binary patch delta 8347 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 ahlQJmkDHY>F28^fF7Q9W$||p^fcrnhxb{{6 delta 8225 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 Fe*g=!wHW{a diff --git a/doc/manual/UserManual.tex b/doc/manual/UserManual.tex index a95d981..b3851e6 100644 --- a/doc/manual/UserManual.tex +++ b/doc/manual/UserManual.tex @@ -176,7 +176,9 @@ \subsection{File Structure} Each libSplash file uses a similar internal file structure which is composed from groups (folders), datasets, attributes and references. A dataset in a libSplash HDF5 file is stored in the data group -(see below) under its timestamp, e.g. \code{/data/100/my\_dataset}. +(see below) under its corresponding iteration, e.g. \code{/data/100/my\_dataset}. +We refer to iterations (of algorithms and/or simulations) instead of \textit{time steps} +since for some algorithms time steps can change (or are not defined in the first place). Groups can be organized in hierarchies. \begin{itemize} @@ -422,7 +424,7 @@ \section{Files} the filename structure is \emph{(common name)\_(iteration).h5}. \emph{common name} is the name chosen by the user for the libSplash files, e.g. 'simulation\_data'. -\emph{iteration} is the iteration id (simulation timestep), e.g. 0, 100, 512. +\emph{iteration} is the iteration id, e.g. 0, 100, 512. One file is created for each iteration for the sake of resilience. Example: @@ -486,7 +488,7 @@ \section{Notes} When using parallel libSplash, the functions \code{getMaxID} and \code{getEntryIDs} internally list the files in the directory of the HDF5 filename given at \code{open} -to obtain the list of available timestamps for this file set. +to obtain the list of available iterations for this file set. Therefore, old files in the same directory with the same common filename part will be recognized as belonging to the current file set, too. @@ -520,7 +522,7 @@ \section{splashtools} Features include: \begin{itemize} \item List all file entries. - \item Transparently delete timesteps in all HDF5 files belonging to a single run. + \item Transparently delete all iterations in all HDF5 files belonging to a single run. \item Check files for syntactic and semantic consistency. \end{itemize} Run \command{splashtools --help} for a complete list of all current features. From b7b1117ac95c5812c21aa9b0997c109682158fa3 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Fri, 21 Aug 2015 01:52:36 -0700 Subject: [PATCH 33/47] Documentation: Iteration Instead of Time Step changes all plain documentations related to #157 without changing APIs, file formats or tools such as `splash2xdmf.py` --- examples/domain_read/domain_read.cpp | 7 ++++--- examples/domain_read/domain_read_mpi.cpp | 3 ++- examples/domain_write/domain_write_mpi.cpp | 3 ++- src/ParallelDataCollector.cpp | 2 +- tests/AttributesTest.cpp | 5 +++-- tools/splashtools.cpp | 5 +++-- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/examples/domain_read/domain_read.cpp b/examples/domain_read/domain_read.cpp index 7fb3d6b..633e2e4 100644 --- a/examples/domain_read/domain_read.cpp +++ b/examples/domain_read/domain_read.cpp @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -70,8 +71,8 @@ int main(int argc, char **argv) dc.getEntryIDs(ids, &num_ids); } - // get entries for 1. id (timestep) - std::cout << "reading from timestep " << ids[0] << std::endl; + // get entries for 1. id (iteration) + std::cout << "reading from iteration " << ids[0] << std::endl; DataCollector::DCEntry *entries = NULL; size_t num_entries = 0; dc.getEntriesForID(ids[0], NULL, &num_entries); @@ -87,7 +88,7 @@ int main(int argc, char **argv) dc.getEntriesForID(ids[0], entries, &num_entries); } - // read 1. entry from this timestep + // read 1. entry from this iteration DataCollector::DCEntry first_entry = entries[0]; std::cout << "reading entry " << first_entry.name << std::endl; diff --git a/examples/domain_read/domain_read_mpi.cpp b/examples/domain_read/domain_read_mpi.cpp index fdf4489..d7d1617 100644 --- a/examples/domain_read/domain_read_mpi.cpp +++ b/examples/domain_read/domain_read_mpi.cpp @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -142,7 +143,7 @@ int main(int argc, char **argv) dc.getEntryIDs(ids, &num_ids); } - // get entries for 1. id (timestep) + // get entries for 1. id (iteration) DataCollector::DCEntry *entries = NULL; size_t num_entries = 0; dc.getEntriesForID(ids[0], NULL, &num_entries); diff --git a/examples/domain_write/domain_write_mpi.cpp b/examples/domain_write/domain_write_mpi.cpp index ad19254..7f51354 100644 --- a/examples/domain_write/domain_write_mpi.cpp +++ b/examples/domain_write/domain_write_mpi.cpp @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -100,7 +101,7 @@ int main(int argc, char **argv) * http://computationalradiationphysics.github.io/libSplash/classsplash_1_1_domain_collector.html * for more information on this interface. **/ - dc.writeDomain(10, /* timestamp/iteration */ + dc.writeDomain(10, /* iteration */ ctFloat, /* data type */ localGridSize.getDims(), /* number of dimensions (here 3) */ Selection(localGridSize), /* data size of this process */ diff --git a/src/ParallelDataCollector.cpp b/src/ParallelDataCollector.cpp index c2cec7c..63f85ea 100644 --- a/src/ParallelDataCollector.cpp +++ b/src/ParallelDataCollector.cpp @@ -102,7 +102,7 @@ namespace splash log_msg(2, "listing files for %s", baseFilename.c_str()); /* Split baseFilename into path and name prefix. - * Always append '_' since PDC filenames are 'prefix_timestep.h5'. + * Always append '_' since PDC filenames are 'prefix_iteration.h5'. * e.g. '/path/to/filename' -> dir_path='/path/to/' name='filename_' */ std::string dir_path, name; diff --git a/tests/AttributesTest.cpp b/tests/AttributesTest.cpp index 57a2212..3370b6b 100644 --- a/tests/AttributesTest.cpp +++ b/tests/AttributesTest.cpp @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -77,7 +78,7 @@ void AttributesTest::testDataAttributes() } sum2 = sum; - dataCollector->writeAttribute(10, ctInt, NULL, "timestep", &sum2); + dataCollector->writeAttribute(10, ctInt, NULL, "iteration", &sum2); /* variable length string, '\0' terminated */ const char *string_attr = {"My first c-string."}; @@ -125,7 +126,7 @@ void AttributesTest::testDataAttributes() dataCollector->open(TEST_FILE, attr); - dataCollector->readAttribute(10, NULL, "timestep", &sum2); + dataCollector->readAttribute(10, NULL, "iteration", &sum2); char* string_read; dataCollector->readAttribute(10, NULL, "my_string", &string_read); diff --git a/tools/splashtools.cpp b/tools/splashtools.cpp index b4721e0..9fd042f 100644 --- a/tools/splashtools.cpp +++ b/tools/splashtools.cpp @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -488,7 +489,7 @@ int listAvailableDatasets(Options& options, DataCollector *dc, const char* /*fil } } - // number of timesteps in this file + // number of iterations in this file size_t num_entries = 0; dc->getEntriesForID(id, NULL, &num_entries); @@ -499,7 +500,7 @@ int listAvailableDatasets(Options& options, DataCollector *dc, const char* /*fil for (size_t i = 0; i < num_entries; ++i) std::cout << entries[i].name << std::endl; - + delete[] entries; } From c5e6013e619aa1811f6f64b51e3b37da897770dd Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Fri, 21 Aug 2015 01:55:25 -0700 Subject: [PATCH 34/47] Close #157 splash2xdmf iteration Draws the connection between libSplash iterations and XDMF time steps in splash2xdmf.py to do: - [ ] run time test - [ ] cross check against `pic2xdmf.py` to see if all hooks are still working correctly --- tools/splash2xdmf.py | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/tools/splash2xdmf.py b/tools/splash2xdmf.py index 22e5930..ba02867 100644 --- a/tools/splash2xdmf.py +++ b/tools/splash2xdmf.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# Copyright 2014 Felix Schmitt, Conrad Schumann, Axel Huebl +# Copyright 2014-2015 Felix Schmitt, Conrad Schumann, Axel Huebl # # This file is part of libSplash. # @@ -92,7 +92,7 @@ def get_common_filename(filename): def get_attr_name(dset_name): """ - Return name part of HDF5 dataset without /data/ + Return name part of HDF5 dataset without /data/ Parameters: ---------------- @@ -101,7 +101,7 @@ def get_attr_name(dset_name): Returns: ---------------- return: string - dataset name part with /data/ stripped + dataset name part with /data/ stripped """ index = dset_name.find("/", len("/data/")) @@ -311,7 +311,7 @@ def create_timestep_node(time): Parameters: ---------------- time: int - time step + re-interpret libSplash iterations as time steps Returns: ---------------- return: Element @@ -411,9 +411,10 @@ def parse_hdf5_recursive(h5Group, h5filename, level): print_dataset(h5Group[g], level, h5filename) -def get_timestep_for_group(dataGroup): +def get_iteration_for_group(dataGroup): """ - Return the time step for an libSplash HDF5 group of type /data/ + Return the iteration for an libSplash HDF5 group of type /data/. + Will be re-interpreted as time steps for XDMF. Parameters: ---------------- @@ -422,12 +423,12 @@ def get_timestep_for_group(dataGroup): Returns: ---------------- return: string - part as string + part as string """ groups = dataGroup.keys() if len(groups) != 1: - print("Error: data group is expected to have a single timestep child group") + print("Error: data group is expected to have a single iteration child group") return -1 objClass = dataGroup.get(groups[0], None, True) @@ -476,15 +477,15 @@ def create_xdmf_for_splash_file(base_node_grid, base_node_poly, splashFilename, h5file.close() return False - time_step = get_timestep_for_group(dataGroup) + iteration = get_iteration_for_group(dataGroup) parse_hdf5_recursive(dataGroup, splashFilenameXmf, 1) # append all collected grids to current xml base node index = 0 for grid in grids.values(): - grid.setAttribute("Name", "Grid_{}_{}".format(time_step, index)) - grid.appendChild(create_timestep_node(time_step)) + grid.setAttribute("Name", "Grid_{}_{}".format(iteration, index)) + grid.appendChild(create_timestep_node(iteration)) base_node_grid.appendChild(grid) index += 1 grids.clear() @@ -492,8 +493,8 @@ def create_xdmf_for_splash_file(base_node_grid, base_node_poly, splashFilename, # append all collected polys to current xml base node index = 0 for poly in polys.values(): - poly.setAttribute("Name", "Poly_{}_{}".format(time_step, index)) - poly.appendChild(create_timestep_node(time_step)) + poly.setAttribute("Name", "Poly_{}_{}".format(iteration, index)) + poly.appendChild(create_timestep_node(iteration)) base_node_poly.appendChild(poly) index += 1 polys.clear() @@ -544,7 +545,7 @@ def create_xdmf_xml(splash_files_list, args): XML XDMF root node """ - time_series = (len(splash_files_list) > 1) + iteration_series = (len(splash_files_list) > 1) # setup xml structure xdmf_root = doc.createElement("Xdmf") @@ -560,7 +561,7 @@ def create_xdmf_xml(splash_files_list, args): base_node_grid = grid_domain base_node_poly = poly_domain - if time_series: + if iteration_series: if args.no_splitgrid: main_grid = doc.createElement("Grid") main_poly = doc.createElement("Grid") @@ -577,7 +578,7 @@ def create_xdmf_xml(splash_files_list, args): create_xdmf_for_splash_file(base_node_grid, base_node_poly, current_file, args) # finalize xml structure - if time_series: + if iteration_series: if args.no_splitgrid: domain.appendChild(main_grid) domain.appendChild(main_poly) @@ -646,7 +647,7 @@ def get_args_parser(): parser.add_argument("-v", "--verbose", help="Produce verbose output", action="store_true") - parser.add_argument("-t", "--time", help="Aggregate information over a time-series of libSplash data", action="store_true") + parser.add_argument("-t", "--time", help="Aggregate information over a time-series over iterations in libSplash data", action="store_true") parser.add_argument("--fullpath", help="Use absolute paths for HDF5 files", action="store_true") @@ -666,13 +667,13 @@ def main(): # apply arguments splashFilename = args.splashfile - time_series = args.time + iteration_series = args.time if args.verbose: verbosity_level = 100 # create the list of requested splash files splash_files = list() - if time_series: + if iteration_series: splashFilename = get_common_filename(splashFilename) for s_filename in glob.glob("{}_*.h5".format(splashFilename)): splash_files.append(s_filename) From 3122be3510bb4a5b02fb94a095aa272a550c053f Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Wed, 26 Aug 2015 08:49:46 +0200 Subject: [PATCH 35/47] splashtools: iteration instead of step --- tools/splashtools.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/splashtools.cpp b/tools/splashtools.cpp index 9fd042f..95d4036 100644 --- a/tools/splashtools.cpp +++ b/tools/splashtools.cpp @@ -42,19 +42,19 @@ typedef struct { bool singleFile; bool checkIntegrity; - bool deleteStep; + bool deleteIteration; bool listEntries; bool parallelFile; bool verbose; std::string filename; - int32_t step; + int32_t iteration; int mpiRank; int mpiSize; int fileIndexStart; int fileIndexEnd; } Options; -int deleteFromStep(Options& options); +int deleteFromIteration(Options& options); int testFileIntegrity(Options& options); /* helper functions */ @@ -62,7 +62,7 @@ int testFileIntegrity(Options& options); void initOptions(Options& options) { options.checkIntegrity = false; - options.deleteStep = false; + options.deleteIteration = false; options.listEntries = false; options.parallelFile = false; options.fileIndexEnd = -1; @@ -71,11 +71,11 @@ void initOptions(Options& options) options.mpiRank = 0; options.mpiSize = 1; options.singleFile = false; - options.step = 0; + options.iteration = 0; options.verbose = false; } -void deleteFromStepInFile(DataCollector *dc, int32_t step) +void deleteFromIterationInFile(DataCollector *dc, int32_t iteration) { size_t num_entries = 0; dc->getEntryIDs(NULL, &num_entries); @@ -85,7 +85,7 @@ void deleteFromStepInFile(DataCollector *dc, int32_t step) for (size_t i = 0; i < num_entries; ++i) { - if (entries[i] >= step) + if (entries[i] >= iteration) { dc->remove(entries[i]); } @@ -104,7 +104,7 @@ int parseCmdLine(int argc, char **argv, Options& options) full_desc_stream << usage_stream.str() << std::endl << " --help,-h\t\t\t print this help message" << std::endl << " --file,-f\t\t\t HDF5 libSplash file to edit" << std::endl << - " --delete,-d\t\t\t Delete [d,*) simulation steps" << std::endl << + " --delete,-d\t\t\t Delete iterations [d,*)" << std::endl << " --check,-c\t\t\t Check file integrity" << std::endl << " --list,-l\t\t\t List all file entries" << std::endl << #if (SPLASH_SUPPORTED_PARALLEL==1) @@ -151,7 +151,7 @@ int parseCmdLine(int argc, char **argv, Options& options) return RESULT_ERROR; } - options.step = atoi(next_option); + options.iteration = atoi(next_option); i++; continue; } @@ -406,7 +406,7 @@ int executeToolFunction(Options& options, // get mpi position from index indexToPos(i, fileMPISizeDim, mpi_pos); - // delete steps in this file + // delete iterations in this file std::stringstream mpiFilename; #if (SPLASH_SUPPORTED_PARALLEL==1) if (options.parallelFile) @@ -428,7 +428,7 @@ int executeToolFunction(Options& options, return result; } -int deleteFromStep(Options& options, DataCollector *dc, const char *filename) +int deleteFromIteration(Options& options, DataCollector *dc, const char *filename) { int result = RESULT_OK; DataCollector::FileCreationAttr fileCAttr; @@ -437,14 +437,14 @@ int deleteFromStep(Options& options, DataCollector *dc, const char *filename) if (options.verbose) { - std::cout << "[" << options.mpiRank << "] Deleting from step " << - options.step << " in file " << filename << std::endl; + std::cout << "[" << options.mpiRank << "] Deleting from iteration " << + options.iteration << " in file " << filename << std::endl; } try { dc->open(filename, fileCAttr); - deleteFromStepInFile(dc, options.step); + deleteFromIterationInFile(dc, options.iteration); dc->close(); } catch (DCException e) { @@ -528,8 +528,8 @@ int main(int argc, char **argv) if (options.checkIntegrity) result = executeToolFunction(options, testFileIntegrity); - if (options.deleteStep) - result = executeToolFunction(options, deleteFromStep); + if (options.deleteIteration) + result = executeToolFunction(options, deleteFromIteration); if (options.listEntries) result = executeToolFunction(options, listAvailableDatasets); From 95b42572ee485141508fbf6e35d98320f0e21d66 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Thu, 27 Aug 2015 14:32:12 +0200 Subject: [PATCH 36/47] Draft readMeta --- src/DCGroup.cpp | 3 ++ src/SerialDataCollector.cpp | 51 ++++++++++++++++++++ src/include/splash/ParallelDataCollector.hpp | 7 +++ src/include/splash/SerialDataCollector.hpp | 18 +++++++ tools/splashtools.cpp | 10 +++- 5 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/DCGroup.cpp b/src/DCGroup.cpp index 7c0b105..dd9f6e4 100644 --- a/src/DCGroup.cpp +++ b/src/DCGroup.cpp @@ -196,7 +196,10 @@ namespace splash if (obj_info.type == H5O_TYPE_DATASET) { if (param->entries) + { param->entries[param->count].name = currentBaseName; + // type ... + } param->count++; } diff --git a/src/SerialDataCollector.cpp b/src/SerialDataCollector.cpp index c8b6a77..cae2664 100644 --- a/src/SerialDataCollector.cpp +++ b/src/SerialDataCollector.cpp @@ -425,6 +425,22 @@ namespace splash Dimensions(0, 0, 0), sizeRead, ndims, data); } + void SerialDataCollector::readMeta(int32_t id, + CollectionType &type, + const char* name, + const Dimensions dstBuffer, + const Dimensions dstOffset, + Dimensions &sizeRead) + throw (DCException) + { + if (fileStatus != FST_READING && fileStatus != FST_WRITING && fileStatus != FST_MERGING) + throw DCException(getExceptionString("read", "this access is not permitted")); + + uint32_t ndims = 0; + readDataSetMeta(handles.get(0), id, type, name, dstBuffer, dstOffset, + Dimensions(0, 0, 0), sizeRead, ndims); + } + void SerialDataCollector::write(int32_t id, const CollectionType& type, uint32_t ndims, const Selection select, const char* name, const void* data) throw (DCException) @@ -957,6 +973,41 @@ namespace splash dataset.close(); } + void SerialDataCollector::readDataSetMeta(H5Handle h5File, + int32_t id, + CollectionType &type, + const char* name, + const Dimensions dstBuffer, + const Dimensions dstOffset, + const Dimensions srcOffset, + Dimensions &sizeRead, + uint32_t& srcDims) + throw (DCException) + { + log_msg(2, "readDataSetMeta"); + + std::string group_path, dset_name; + DCDataSet::getFullDataPath(name, SDC_GROUP_DATA, id, group_path, dset_name); + + DCGroup group; + group.open(h5File, group_path); + + DCDataSet dataset(dset_name.c_str()); + dataset.open(group.getHandle()); + + size_t datatype_size = 0; + DCDataType dc_datatype = DCDT_UNKNOWN; + datatype_size = dataset.getDataTypeSize(); + dc_datatype = dataset.getDCDataType(); + + // make a collection for "type" out of it... + //type.getDataType() = ... + + Dimensions src_size(dataset.getSize() - srcOffset); + dataset.read(dstBuffer, dstOffset, src_size, srcOffset, sizeRead, srcDims, NULL); + dataset.close(); + } + void SerialDataCollector::readSizeInternal(H5Handle h5File, int32_t id, const char* name, diff --git a/src/include/splash/ParallelDataCollector.hpp b/src/include/splash/ParallelDataCollector.hpp index 1224b84..51c108e 100644 --- a/src/include/splash/ParallelDataCollector.hpp +++ b/src/include/splash/ParallelDataCollector.hpp @@ -312,6 +312,13 @@ namespace splash Dimensions &sizeRead, void* buf) throw (DCException); +/* void readMeta(int32_t id, + CollectionType &type, + const char* name, + const Dimensions dstBuffer, + const Dimensions dstOffset, + Dimensions &sizeRead) throw (DCException);*/ + /** * Reads data from HDF5 file. * If data is to be read (instead of only its size in the file), diff --git a/src/include/splash/SerialDataCollector.hpp b/src/include/splash/SerialDataCollector.hpp index 51f73af..8988f50 100644 --- a/src/include/splash/SerialDataCollector.hpp +++ b/src/include/splash/SerialDataCollector.hpp @@ -161,6 +161,17 @@ namespace splash void* dst) throw (DCException); + void readDataSetMeta(H5Handle h5File, + int32_t id, + CollectionType &type, + const char* name, + const Dimensions dstBuffer, + const Dimensions dstOffset, + const Dimensions srcOffset, + Dimensions &sizeRead, + uint32_t& srcDims) + throw (DCException); + /** * Internal reading method. */ @@ -321,6 +332,13 @@ namespace splash const Dimensions dstOffset, Dimensions &sizeRead, void* data) throw (DCException); + + void readMeta(int32_t id, + CollectionType &type, + const char* name, + const Dimensions dstBuffer, + const Dimensions dstOffset, + Dimensions &sizeRead) throw (DCException); }; } // namespace DataCollector diff --git a/tools/splashtools.cpp b/tools/splashtools.cpp index 95d4036..ddef5db 100644 --- a/tools/splashtools.cpp +++ b/tools/splashtools.cpp @@ -499,7 +499,15 @@ int listAvailableDatasets(Options& options, DataCollector *dc, const char* /*fil dc->getEntriesForID(id, entries, NULL); for (size_t i = 0; i < num_entries; ++i) - std::cout << entries[i].name << std::endl; + { + //DCDataType data_type = dc->getIndex(i)->getDataType(); + Dimensions sizeRead; + dc->read(id, entries[i].name.c_str(), sizeRead, NULL); + std::cout << entries[i].name + //<< "(type: " << data_type << ")" + << " " << sizeRead.toString() + << std::endl; + } delete[] entries; } From 115df0e1fdd5081e32cc4edda40bda5be12bcea1 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Wed, 16 Sep 2015 16:21:52 +0200 Subject: [PATCH 37/47] CMake: HDF5 Has Shared This PR refactores the CMakeLists.txt a little: what we actually want to know is, if a shared library is available (and then we prefer it). Before that, we assumed that either a shared or a static library exists, which still works but it somewhat obfuscating. --- CMakeLists.txt | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1004db7..46ae336 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,15 +76,14 @@ MESSAGE(STATUS "Building libSplash version ${SPLASH_VERSION}") FIND_PACKAGE(HDF5 1.8.6 REQUIRED) INCLUDE_DIRECTORIES(SYSTEM ${HDF5_INCLUDE_DIR}) -# check if static version of HDF5 is used -# CMake prefers .so/shared libraries -# if we find a static HDF5 lib in the ${HDF5_LIBRARIES} -# it means there is only a static version installed -SET(HDF5_IS_STATIC ON) -STRING(FIND "${HDF5_LIBRARIES}" "hdf5.a" HDF5_IS_STATIC_POS) -IF(${HDF5_IS_STATIC_POS} EQUAL -1) - SET(HDF5_IS_STATIC OFF) -ENDIF(${HDF5_IS_STATIC_POS} EQUAL -1) +# check if shared version of HDF5 can be used +# CMake prefers .so/shared libraries over static ones +SET(HDF5_HAS_SHARED ON) +STRING(FIND "${HDF5_LIBRARIES}" "hdf5.so" HDF5_HAS_SHARED_POS) +IF(${HDF5_HAS_SHARED_POS} EQUAL -1) + SET(HDF5_HAS_SHARED OFF) +ENDIF() +UNSET(HDF5_HAS_SHARED_POS) #------------------------------------------------------------------------------- @@ -147,12 +146,12 @@ AUX_SOURCE_DIRECTORY("${CMAKE_CURRENT_SOURCE_DIR}/tools" TOOLS_SOURCES) #------------------------------------------------------------------------------- # build libsplash shared (if shared HDF5 is used) -IF(HDF5_IS_STATIC) +IF(NOT HDF5_HAS_SHARED) MESSAGE(WARNING "Skipping dynamic libSplash because HDF5 library is static") -ELSE(HDF5_IS_STATIC) +ELSE() ADD_LIBRARY(splash SHARED ${LIBRARY_SOURCES}) TARGET_LINK_LIBRARIES(splash ${SPLASH_LIBS}) -ENDIF(HDF5_IS_STATIC) +ENDIF() # build libsplash static ADD_LIBRARY(splash_static STATIC ${LIBRARY_SOURCES}) @@ -160,9 +159,9 @@ SET_TARGET_PROPERTIES(splash_static PROPERTIES OUTPUT_NAME splash) TARGET_LINK_LIBRARIES (splash_static ${SPLASH_LIBS}) # install libs -IF(NOT HDF5_IS_STATIC) +IF(HDF5_HAS_SHARED) INSTALL(TARGETS splash LIBRARY DESTINATION lib) -ENDIF(NOT HDF5_IS_STATIC) +ENDIF() INSTALL(TARGETS splash_static ARCHIVE DESTINATION lib) @@ -220,7 +219,11 @@ OPTION(WITH_TOOLS "enable splashtools" ON) IF(WITH_TOOLS) MESSAGE(STATUS "Building splashtools") - SET(TOOLS_LIBS ${TOOLS_LIBS} splash_static) + IF(HDF5_HAS_SHARED) + SET(TOOLS_LIBS ${TOOLS_LIBS} splash) + ELSE() + SET(TOOLS_LIBS ${TOOLS_LIBS} splash_static) + ENDIF() INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) # MPI for tools From 2038b2aca97041403eded88f75e4c2e5a917762f Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Tue, 6 Oct 2015 14:03:44 +0200 Subject: [PATCH 38/47] Travis: Check Bool Identification --- tests/readBoolChar.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/readBoolChar.py b/tests/readBoolChar.py index 08c502c..705ea55 100755 --- a/tests/readBoolChar.py +++ b/tests/readBoolChar.py @@ -33,6 +33,10 @@ # read data set data = f["data/10/deep/folders/data_bool"] +print(data, type(data), data.dtype) + +if not type(data[0,0,0]) is np.bool_: + exit(1) len = data.size data1d = data[:,:,:].reshape(len) From 49f4788fdcfc2a25119b53723bc5ff84e105394e Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Tue, 6 Oct 2015 13:27:50 +0200 Subject: [PATCH 39/47] Bool: CAPS Enum Labels for h5py Else it does not identify those as `bool_` but as `int8`. Regression for #153 (still in `dev`). Increases format by a minor since the structure is still the same but the identification in `h5py` is improved (and it is still not in a stable release). --- src/include/splash/basetypes/ColTypeBool.hpp | 2 +- src/include/splash/version.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/splash/basetypes/ColTypeBool.hpp b/src/include/splash/basetypes/ColTypeBool.hpp index 8fc49ac..da0481c 100644 --- a/src/include/splash/basetypes/ColTypeBool.hpp +++ b/src/include/splash/basetypes/ColTypeBool.hpp @@ -40,7 +40,7 @@ class ColTypeBool : public CollectionType // this is a h5py compatible implementation for bool, see: // http://docs.h5py.org/en/latest/faq.html this->type = H5Tenum_create(H5T_NATIVE_INT8); - const char *names[2] = {"true", "false"}; + const char *names[2] = {"TRUE", "FALSE"}; const int64_t val[2] = {1, 0}; H5Tenum_insert(this->type, names[0], &val[0]); H5Tenum_insert(this->type, names[1], &val[1]); diff --git a/src/include/splash/version.hpp b/src/include/splash/version.hpp index 91dda60..82ece2d 100644 --- a/src/include/splash/version.hpp +++ b/src/include/splash/version.hpp @@ -32,7 +32,7 @@ * changes in the minor number have to be backwards compatible */ #define SPLASH_FILE_FORMAT_MAJOR 3 -#define SPLASH_FILE_FORMAT_MINOR 2 +#define SPLASH_FILE_FORMAT_MINOR 3 /** The version of HDF5 that was used to compile splash */ #define SPLASH_HDF5_VERSION "${HDF5_VERSION}" From d9658e2c5f36237770afe83261e52aa5782970e0 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Tue, 6 Oct 2015 15:02:23 +0200 Subject: [PATCH 40/47] Fix Public Wshadow Warnings This commit fixes warnings in public header files caused by libSplash in external projects (as in PIConGPU) when compiled with `-Wshadow`. Since the affected classes are used as structs (purely public members) refining those in a `member_m` naming scheme would be more intrusive then changing the naming in their contructors. Generally it is pretty annoying that `-Wshadow` also calls out contructors but keeping those clean allows to find more serious bugs with it. Related to #190 but does not yet fix the Splash compile itself (non-public headers and implementations). --- src/include/splash/Selection.hpp | 58 +++++++++++------------ src/include/splash/domains/Domain.hpp | 20 ++++---- src/include/splash/domains/DomainData.hpp | 30 ++++++------ 3 files changed, 52 insertions(+), 56 deletions(-) diff --git a/src/include/splash/Selection.hpp b/src/include/splash/Selection.hpp index 83b6e83..d23160a 100644 --- a/src/include/splash/Selection.hpp +++ b/src/include/splash/Selection.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2014 Felix Schmitt + * Copyright 2014-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -39,12 +40,12 @@ namespace splash /** * Constructor - * - * @param size size of src buffer (select complete buffer) + * + * @param size_ size of src buffer (select complete buffer) */ - Selection(Dimensions size) : - size(size), - count(size), + Selection(Dimensions size_) : + size(size_), + count(size_), offset(0, 0, 0), stride(1, 1, 1) { @@ -52,16 +53,16 @@ namespace splash } /** - * Constructor - * - * @param size size of src buffer - * @param count size of selection within src buffer - * @param offset offset of selection within src buffer + * Constructor + * + * @param size_ size of src buffer + * @param count_ size of selection within src buffer + * @param offset_ offset of selection within src buffer */ - Selection(Dimensions size, Dimensions count, Dimensions offset) : - size(size), - count(count), - offset(offset), + Selection(Dimensions size_, Dimensions count_, Dimensions offset_) : + size(size_), + count(count_), + offset(offset_), stride(1, 1, 1) { @@ -69,24 +70,24 @@ namespace splash /** * Constructor - * - * @param size size of src buffer - * @param count size of selection within src buffer - * @param offset offset of selection within src buffer - * @param stride stride of selection within src buffer + * + * @param size_ size of src buffer + * @param count_ size of selection within src buffer + * @param offset_ offset of selection within src buffer + * @param stride_ stride of selection within src buffer */ - Selection(Dimensions size, Dimensions count, Dimensions offset, Dimensions stride) : - size(size), - count(count), - offset(offset), - stride(stride) + Selection(Dimensions size_, Dimensions count_, Dimensions offset_, Dimensions stride_) : + size(size_), + count(count_), + offset(offset_), + stride(stride_) { } - + /** * Swap dimensions - * + * * @param ndims number of dimensions of this selection */ void swapDims(uint32_t ndims) @@ -96,7 +97,7 @@ namespace splash offset.swapDims(ndims); stride.swapDims(ndims); } - + /** * Create a string representation of this selection * @@ -122,4 +123,3 @@ namespace splash } #endif /* SELECTION_HPP */ - diff --git a/src/include/splash/domains/Domain.hpp b/src/include/splash/domains/Domain.hpp index 28e1e14..400ddaf 100644 --- a/src/include/splash/domains/Domain.hpp +++ b/src/include/splash/domains/Domain.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013-2014 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -7,7 +7,8 @@ * it under the terms of of either the GNU General Public License or * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -19,8 +20,6 @@ * If not, see . */ - - #ifndef DOMAIN_HPP #define DOMAIN_HPP @@ -53,13 +52,13 @@ namespace splash /** * Constructor. - * - * @param offset Offset of this domain in the parent domain. - * @param size Size of this domain in every dimension. + * + * @param offset_ Offset of this domain in the parent domain. + * @param size_ Size of this domain in every dimension. */ - Domain(Dimensions offset, Dimensions size) : - offset(offset), - size(size) + Domain(Dimensions offset_, Dimensions size_) : + offset(offset_), + size(size_) { } @@ -177,4 +176,3 @@ namespace splash } #endif /* DOMAIN_HPP */ - diff --git a/src/include/splash/domains/DomainData.hpp b/src/include/splash/domains/DomainData.hpp index d1f35b7..f8139e9 100644 --- a/src/include/splash/domains/DomainData.hpp +++ b/src/include/splash/domains/DomainData.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013-2014 Felix Schmitt + * Copyright 2013-2015 Felix Schmitt, Axel Huebl * * This file is part of libSplash. * @@ -7,7 +7,8 @@ * it under the terms of of either the GNU General Public License or * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -19,8 +20,6 @@ * If not, see . */ - - #ifndef DOMAINDATA_HPP #define DOMAINDATA_HPP @@ -61,20 +60,20 @@ namespace splash /** * Constructor. * Allocates enough memory to hold 'elements' data of 'type'. - * - * @param domain The underlying Domain. - * @param elements Number of data elements in every dimension. - * @param datatypeSize Size of each element in bytes. - * @param datatype Internal representation of HDF5 datatype. + * + * @param domain_ The underlying Domain. + * @param elements_ Number of data elements in every dimension. + * @param datatypeSize_ Size of each element in bytes. + * @param datatype_ Internal representation of HDF5 datatype. */ - DomainData(const Domain& domain, const Dimensions elements, - size_t datatypeSize, DCDataType datatype) : - Domain(domain), - elements(elements), + DomainData(const Domain& domain_, const Dimensions elements_, + size_t datatypeSize_, DCDataType datatype_) : + Domain(domain_), + elements(elements_), data(NULL), loadingReference(NULL), - datatype(datatype), - datatypeSize(datatypeSize) + datatype(datatype_), + datatypeSize(datatypeSize_) { data = new uint8_t[datatypeSize * elements.getScalarSize()]; assert(data != NULL); @@ -232,4 +231,3 @@ namespace splash } #endif /* DOMAINDATA_HPP */ - From ce3e9bb6b5729fd29de00e2c083a4f5f64dd003c Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Tue, 6 Oct 2015 13:01:59 +0200 Subject: [PATCH 41/47] Close #184 Compression Header as Bool Close #184 by using the new `h5py` compatible bool type for our `/header/compression` attribute. Increases the format by a minor (since last release already a major increase, purely informative argument that has no influence on transparent reads of compressed or uncompressed data sets) --- src/ParallelDataCollector.cpp | 9 +++++---- src/SDCHelper.cpp | 9 +++++---- src/SerialDataCollector.cpp | 5 ++++- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/ParallelDataCollector.cpp b/src/ParallelDataCollector.cpp index 63f85ea..3019d48 100644 --- a/src/ParallelDataCollector.cpp +++ b/src/ParallelDataCollector.cpp @@ -29,8 +29,7 @@ #include "splash/version.hpp" #include "splash/ParallelDataCollector.hpp" -#include "splash/basetypes/ColTypeDim.hpp" -#include "splash/basetypes/ColTypeString.hpp" +#include "splash/basetypes/basetypes.hpp" #include "splash/core/DCParallelDataSet.hpp" #include "splash/core/DCAttribute.hpp" #include "splash/core/DCParallelGroup.hpp" @@ -835,15 +834,17 @@ namespace splash splashFormat << SPLASH_FILE_FORMAT_MAJOR << "." << SPLASH_FILE_FORMAT_MINOR; + ColTypeInt32 ctInt32; + ColTypeBool ctBool; ColTypeDim dim_t; ColTypeString ctStringVersion(splashVersion.str().length()); ColTypeString ctStringFormat(splashFormat.str().length()); // create master specific header attributes - DCAttribute::writeAttribute(SDC_ATTR_MAX_ID, H5T_NATIVE_INT32, + DCAttribute::writeAttribute(SDC_ATTR_MAX_ID, ctInt32.getDataType(), group.getHandle(), &index); - DCAttribute::writeAttribute(SDC_ATTR_COMPRESSION, H5T_NATIVE_HBOOL, + DCAttribute::writeAttribute(SDC_ATTR_COMPRESSION, ctBool.getDataType(), group.getHandle(), &compression); DCAttribute::writeAttribute(SDC_ATTR_MPI_SIZE, dim_t.getDataType(), diff --git a/src/SDCHelper.cpp b/src/SDCHelper.cpp index c979c61..3fcf207 100644 --- a/src/SDCHelper.cpp +++ b/src/SDCHelper.cpp @@ -23,8 +23,7 @@ #include "splash/core/SDCHelper.hpp" #include "splash/version.hpp" -#include "splash/basetypes/ColTypeDim.hpp" -#include "splash/basetypes/ColTypeString.hpp" +#include "splash/basetypes/basetypes.hpp" #include "splash/core/DCAttribute.hpp" #include "splash/core/logging.hpp" @@ -102,20 +101,22 @@ namespace splash splashFormat << SPLASH_FILE_FORMAT_MAJOR << "." << SPLASH_FILE_FORMAT_MINOR; + ColTypeInt32 ctInt32; + ColTypeBool ctBool; ColTypeDim dim_t; ColTypeString ctStringVersion(splashVersion.str().length()); ColTypeString ctStringFormat(splashFormat.str().length()); // create master specific header attributes if (master) { - DCAttribute::writeAttribute(SDC_ATTR_MAX_ID, H5T_NATIVE_INT32, + DCAttribute::writeAttribute(SDC_ATTR_MAX_ID, ctInt32.getDataType(), group_header, maxID); } else { DCAttribute::writeAttribute(SDC_ATTR_MPI_POSITION, dim_t.getDataType(), group_header, mpiPosition.getPointer()); } - DCAttribute::writeAttribute(SDC_ATTR_COMPRESSION, H5T_NATIVE_HBOOL, + DCAttribute::writeAttribute(SDC_ATTR_COMPRESSION, ctBool.getDataType(), group_header, enableCompression); DCAttribute::writeAttribute(SDC_ATTR_MPI_SIZE, dim_t.getDataType(), diff --git a/src/SerialDataCollector.cpp b/src/SerialDataCollector.cpp index c8b6a77..87c52c8 100644 --- a/src/SerialDataCollector.cpp +++ b/src/SerialDataCollector.cpp @@ -29,6 +29,8 @@ #include "splash/SerialDataCollector.hpp" +#include "splash/basetypes/basetypes.hpp" + #include "splash/core/DCAttribute.hpp" #include "splash/core/DCDataSet.hpp" #include "splash/core/DCGroup.hpp" @@ -163,7 +165,8 @@ namespace splash // write number of iterations try { - DCAttribute::writeAttribute(SDC_ATTR_MAX_ID, H5T_NATIVE_INT32, + ColTypeInt32 ctInt32; + DCAttribute::writeAttribute(SDC_ATTR_MAX_ID, ctInt32.getDataType(), group.getHandle(), &maxID); } catch (DCException e) { From 2da14a60f2244881829d95987ac6f90cfd34a33b Mon Sep 17 00:00:00 2001 From: Carlchristian Eckert Date: Mon, 12 Oct 2015 18:05:05 +0200 Subject: [PATCH 42/47] implemented type arbitration --- src/DCGroup.cpp | 11 +- src/ParallelDataCollector.cpp | 55 +++++++++ src/SerialDataCollector.cpp | 26 ++-- src/include/splash/CollectionType.hpp | 9 ++ src/include/splash/DataCollector.hpp | 3 + src/include/splash/ParallelDataCollector.hpp | 16 ++- src/include/splash/SerialDataCollector.hpp | 12 +- src/include/splash/basetypes/ColTypeBool.hpp | 33 +++++- src/include/splash/basetypes/ColTypeDim.hpp | 34 ++++++ .../splash/basetypes/ColTypeDimArray.hpp | 32 +++++ .../splash/basetypes/ColTypeString.hpp | 30 ++++- .../splash/basetypes/ColTypeUnknown.hpp | 46 +++++++ .../basetypes/CollectionTypeGenerator.hpp | 112 ++++++++++++++++++ src/include/splash/basetypes/basetypes.hpp | 2 + .../splash/basetypes/basetypes_array.hpp | 31 +++++ .../splash/basetypes/basetypes_atomic.hpp | 30 ++++- .../splash/basetypes/basetypes_compound.hpp | 39 +++++- tools/splashtools.cpp | 5 +- 18 files changed, 502 insertions(+), 24 deletions(-) create mode 100644 src/include/splash/basetypes/ColTypeUnknown.hpp create mode 100644 src/include/splash/basetypes/CollectionTypeGenerator.hpp diff --git a/src/DCGroup.cpp b/src/DCGroup.cpp index dd9f6e4..2fec357 100644 --- a/src/DCGroup.cpp +++ b/src/DCGroup.cpp @@ -1,5 +1,6 @@ /** * Copyright 2013 Felix Schmitt + * 2015 Carlchristian Eckert * * This file is part of libSplash. * @@ -25,8 +26,11 @@ #include #include #include +#include #include "splash/core/DCGroup.hpp" +#include "splash/basetypes/basetypes.hpp" +#include #define H5_TRUE 1 #define H5_FALSE 0 @@ -198,7 +202,12 @@ namespace splash if (param->entries) { param->entries[param->count].name = currentBaseName; - // type ... + + hid_t dataset_id = H5Oopen_by_idx(base, ".", H5_INDEX_NAME, H5_ITER_INC, i, H5P_DEFAULT); + hid_t datatype_id = H5Dget_type(dataset_id); + param->entries[param->count].col_type = CollectionTypeGenerator::genCollectionType(datatype_id); + H5Dclose(datatype_id); + H5Oclose(dataset_id); } param->count++; diff --git a/src/ParallelDataCollector.cpp b/src/ParallelDataCollector.cpp index 63f85ea..b9b1b6f 100644 --- a/src/ParallelDataCollector.cpp +++ b/src/ParallelDataCollector.cpp @@ -559,6 +559,22 @@ namespace splash localSize, globalOffset, sizeRead, ndims, buf); } + CollectionType* ParallelDataCollector::readMeta(int32_t id, + const char* name, + const Dimensions dstBuffer, + const Dimensions dstOffset, + Dimensions& sizeRead) throw (DCException) + { + // TODO: Check what this line does (FST_MERGING is not defined!) +// if (fileStatus != FST_READING && fileStatus != FST_WRITING && fileStatus != FST_MERGING) +// throw DCException(getExceptionString("read", "this access is not permitted")); + + std::cout << "here 1" << std::endl; + uint32_t ndims = 0; + return readDataSetMeta(handles.get(0), id, name, dstBuffer, dstOffset, + Dimensions(0, 0, 0), sizeRead, ndims); + } + void ParallelDataCollector::write(int32_t id, const CollectionType& type, uint32_t ndims, const Selection select, const char* name, const void* buf) throw (DCException) @@ -956,6 +972,45 @@ namespace splash dataset.close(); } + CollectionType* ParallelDataCollector::readDataSetMeta(H5Handle h5File, + int32_t id, + const char* name, + const Dimensions dstBuffer, + const Dimensions dstOffset, + const Dimensions srcOffset, + Dimensions &sizeRead, + uint32_t& srcDims) + throw (DCException) + { + log_msg(2, "readDataSetMeta"); + + std::string group_path, dset_name; + DCDataSet::getFullDataPath(name, SDC_GROUP_DATA, id, group_path, dset_name); + + DCGroup group; + group.open(h5File, group_path); + + DCDataSet dataset(dset_name.c_str()); + dataset.open(group.getHandle()); + + //size_t datatype_size = 0; + //DCDataType dc_datatype = DCDT_UNKNOWN; + //datatype_size = dataset.getDataTypeSize(); + //dc_datatype = dataset.getDCDataType(); + + size_t entrySize; + getEntriesForID(id, NULL, &entrySize); + std::vector entries(entrySize); + + getEntriesForID(id, &(*entries.begin()), NULL); + + Dimensions src_size(dataset.getSize() - srcOffset); + dataset.read(dstBuffer, dstOffset, src_size, srcOffset, sizeRead, srcDims, NULL); + dataset.close(); + + return entries[0].col_type; + } + void ParallelDataCollector::writeDataSet(H5Handle group, const Dimensions globalSize, const Dimensions globalOffset, diff --git a/src/SerialDataCollector.cpp b/src/SerialDataCollector.cpp index cae2664..465fd21 100644 --- a/src/SerialDataCollector.cpp +++ b/src/SerialDataCollector.cpp @@ -35,6 +35,7 @@ #include "splash/core/DCHelper.hpp" #include "splash/core/SDCHelper.hpp" #include "splash/core/logging.hpp" +#include "splash/basetypes/basetypes.hpp" namespace splash { @@ -425,8 +426,7 @@ namespace splash Dimensions(0, 0, 0), sizeRead, ndims, data); } - void SerialDataCollector::readMeta(int32_t id, - CollectionType &type, + CollectionType* SerialDataCollector::readMeta(int32_t id, const char* name, const Dimensions dstBuffer, const Dimensions dstOffset, @@ -437,7 +437,7 @@ namespace splash throw DCException(getExceptionString("read", "this access is not permitted")); uint32_t ndims = 0; - readDataSetMeta(handles.get(0), id, type, name, dstBuffer, dstOffset, + return readDataSetMeta(handles.get(0), id, name, dstBuffer, dstOffset, Dimensions(0, 0, 0), sizeRead, ndims); } @@ -973,9 +973,8 @@ namespace splash dataset.close(); } - void SerialDataCollector::readDataSetMeta(H5Handle h5File, + CollectionType* SerialDataCollector::readDataSetMeta(H5Handle h5File, int32_t id, - CollectionType &type, const char* name, const Dimensions dstBuffer, const Dimensions dstOffset, @@ -995,17 +994,22 @@ namespace splash DCDataSet dataset(dset_name.c_str()); dataset.open(group.getHandle()); - size_t datatype_size = 0; - DCDataType dc_datatype = DCDT_UNKNOWN; - datatype_size = dataset.getDataTypeSize(); - dc_datatype = dataset.getDCDataType(); + //size_t datatype_size = 0; + //DCDataType dc_datatype = DCDT_UNKNOWN; + //datatype_size = dataset.getDataTypeSize(); + //dc_datatype = dataset.getDCDataType(); - // make a collection for "type" out of it... - //type.getDataType() = ... + size_t entrySize; + getEntriesForID(id, NULL, &entrySize); + std::vector entries(entrySize); + + getEntriesForID(id, &(*entries.begin()), NULL); Dimensions src_size(dataset.getSize() - srcOffset); dataset.read(dstBuffer, dstOffset, src_size, srcOffset, sizeRead, srcDims, NULL); dataset.close(); + + return entries[0].col_type; } void SerialDataCollector::readSizeInternal(H5Handle h5File, diff --git a/src/include/splash/CollectionType.hpp b/src/include/splash/CollectionType.hpp index b1fb272..30f39b1 100644 --- a/src/include/splash/CollectionType.hpp +++ b/src/include/splash/CollectionType.hpp @@ -1,5 +1,6 @@ /** * Copyright 2013 Felix Schmitt + * 2015 Carlchristian Eckert * * This file is part of libSplash. * @@ -25,6 +26,7 @@ #define COLLECTIONTYPE_H #include +#include #define H5DataType hid_t @@ -55,6 +57,13 @@ namespace splash */ virtual size_t getSize() const = 0; + /** + * Returns a human-readable representation of the datatype. + * + * @return the name of the datatype as a string + */ + virtual std::string toString() const = 0; + /** * Destructor */ diff --git a/src/include/splash/DataCollector.hpp b/src/include/splash/DataCollector.hpp index 1b80216..ee94847 100644 --- a/src/include/splash/DataCollector.hpp +++ b/src/include/splash/DataCollector.hpp @@ -52,6 +52,7 @@ #include "splash/CollectionType.hpp" #include "splash/Dimensions.hpp" #include "splash/Selection.hpp" +#include "splash/core/DCDataSet.hpp" namespace splash { @@ -113,6 +114,8 @@ namespace splash * Fully-qualified name of this dataset. */ std::string name; + DCDataType dc_type; + CollectionType* col_type; } DCEntry; /** diff --git a/src/include/splash/ParallelDataCollector.hpp b/src/include/splash/ParallelDataCollector.hpp index 51c108e..581c7ab 100644 --- a/src/include/splash/ParallelDataCollector.hpp +++ b/src/include/splash/ParallelDataCollector.hpp @@ -312,12 +312,11 @@ namespace splash Dimensions &sizeRead, void* buf) throw (DCException); -/* void readMeta(int32_t id, - CollectionType &type, + CollectionType* readMeta(int32_t id, const char* name, const Dimensions dstBuffer, const Dimensions dstOffset, - Dimensions &sizeRead) throw (DCException);*/ + Dimensions &sizeRead) throw (DCException); /** * Reads data from HDF5 file. @@ -415,6 +414,17 @@ namespace splash Dimensions /*count*/, Dimensions /*offset*/, Dimensions /*stride*/) throw (DCException); + + + CollectionType* readDataSetMeta(H5Handle h5File, + int32_t id, + const char* name, + const Dimensions dstBuffer, + const Dimensions dstOffset, + const Dimensions srcOffset, + Dimensions &sizeRead, + uint32_t& srcDims) + throw (DCException); }; } diff --git a/src/include/splash/SerialDataCollector.hpp b/src/include/splash/SerialDataCollector.hpp index 8988f50..8d77935 100644 --- a/src/include/splash/SerialDataCollector.hpp +++ b/src/include/splash/SerialDataCollector.hpp @@ -186,6 +186,15 @@ namespace splash uint32_t& srcDims, void* dst) throw (DCException); + CollectionType* readDataSetMeta(H5Handle h5File, + int32_t id, + const char* name, + const Dimensions dstBuffer, + const Dimensions dstOffset, + const Dimensions srcOffset, + Dimensions &sizeRead, + uint32_t& srcDims) throw (DCException); + void readSizeInternal(H5Handle h5File, int32_t id, const char* name, @@ -333,8 +342,7 @@ namespace splash Dimensions &sizeRead, void* data) throw (DCException); - void readMeta(int32_t id, - CollectionType &type, + CollectionType* readMeta(int32_t id, const char* name, const Dimensions dstBuffer, const Dimensions dstOffset, diff --git a/src/include/splash/basetypes/ColTypeBool.hpp b/src/include/splash/basetypes/ColTypeBool.hpp index 8fc49ac..a538824 100644 --- a/src/include/splash/basetypes/ColTypeBool.hpp +++ b/src/include/splash/basetypes/ColTypeBool.hpp @@ -1,5 +1,6 @@ /** - * Copyright 2013, 2015 Felix Schmitt, René Widera, Axel Huebl + * Copyright 2013, 2015 Felix Schmitt, René Widera, Axel Huebl, + * Carlchristian Eckert * * This file is part of libSplash. * @@ -25,6 +26,10 @@ #define COLTYPEBOOL_H #include "splash/CollectionType.hpp" +#include "splash/basetypes/ColTypeUnknown.hpp" + +#include +#include namespace splash { @@ -55,6 +60,32 @@ class ColTypeBool : public CollectionType { return sizeof (bool); } + + static CollectionType* genType(hid_t datatype_id) + { + bool found = false; + H5T_class_t h5_class = H5Tget_class(datatype_id); + if(h5_class == H5T_ENUM){ + if(H5Tget_nmembers(datatype_id) == 2){ + char* m0 = H5Tget_member_name(datatype_id,0); + char* m1 = H5Tget_member_name(datatype_id,1); + if(strcmp("true" , m0) == 0 && strcmp("false", m1) == 0) + found = true; + free(m1); + free(m0); + } + } + + if(found) + return new ColTypeBool; + else + return NULL; + } + + std::string toString() const + { + return "Bool"; + } }; } diff --git a/src/include/splash/basetypes/ColTypeDim.hpp b/src/include/splash/basetypes/ColTypeDim.hpp index 3ad9fb6..a482b50 100644 --- a/src/include/splash/basetypes/ColTypeDim.hpp +++ b/src/include/splash/basetypes/ColTypeDim.hpp @@ -1,5 +1,6 @@ /** * Copyright 2013 Felix Schmitt + * 2015 Carlchristian Eckert * * This file is part of libSplash. * @@ -27,6 +28,10 @@ #include "splash/CollectionType.hpp" #include "splash/Dimensions.hpp" +#include +#include +#include + namespace splash { @@ -51,6 +56,35 @@ namespace splash { return Dimensions::getSize(); } + + std::string toString() const + { + return "Dimension"; + } + + static CollectionType* genType(hid_t datatype_id) + { + bool found = false; + H5T_class_t h5_class = H5Tget_class(datatype_id); + if(h5_class == H5T_COMPOUND){ + if(H5Tget_nmembers(datatype_id) == 3){ + if(H5Tget_size(datatype_id) == Dimensions::getSize()){ + char* m0 = H5Tget_member_name(datatype_id, 0); + char* m1 = H5Tget_member_name(datatype_id, 1); + char* m2 = H5Tget_member_name(datatype_id, 2); + if( (strcmp("x", m0) || strcmp("y", m1) || strcmp("z", m2)) == 0) + found = true; + free(m2); + free(m1); + free(m0); + } + } + } + if(found) + return new ColTypeDim; + else + return NULL; + } }; } diff --git a/src/include/splash/basetypes/ColTypeDimArray.hpp b/src/include/splash/basetypes/ColTypeDimArray.hpp index 303352e..21d51fe 100644 --- a/src/include/splash/basetypes/ColTypeDimArray.hpp +++ b/src/include/splash/basetypes/ColTypeDimArray.hpp @@ -1,5 +1,6 @@ /** * Copyright 2013 Felix Schmitt + * 2015 Carlchristian Eckert * * This file is part of libSplash. * @@ -26,6 +27,8 @@ #include "splash/CollectionType.hpp" +#include + namespace splash { class ColTypeDimArray : public CollectionType @@ -47,6 +50,35 @@ namespace splash { return sizeof (hsize_t) * 3; } + + static CollectionType* genType(hid_t datatype_id) + { + bool found = false; + H5T_class_t h5_class = H5Tget_class(datatype_id); + if(h5_class == H5T_ARRAY) + { + hid_t base = H5Tget_super(datatype_id); + if(H5Tequal(base, H5T_NATIVE_HSIZE) == 1){ + if(H5Tget_array_ndims(datatype_id) == 1) + { + hsize_t adims_out[1]; + H5Tget_array_dims(datatype_id, adims_out); + if(adims_out[0] == 3) + found = true; + } + } + H5Tclose(base); + } + if(found) + return new ColTypeDimArray; + else + return NULL; + } + + std::string toString() const + { + return "DimArray"; + } }; } diff --git a/src/include/splash/basetypes/ColTypeString.hpp b/src/include/splash/basetypes/ColTypeString.hpp index 6084fc1..b2b224c 100644 --- a/src/include/splash/basetypes/ColTypeString.hpp +++ b/src/include/splash/basetypes/ColTypeString.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013-2015 Felix Schmitt, Axel Huebl + * Copyright 2013-2015 Felix Schmitt, Axel Huebl, Carlchristian Eckert * * This file is part of libSplash. * @@ -23,6 +23,9 @@ #define COLTYPESTRING_H #include "splash/CollectionType.hpp" +#include "splash/basetypes/ColTypeUnknown.hpp" + +#include namespace splash { @@ -70,6 +73,31 @@ namespace splash else return sizeof(char) * (myElements - 1); /* just as strlen() */ } + + static CollectionType* genType(hid_t datatype_id) + { + H5T_class_t h5_class = H5Tget_class(datatype_id); + + if(h5_class == H5T_STRING){ + if( H5Tis_variable_str(datatype_id) ){ + return new ColTypeString; + }else{ + size_t size = H5Tget_size(datatype_id); + return new ColTypeString(size); + } + }else{ + return NULL; + } + } + + std::string toString() const + { + if( H5Tis_variable_str(this->type) ) + return "VLString"; + else + return "String"; + } + }; } diff --git a/src/include/splash/basetypes/ColTypeUnknown.hpp b/src/include/splash/basetypes/ColTypeUnknown.hpp new file mode 100644 index 0000000..4cffdcb --- /dev/null +++ b/src/include/splash/basetypes/ColTypeUnknown.hpp @@ -0,0 +1,46 @@ +/** + * Copyright 2015 Carlchristian Eckert + * + * This file is part of libSplash. + * + * libSplash is free software: you can redistribute it and/or modify + * it under the terms of of either the GNU General Public License or + * the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * libSplash is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser General Public License along with libSplash. + * If not, see . + */ + +#ifndef COLTYPEUNKNOWN_H +#define COLTYPEUNKNOWN_H + +#include "splash/CollectionType.hpp" +#include + +namespace splash +{ + class ColTypeUnknown : public CollectionType + { + public: + + size_t getSize() const + { + return 0; + } + + std::string toString() const + { + return "UNKNOWN"; + } + }; +} + +#endif /* COLTYPEUNKNOWN_H */ diff --git a/src/include/splash/basetypes/CollectionTypeGenerator.hpp b/src/include/splash/basetypes/CollectionTypeGenerator.hpp new file mode 100644 index 0000000..68e212c --- /dev/null +++ b/src/include/splash/basetypes/CollectionTypeGenerator.hpp @@ -0,0 +1,112 @@ +/** + * Copyright 2015 Carlchristian Eckert + * + * This file is part of libSplash. + * + * libSplash is free software: you can redistribute it and/or modify + * it under the terms of of either the GNU General Public License or + * the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * libSplash is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser General Public License along with libSplash. + * If not, see . + */ + +#ifndef COLTYPEGENERATOR_H +#define COLTYPEGENERATOR_H + + +#include "splash/basetypes/basetypes.hpp" +#include "splash/CollectionType.hpp" + +namespace splash +{ + +#define COLLECTION_TEST(_name) \ +{ \ + CollectionType* t = ColType##_name::genType(datatype_id); \ + if(t != NULL && typeid(*t) == typeid(ColType##_name)) return t; \ +} \ + + +class CollectionTypeGenerator{ +public: + + static CollectionType* genCollectionType(hid_t datatype_id) + { + // basetypes atomic + COLLECTION_TEST(Int8) + COLLECTION_TEST(Int16) + COLLECTION_TEST(Int32) + COLLECTION_TEST(Int64) + + COLLECTION_TEST(UInt8) + COLLECTION_TEST(UInt16) + COLLECTION_TEST(UInt32) + COLLECTION_TEST(UInt64) + + COLLECTION_TEST(Float) + COLLECTION_TEST(Double) + COLLECTION_TEST(Char) + COLLECTION_TEST(Int) + + + // ColType Bool -> must be before the other enum types! + COLLECTION_TEST(Bool) + + + // ColType String + COLLECTION_TEST(String) + + + // ColTypeArray() + COLLECTION_TEST(Float2Array) + COLLECTION_TEST(Float3Array) + COLLECTION_TEST(Float4Array) + + COLLECTION_TEST(Double2Array) + COLLECTION_TEST(Double3Array) + COLLECTION_TEST(Double4Array) + + COLLECTION_TEST(Int4Array) + COLLECTION_TEST(Int3Array) + COLLECTION_TEST(Int2Array) + + + // ColTypeDimArray + COLLECTION_TEST(DimArray) + + + // ColType Dim + COLLECTION_TEST(Dim) + + + // Coltype Compound + COLLECTION_TEST(Float2) + COLLECTION_TEST(Float3) + COLLECTION_TEST(Float4) + + COLLECTION_TEST(Double2) + COLLECTION_TEST(Double3) + COLLECTION_TEST(Double4) + + COLLECTION_TEST(Int2) + COLLECTION_TEST(Int3) + COLLECTION_TEST(Int4) + + return new ColTypeUnknown; + } + +}; + +} + + +#endif /* COLTYPEGENERATOR_H */ diff --git a/src/include/splash/basetypes/basetypes.hpp b/src/include/splash/basetypes/basetypes.hpp index 16d6b72..bdf2682 100644 --- a/src/include/splash/basetypes/basetypes.hpp +++ b/src/include/splash/basetypes/basetypes.hpp @@ -31,5 +31,7 @@ #include "splash/basetypes/ColTypeDimArray.hpp" #include "splash/basetypes/ColTypeString.hpp" +#include "splash/basetypes/ColTypeUnknown.hpp" + #endif /* BASETYPES_HPP */ diff --git a/src/include/splash/basetypes/basetypes_array.hpp b/src/include/splash/basetypes/basetypes_array.hpp index b80a82a..8d5142f 100644 --- a/src/include/splash/basetypes/basetypes_array.hpp +++ b/src/include/splash/basetypes/basetypes_array.hpp @@ -1,5 +1,6 @@ /** * Copyright 2013 Felix Schmitt + * 2015 Carlchristian Eckert * * This file is part of libSplash. * @@ -23,6 +24,7 @@ #define BASETYPES_ARRAY_HPP #include +#include #include "splash/CollectionType.hpp" @@ -45,6 +47,35 @@ namespace splash \ size_t getSize() const \ { return sizeof (_real_type) * _size; } \ + \ + static CollectionType* genType(hid_t datatype_id){ \ + bool found = false; \ + H5T_class_t h5_class = H5Tget_class(datatype_id); \ + if(h5_class == H5T_ARRAY) \ + { \ + hid_t base = H5Tget_super(datatype_id); \ + if(H5Tequal(base, _h5_type) == 1) \ + { \ + if(H5Tget_array_ndims(datatype_id) == 1) \ + { \ + hsize_t adims_out[1]; \ + H5Tget_array_dims(datatype_id, adims_out); \ + if(adims_out[0] == _size) \ + found = true; \ + } \ + } \ + H5Tclose(base); \ + } \ + if(found) \ + return new ColType##_name##Array; \ + else \ + return NULL; \ + } \ + \ + std::string toString() const \ + { \ + return #_name"Array"; \ + } \ }; TYPE_ARRAY(Float2, H5T_NATIVE_FLOAT, float, 2); diff --git a/src/include/splash/basetypes/basetypes_atomic.hpp b/src/include/splash/basetypes/basetypes_atomic.hpp index a3f173f..6054421 100644 --- a/src/include/splash/basetypes/basetypes_atomic.hpp +++ b/src/include/splash/basetypes/basetypes_atomic.hpp @@ -1,5 +1,5 @@ /** - * Copyright 2013-2015 Felix Schmitt, Axel Huebl + * Copyright 2013-2015 Felix Schmitt, Axel Huebl, Carlchristian Eckert * * This file is part of libSplash. * @@ -23,8 +23,11 @@ #define BASETYPES_ATOMIC_HPP #include +#include +#include #include "splash/CollectionType.hpp" +#include "splash/basetypes/ColTypeUnknown.hpp" namespace splash { @@ -39,7 +42,30 @@ namespace splash \ size_t getSize() const \ { return sizeof (_real_type); } \ - }; + \ + static CollectionType* genType(hid_t datatype_id){ \ + bool found = false; \ + H5T_class_t h5_class = H5Tget_class(datatype_id); \ + if(h5_class == H5T_INTEGER || h5_class == H5T_FLOAT) \ + { \ + hid_t native = H5Tget_native_type(datatype_id,H5T_DIR_DEFAULT);\ + if(H5Tequal(native, _h5_type) == 1) \ + found = true; \ + H5Tclose(native); \ + } \ + if(found) \ + return new ColType##_name; \ + else \ + return NULL; \ + } \ + \ + std::string toString() const \ + { \ + return #_name; \ + } \ + \ + }; \ + TYPE_ATOMIC(Float, H5T_NATIVE_FLOAT, float); TYPE_ATOMIC(Double, H5T_NATIVE_DOUBLE, double); diff --git a/src/include/splash/basetypes/basetypes_compound.hpp b/src/include/splash/basetypes/basetypes_compound.hpp index d90cd30..1a4854f 100644 --- a/src/include/splash/basetypes/basetypes_compound.hpp +++ b/src/include/splash/basetypes/basetypes_compound.hpp @@ -1,5 +1,6 @@ /** * Copyright 2013 Felix Schmitt + * 2015 Carlchristian Eckert * * This file is part of libSplash. * @@ -23,6 +24,8 @@ #define BASETYPES_COMPOUND_HPP #include +#include +#include #include "splash/CollectionType.hpp" @@ -50,7 +53,41 @@ namespace splash \ size_t getSize() const \ { return _size * sizeof (_real_type); } \ - }; + \ + static CollectionType* genType(hid_t datatype_id){ \ + H5T_class_t h5_class = H5Tget_class(datatype_id); \ + bool found = false; \ + if(h5_class == H5T_COMPOUND) \ + { \ + int nmembers = H5Tget_nmembers(datatype_id); \ + if(nmembers == _size) \ + { \ + for(int i = 0; i < nmembers && !found ; ++i){ \ + hid_t mtype = H5Tget_member_type(datatype_id, i); \ + char* mname = H5Tget_member_name(datatype_id, i); \ + if(H5Tequal(mtype, _h5_type) == 1 && \ + strcmp(COMPOUND_ELEMENTS[i], mname) == 0) \ + { \ + found = true; \ + } \ + free(mname); \ + H5Tclose(mtype); \ + } \ + } \ + } \ + if(found) \ + return new ColType##_name; \ + else \ + return NULL; \ + } \ + \ + std::string toString() const \ + { \ + return #_name; \ + } \ + \ + }; \ + TYPE_COMPOUND(Float2, H5T_NATIVE_FLOAT, float, 2); TYPE_COMPOUND(Float3, H5T_NATIVE_FLOAT, float, 3); diff --git a/tools/splashtools.cpp b/tools/splashtools.cpp index ddef5db..b4daaee 100644 --- a/tools/splashtools.cpp +++ b/tools/splashtools.cpp @@ -500,13 +500,14 @@ int listAvailableDatasets(Options& options, DataCollector *dc, const char* /*fil for (size_t i = 0; i < num_entries; ++i) { - //DCDataType data_type = dc->getIndex(i)->getDataType(); + CollectionType* data_type = entries[i].col_type; Dimensions sizeRead; dc->read(id, entries[i].name.c_str(), sizeRead, NULL); std::cout << entries[i].name - //<< "(type: " << data_type << ")" + << " (" << data_type->toString() << ")" << " " << sizeRead.toString() << std::endl; + } delete[] entries; From 7a650451e11c9a3d68acdf751d3d9101b8f68abe Mon Sep 17 00:00:00 2001 From: Carlchristian Eckert Date: Mon, 9 Nov 2015 10:39:42 +0100 Subject: [PATCH 43/47] added check for open file handle --- src/ParallelDataCollector.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ParallelDataCollector.cpp b/src/ParallelDataCollector.cpp index b9b1b6f..b4a8fa1 100644 --- a/src/ParallelDataCollector.cpp +++ b/src/ParallelDataCollector.cpp @@ -565,11 +565,9 @@ namespace splash const Dimensions dstOffset, Dimensions& sizeRead) throw (DCException) { - // TODO: Check what this line does (FST_MERGING is not defined!) -// if (fileStatus != FST_READING && fileStatus != FST_WRITING && fileStatus != FST_MERGING) -// throw DCException(getExceptionString("read", "this access is not permitted")); + if (fileStatus != FST_READING && fileStatus != FST_WRITING) + throw DCException(getExceptionString("read", "this access is not permitted")); - std::cout << "here 1" << std::endl; uint32_t ndims = 0; return readDataSetMeta(handles.get(0), id, name, dstBuffer, dstOffset, Dimensions(0, 0, 0), sizeRead, ndims); From 927a20cffc6b1e598c925d8bda3ad3093f77931a Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Mon, 9 Nov 2015 15:05:03 +0100 Subject: [PATCH 44/47] Close #157 Iteration in Doxygen Use the term `iteration` instead of (time) `step` also in last doxygen strings that were missing. Removes also an unused define. --- src/include/splash/DataCollector.hpp | 17 ++++++++++------- src/include/splash/sdc_defines.hpp | 1 - 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/include/splash/DataCollector.hpp b/src/include/splash/DataCollector.hpp index 1b80216..c98f165 100644 --- a/src/include/splash/DataCollector.hpp +++ b/src/include/splash/DataCollector.hpp @@ -245,15 +245,18 @@ namespace splash const void *buf) = 0; /** - * Removes a simulation step from the HDF5 file. - * + * Removes a simulation iteration from the HDF5 file. + * + * Recursively removes all datasets and attributes within + * the iteration. + * * @param id ID to remove. */ virtual void remove(int32_t id) = 0; /** * Removes a dataset from a HDF5 file. - * + * * @param id ID holding the dataset to be removed. * @param name Name of the dataset to be removed. */ @@ -262,10 +265,10 @@ namespace splash /** * Creates an object reference to an existing dataset in the same HDF5 file. - * + * * @param srcID ID of the iteration holding the source dataset. * @param srcName Name of the existing source dataset. - * @param dstID ID of the simulation step holding the created reference dataset. + * @param dstID ID of the simulation iteration holding the created reference dataset. * If this group does not exist, it is created. * @param dstName Name of the created reference. */ @@ -276,10 +279,10 @@ namespace splash /** * Creates a dataset region reference to an existing dataset in the same HDF5 file. - * + * * @param srcID ID of the iteration holding the source dataset. * @param srcName Name of the existing source dataset. - * @param dstID ID of the simulation step holding the created reference dataset. + * @param dstID ID of the simulation iteration holding the created reference dataset. * If this group does not exist, it is created. * @param dstName Name of the created reference. * @param count Number of elements referenced from the source dataset. diff --git a/src/include/splash/sdc_defines.hpp b/src/include/splash/sdc_defines.hpp index 2d92748..85ff40e 100644 --- a/src/include/splash/sdc_defines.hpp +++ b/src/include/splash/sdc_defines.hpp @@ -34,7 +34,6 @@ namespace splash #define SDC_ATTR_DIM_LOCAL "dim_local" #define SDC_ATTR_DIM_GLOBAL "dim_global" #define SDC_ATTR_MAX_ID "max_id" -#define SDC_ATTR_ID_STEP "id_step" #define SDC_ATTR_MPI_POSITION "mpi_position" #define SDC_ATTR_MPI_SIZE "mpi_size" #define SDC_ATTR_GRID_SIZE "grid_size" From 68380fd1588671a5f8c680adf216dd331b5a2553 Mon Sep 17 00:00:00 2001 From: Carlchristian Eckert Date: Tue, 10 Nov 2015 10:25:22 +0100 Subject: [PATCH 45/47] internal changes --- src/DCGroup.cpp | 4 +- src/ParallelDataCollector.cpp | 2 +- src/SerialDataCollector.cpp | 2 +- src/include/splash/DataCollector.hpp | 6 +- src/include/splash/basetypes/ColTypeBool.hpp | 7 +- src/include/splash/basetypes/ColTypeDim.hpp | 14 +- .../splash/basetypes/ColTypeDimArray.hpp | 3 +- .../splash/basetypes/ColTypeString.hpp | 13 +- .../splash/basetypes/ColTypeUnknown.hpp | 2 +- .../basetypes/CollectionTypeGenerator.hpp | 112 --------------- .../splash/basetypes/basetypes_array.hpp | 3 +- .../splash/basetypes/basetypes_atomic.hpp | 4 +- .../splash/basetypes/basetypes_compound.hpp | 9 +- .../basetypes/generateCollectionType.hpp | 131 ++++++++++++++++++ tools/splashtools.cpp | 2 +- 15 files changed, 174 insertions(+), 140 deletions(-) delete mode 100644 src/include/splash/basetypes/CollectionTypeGenerator.hpp create mode 100644 src/include/splash/basetypes/generateCollectionType.hpp diff --git a/src/DCGroup.cpp b/src/DCGroup.cpp index 2fec357..1d99fa5 100644 --- a/src/DCGroup.cpp +++ b/src/DCGroup.cpp @@ -30,7 +30,7 @@ #include "splash/core/DCGroup.hpp" #include "splash/basetypes/basetypes.hpp" -#include +#include #define H5_TRUE 1 #define H5_FALSE 0 @@ -205,7 +205,7 @@ namespace splash hid_t dataset_id = H5Oopen_by_idx(base, ".", H5_INDEX_NAME, H5_ITER_INC, i, H5P_DEFAULT); hid_t datatype_id = H5Dget_type(dataset_id); - param->entries[param->count].col_type = CollectionTypeGenerator::genCollectionType(datatype_id); + param->entries[param->count].colType = generateCollectionType(datatype_id); H5Dclose(datatype_id); H5Oclose(dataset_id); } diff --git a/src/ParallelDataCollector.cpp b/src/ParallelDataCollector.cpp index b4a8fa1..259730b 100644 --- a/src/ParallelDataCollector.cpp +++ b/src/ParallelDataCollector.cpp @@ -1006,7 +1006,7 @@ namespace splash dataset.read(dstBuffer, dstOffset, src_size, srcOffset, sizeRead, srcDims, NULL); dataset.close(); - return entries[0].col_type; + return entries[0].colType; } void ParallelDataCollector::writeDataSet(H5Handle group, diff --git a/src/SerialDataCollector.cpp b/src/SerialDataCollector.cpp index 465fd21..79d25cd 100644 --- a/src/SerialDataCollector.cpp +++ b/src/SerialDataCollector.cpp @@ -1009,7 +1009,7 @@ namespace splash dataset.read(dstBuffer, dstOffset, src_size, srcOffset, sizeRead, srcDims, NULL); dataset.close(); - return entries[0].col_type; + return entries[0].colType; } void SerialDataCollector::readSizeInternal(H5Handle h5File, diff --git a/src/include/splash/DataCollector.hpp b/src/include/splash/DataCollector.hpp index ee94847..c5507ed 100644 --- a/src/include/splash/DataCollector.hpp +++ b/src/include/splash/DataCollector.hpp @@ -114,8 +114,10 @@ namespace splash * Fully-qualified name of this dataset. */ std::string name; - DCDataType dc_type; - CollectionType* col_type; + /** + * Pointer to an instance of the CollectionType of this dataset + */ + CollectionType* colType; } DCEntry; /** diff --git a/src/include/splash/basetypes/ColTypeBool.hpp b/src/include/splash/basetypes/ColTypeBool.hpp index a538824..91f8281 100644 --- a/src/include/splash/basetypes/ColTypeBool.hpp +++ b/src/include/splash/basetypes/ColTypeBool.hpp @@ -26,7 +26,6 @@ #define COLTYPEBOOL_H #include "splash/CollectionType.hpp" -#include "splash/basetypes/ColTypeUnknown.hpp" #include #include @@ -65,8 +64,10 @@ class ColTypeBool : public CollectionType { bool found = false; H5T_class_t h5_class = H5Tget_class(datatype_id); - if(h5_class == H5T_ENUM){ - if(H5Tget_nmembers(datatype_id) == 2){ + if(h5_class == H5T_ENUM) + { + if(H5Tget_nmembers(datatype_id) == 2) + { char* m0 = H5Tget_member_name(datatype_id,0); char* m1 = H5Tget_member_name(datatype_id,1); if(strcmp("true" , m0) == 0 && strcmp("false", m1) == 0) diff --git a/src/include/splash/basetypes/ColTypeDim.hpp b/src/include/splash/basetypes/ColTypeDim.hpp index a482b50..d704d18 100644 --- a/src/include/splash/basetypes/ColTypeDim.hpp +++ b/src/include/splash/basetypes/ColTypeDim.hpp @@ -59,21 +59,25 @@ namespace splash std::string toString() const { - return "Dimension"; + return "Dim"; } static CollectionType* genType(hid_t datatype_id) { bool found = false; H5T_class_t h5_class = H5Tget_class(datatype_id); - if(h5_class == H5T_COMPOUND){ - if(H5Tget_nmembers(datatype_id) == 3){ - if(H5Tget_size(datatype_id) == Dimensions::getSize()){ + if(h5_class == H5T_COMPOUND) + { + if(H5Tget_nmembers(datatype_id) == 3) + { + if(H5Tget_size(datatype_id) == Dimensions::getSize()) + { char* m0 = H5Tget_member_name(datatype_id, 0); char* m1 = H5Tget_member_name(datatype_id, 1); char* m2 = H5Tget_member_name(datatype_id, 2); - if( (strcmp("x", m0) || strcmp("y", m1) || strcmp("z", m2)) == 0) + if(strcmp("x", m0) == 0 && strcmp("y", m1) == 0 && strcmp("z", m2) == 0) found = true; + free(m2); free(m1); free(m0); diff --git a/src/include/splash/basetypes/ColTypeDimArray.hpp b/src/include/splash/basetypes/ColTypeDimArray.hpp index 21d51fe..b5e1fc4 100644 --- a/src/include/splash/basetypes/ColTypeDimArray.hpp +++ b/src/include/splash/basetypes/ColTypeDimArray.hpp @@ -58,7 +58,8 @@ namespace splash if(h5_class == H5T_ARRAY) { hid_t base = H5Tget_super(datatype_id); - if(H5Tequal(base, H5T_NATIVE_HSIZE) == 1){ + if(H5Tequal(base, H5T_NATIVE_HSIZE) == 1) + { if(H5Tget_array_ndims(datatype_id) == 1) { hsize_t adims_out[1]; diff --git a/src/include/splash/basetypes/ColTypeString.hpp b/src/include/splash/basetypes/ColTypeString.hpp index b2b224c..eb3dea2 100644 --- a/src/include/splash/basetypes/ColTypeString.hpp +++ b/src/include/splash/basetypes/ColTypeString.hpp @@ -23,7 +23,6 @@ #define COLTYPESTRING_H #include "splash/CollectionType.hpp" -#include "splash/basetypes/ColTypeUnknown.hpp" #include @@ -78,14 +77,18 @@ namespace splash { H5T_class_t h5_class = H5Tget_class(datatype_id); - if(h5_class == H5T_STRING){ - if( H5Tis_variable_str(datatype_id) ){ + if(h5_class == H5T_STRING) + { + if( H5Tis_variable_str(datatype_id) ) + { return new ColTypeString; - }else{ + } else + { size_t size = H5Tget_size(datatype_id); return new ColTypeString(size); } - }else{ + } else + { return NULL; } } diff --git a/src/include/splash/basetypes/ColTypeUnknown.hpp b/src/include/splash/basetypes/ColTypeUnknown.hpp index 4cffdcb..769ffb7 100644 --- a/src/include/splash/basetypes/ColTypeUnknown.hpp +++ b/src/include/splash/basetypes/ColTypeUnknown.hpp @@ -38,7 +38,7 @@ namespace splash std::string toString() const { - return "UNKNOWN"; + return "Unknown"; } }; } diff --git a/src/include/splash/basetypes/CollectionTypeGenerator.hpp b/src/include/splash/basetypes/CollectionTypeGenerator.hpp deleted file mode 100644 index 68e212c..0000000 --- a/src/include/splash/basetypes/CollectionTypeGenerator.hpp +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright 2015 Carlchristian Eckert - * - * This file is part of libSplash. - * - * libSplash is free software: you can redistribute it and/or modify - * it under the terms of of either the GNU General Public License or - * the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * libSplash is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License and the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * and the GNU Lesser General Public License along with libSplash. - * If not, see . - */ - -#ifndef COLTYPEGENERATOR_H -#define COLTYPEGENERATOR_H - - -#include "splash/basetypes/basetypes.hpp" -#include "splash/CollectionType.hpp" - -namespace splash -{ - -#define COLLECTION_TEST(_name) \ -{ \ - CollectionType* t = ColType##_name::genType(datatype_id); \ - if(t != NULL && typeid(*t) == typeid(ColType##_name)) return t; \ -} \ - - -class CollectionTypeGenerator{ -public: - - static CollectionType* genCollectionType(hid_t datatype_id) - { - // basetypes atomic - COLLECTION_TEST(Int8) - COLLECTION_TEST(Int16) - COLLECTION_TEST(Int32) - COLLECTION_TEST(Int64) - - COLLECTION_TEST(UInt8) - COLLECTION_TEST(UInt16) - COLLECTION_TEST(UInt32) - COLLECTION_TEST(UInt64) - - COLLECTION_TEST(Float) - COLLECTION_TEST(Double) - COLLECTION_TEST(Char) - COLLECTION_TEST(Int) - - - // ColType Bool -> must be before the other enum types! - COLLECTION_TEST(Bool) - - - // ColType String - COLLECTION_TEST(String) - - - // ColTypeArray() - COLLECTION_TEST(Float2Array) - COLLECTION_TEST(Float3Array) - COLLECTION_TEST(Float4Array) - - COLLECTION_TEST(Double2Array) - COLLECTION_TEST(Double3Array) - COLLECTION_TEST(Double4Array) - - COLLECTION_TEST(Int4Array) - COLLECTION_TEST(Int3Array) - COLLECTION_TEST(Int2Array) - - - // ColTypeDimArray - COLLECTION_TEST(DimArray) - - - // ColType Dim - COLLECTION_TEST(Dim) - - - // Coltype Compound - COLLECTION_TEST(Float2) - COLLECTION_TEST(Float3) - COLLECTION_TEST(Float4) - - COLLECTION_TEST(Double2) - COLLECTION_TEST(Double3) - COLLECTION_TEST(Double4) - - COLLECTION_TEST(Int2) - COLLECTION_TEST(Int3) - COLLECTION_TEST(Int4) - - return new ColTypeUnknown; - } - -}; - -} - - -#endif /* COLTYPEGENERATOR_H */ diff --git a/src/include/splash/basetypes/basetypes_array.hpp b/src/include/splash/basetypes/basetypes_array.hpp index 8d5142f..ce61c0d 100644 --- a/src/include/splash/basetypes/basetypes_array.hpp +++ b/src/include/splash/basetypes/basetypes_array.hpp @@ -48,7 +48,8 @@ namespace splash size_t getSize() const \ { return sizeof (_real_type) * _size; } \ \ - static CollectionType* genType(hid_t datatype_id){ \ + static CollectionType* genType(hid_t datatype_id) \ + { \ bool found = false; \ H5T_class_t h5_class = H5Tget_class(datatype_id); \ if(h5_class == H5T_ARRAY) \ diff --git a/src/include/splash/basetypes/basetypes_atomic.hpp b/src/include/splash/basetypes/basetypes_atomic.hpp index 6054421..c3da524 100644 --- a/src/include/splash/basetypes/basetypes_atomic.hpp +++ b/src/include/splash/basetypes/basetypes_atomic.hpp @@ -27,7 +27,6 @@ #include #include "splash/CollectionType.hpp" -#include "splash/basetypes/ColTypeUnknown.hpp" namespace splash { @@ -43,7 +42,8 @@ namespace splash size_t getSize() const \ { return sizeof (_real_type); } \ \ - static CollectionType* genType(hid_t datatype_id){ \ + static CollectionType* genType(hid_t datatype_id) \ + { \ bool found = false; \ H5T_class_t h5_class = H5Tget_class(datatype_id); \ if(h5_class == H5T_INTEGER || h5_class == H5T_FLOAT) \ diff --git a/src/include/splash/basetypes/basetypes_compound.hpp b/src/include/splash/basetypes/basetypes_compound.hpp index 1a4854f..54b0337 100644 --- a/src/include/splash/basetypes/basetypes_compound.hpp +++ b/src/include/splash/basetypes/basetypes_compound.hpp @@ -42,7 +42,8 @@ namespace splash ColType##_name() \ { \ this->type = H5Tcreate(H5T_COMPOUND, sizeof (_real_type) * _size); \ - for (size_t i = 0; i < _size; ++i) { \ + for (size_t i = 0; i < _size; ++i) \ + { \ H5Tinsert(this->type, COMPOUND_ELEMENTS[i], \ i * sizeof(_real_type), _h5_type); \ } \ @@ -54,7 +55,8 @@ namespace splash size_t getSize() const \ { return _size * sizeof (_real_type); } \ \ - static CollectionType* genType(hid_t datatype_id){ \ + static CollectionType* genType(hid_t datatype_id) \ + { \ H5T_class_t h5_class = H5Tget_class(datatype_id); \ bool found = false; \ if(h5_class == H5T_COMPOUND) \ @@ -62,7 +64,8 @@ namespace splash int nmembers = H5Tget_nmembers(datatype_id); \ if(nmembers == _size) \ { \ - for(int i = 0; i < nmembers && !found ; ++i){ \ + for(int i = 0; i < nmembers && !found ; ++i) \ + { \ hid_t mtype = H5Tget_member_type(datatype_id, i); \ char* mname = H5Tget_member_name(datatype_id, i); \ if(H5Tequal(mtype, _h5_type) == 1 && \ diff --git a/src/include/splash/basetypes/generateCollectionType.hpp b/src/include/splash/basetypes/generateCollectionType.hpp new file mode 100644 index 0000000..b659024 --- /dev/null +++ b/src/include/splash/basetypes/generateCollectionType.hpp @@ -0,0 +1,131 @@ +/** + * Copyright 2015 Carlchristian Eckert + * + * This file is part of libSplash. + * + * libSplash is free software: you can redistribute it and/or modify + * it under the terms of of either the GNU General Public License or + * the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * libSplash is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License and the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * and the GNU Lesser General Public License along with libSplash. + * If not, see . + */ + +#ifndef GENERATE_COLLECTION_TYPE_H +#define GENERATE_COLLECTION_TYPE_H + + +#include "splash/basetypes/basetypes.hpp" +#include "splash/CollectionType.hpp" + +namespace splash +{ + +/** + * Checks if a datatype_id (from an outer scope) can be used to generate a + * specific CollectionType derivate. + * + * If the call to the genType member function of a specific collection type + * is successful, it will return the pointer to an instance of this type. + * Otherwise, the pointer (which points to NULL) will be destroyed at the end + * of the local scope. + * + * @param _name the suffix of the ColType. i.e. to check for ColTypeBool, + * _name should be set to Bool. + */ +#define TRY_COLTYPE(_name) \ +{ \ + CollectionType* t = ColType##_name::genType(datatype_id); \ + if(t != NULL && typeid(*t) == typeid(ColType##_name)) return t; \ +} \ + + +/** + * Creates a new instance of a CollectionType based on the given datatype_id + * + * @param datatype_id the H5 datatype_id that should be converted into a + * CollectionType + * + * @return A pointer to a heap-allocated CollectionType, if a matching + * CollectionType could be determined. The allocated object must be + * freed by the caller at the end of its lifetime. + * If no matching CollectionType was found, returns NULL. + */ +CollectionType* generateCollectionType(hid_t datatype_id) +{ + // basetypes atomic + TRY_COLTYPE(Int8) + TRY_COLTYPE(Int16) + TRY_COLTYPE(Int32) + TRY_COLTYPE(Int64) + + TRY_COLTYPE(UInt8) + TRY_COLTYPE(UInt16) + TRY_COLTYPE(UInt32) + TRY_COLTYPE(UInt64) + + TRY_COLTYPE(Float) + TRY_COLTYPE(Double) + TRY_COLTYPE(Char) + TRY_COLTYPE(Int) + + + // ColType Bool -> must be before the other enum types! + TRY_COLTYPE(Bool) + + + // ColType String + TRY_COLTYPE(String) + + + // ColTypeArray() + TRY_COLTYPE(Float2Array) + TRY_COLTYPE(Float3Array) + TRY_COLTYPE(Float4Array) + + TRY_COLTYPE(Double2Array) + TRY_COLTYPE(Double3Array) + TRY_COLTYPE(Double4Array) + + TRY_COLTYPE(Int4Array) + TRY_COLTYPE(Int3Array) + TRY_COLTYPE(Int2Array) + + + // ColTypeDimArray + TRY_COLTYPE(DimArray) + + + // ColType Dim + TRY_COLTYPE(Dim) + + + // Coltype Compound + TRY_COLTYPE(Float2) + TRY_COLTYPE(Float3) + TRY_COLTYPE(Float4) + + TRY_COLTYPE(Double2) + TRY_COLTYPE(Double3) + TRY_COLTYPE(Double4) + + TRY_COLTYPE(Int2) + TRY_COLTYPE(Int3) + TRY_COLTYPE(Int4) + + return new ColTypeUnknown; +} + + +} /* namespace splash */ + + +#endif /* GENERATE_COLLECTION_TYPE_H */ diff --git a/tools/splashtools.cpp b/tools/splashtools.cpp index b4daaee..463d05c 100644 --- a/tools/splashtools.cpp +++ b/tools/splashtools.cpp @@ -500,7 +500,7 @@ int listAvailableDatasets(Options& options, DataCollector *dc, const char* /*fil for (size_t i = 0; i < num_entries; ++i) { - CollectionType* data_type = entries[i].col_type; + CollectionType* data_type = entries[i].colType; Dimensions sizeRead; dc->read(id, entries[i].name.c_str(), sizeRead, NULL); std::cout << entries[i].name From 17d808e78581c1df1a257d361c092e5b6e85e77d Mon Sep 17 00:00:00 2001 From: Carlchristian Eckert Date: Tue, 10 Nov 2015 11:12:27 +0100 Subject: [PATCH 46/47] addressed review comments by @f-schmitt-zih --- src/ParallelDataCollector.cpp | 9 ++------- src/SerialDataCollector.cpp | 9 ++------- src/include/splash/DataCollector.hpp | 19 +++++++++++++++++++ src/include/splash/ParallelDataCollector.hpp | 3 +++ src/include/splash/SerialDataCollector.hpp | 14 +++----------- .../splash/basetypes/ColTypeUnknown.hpp | 1 + .../basetypes/generateCollectionType.hpp | 3 +-- 7 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/ParallelDataCollector.cpp b/src/ParallelDataCollector.cpp index 259730b..5361820 100644 --- a/src/ParallelDataCollector.cpp +++ b/src/ParallelDataCollector.cpp @@ -566,10 +566,10 @@ namespace splash Dimensions& sizeRead) throw (DCException) { if (fileStatus != FST_READING && fileStatus != FST_WRITING) - throw DCException(getExceptionString("read", "this access is not permitted")); + throw DCException(getExceptionString("readMeta", "this access is not permitted")); uint32_t ndims = 0; - return readDataSetMeta(handles.get(0), id, name, dstBuffer, dstOffset, + return readDataSetMeta(handles.get(id), id, name, dstBuffer, dstOffset, Dimensions(0, 0, 0), sizeRead, ndims); } @@ -991,11 +991,6 @@ namespace splash DCDataSet dataset(dset_name.c_str()); dataset.open(group.getHandle()); - //size_t datatype_size = 0; - //DCDataType dc_datatype = DCDT_UNKNOWN; - //datatype_size = dataset.getDataTypeSize(); - //dc_datatype = dataset.getDCDataType(); - size_t entrySize; getEntriesForID(id, NULL, &entrySize); std::vector entries(entrySize); diff --git a/src/SerialDataCollector.cpp b/src/SerialDataCollector.cpp index 79d25cd..f935494 100644 --- a/src/SerialDataCollector.cpp +++ b/src/SerialDataCollector.cpp @@ -434,10 +434,10 @@ namespace splash throw (DCException) { if (fileStatus != FST_READING && fileStatus != FST_WRITING && fileStatus != FST_MERGING) - throw DCException(getExceptionString("read", "this access is not permitted")); + throw DCException(getExceptionString("readMeta", "this access is not permitted")); uint32_t ndims = 0; - return readDataSetMeta(handles.get(0), id, name, dstBuffer, dstOffset, + return readDataSetMeta(handles.get(id), id, name, dstBuffer, dstOffset, Dimensions(0, 0, 0), sizeRead, ndims); } @@ -994,11 +994,6 @@ namespace splash DCDataSet dataset(dset_name.c_str()); dataset.open(group.getHandle()); - //size_t datatype_size = 0; - //DCDataType dc_datatype = DCDT_UNKNOWN; - //datatype_size = dataset.getDataTypeSize(); - //dc_datatype = dataset.getDCDataType(); - size_t entrySize; getEntriesForID(id, NULL, &entrySize); std::vector entries(entrySize); diff --git a/src/include/splash/DataCollector.hpp b/src/include/splash/DataCollector.hpp index c5507ed..b0a512a 100644 --- a/src/include/splash/DataCollector.hpp +++ b/src/include/splash/DataCollector.hpp @@ -426,6 +426,25 @@ namespace splash const Dimensions dstOffset, Dimensions &sizeRead, void* buf) = 0; + + /** + * Reads meta data from HDF5 file. + * + * @param id ID of iteration. + * @param name Name of the dataset. + * @param dstBuffer Size of the dataset. + * @param dstOffset Offset in destination dataset. + * @param sizeRead Returns the size of the data in the file. + * + * @return The CollectionType of the dataset as a heap allocated + * object. The object must be freed by the caller at the + * end of the object's lifetime. + */ + virtual CollectionType* readMeta(int32_t id, + const char* name, + const Dimensions dstBuffer, + const Dimensions dstOffset, + Dimensions &sizeRead) = 0; }; } diff --git a/src/include/splash/ParallelDataCollector.hpp b/src/include/splash/ParallelDataCollector.hpp index 581c7ab..c4550cc 100644 --- a/src/include/splash/ParallelDataCollector.hpp +++ b/src/include/splash/ParallelDataCollector.hpp @@ -416,6 +416,9 @@ namespace splash Dimensions /*stride*/) throw (DCException); + /** + * Internal meta data reading method. + */ CollectionType* readDataSetMeta(H5Handle h5File, int32_t id, const char* name, diff --git a/src/include/splash/SerialDataCollector.hpp b/src/include/splash/SerialDataCollector.hpp index 8d77935..98116eb 100644 --- a/src/include/splash/SerialDataCollector.hpp +++ b/src/include/splash/SerialDataCollector.hpp @@ -161,17 +161,6 @@ namespace splash void* dst) throw (DCException); - void readDataSetMeta(H5Handle h5File, - int32_t id, - CollectionType &type, - const char* name, - const Dimensions dstBuffer, - const Dimensions dstOffset, - const Dimensions srcOffset, - Dimensions &sizeRead, - uint32_t& srcDims) - throw (DCException); - /** * Internal reading method. */ @@ -186,6 +175,9 @@ namespace splash uint32_t& srcDims, void* dst) throw (DCException); + /** + * Internal meta data reading method. + */ CollectionType* readDataSetMeta(H5Handle h5File, int32_t id, const char* name, diff --git a/src/include/splash/basetypes/ColTypeUnknown.hpp b/src/include/splash/basetypes/ColTypeUnknown.hpp index 769ffb7..e2ca9d0 100644 --- a/src/include/splash/basetypes/ColTypeUnknown.hpp +++ b/src/include/splash/basetypes/ColTypeUnknown.hpp @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/src/include/splash/basetypes/generateCollectionType.hpp b/src/include/splash/basetypes/generateCollectionType.hpp index b659024..b771454 100644 --- a/src/include/splash/basetypes/generateCollectionType.hpp +++ b/src/include/splash/basetypes/generateCollectionType.hpp @@ -8,6 +8,7 @@ * the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. + * * libSplash is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -35,8 +36,6 @@ namespace splash * * If the call to the genType member function of a specific collection type * is successful, it will return the pointer to an instance of this type. - * Otherwise, the pointer (which points to NULL) will be destroyed at the end - * of the local scope. * * @param _name the suffix of the ColType. i.e. to check for ColTypeBool, * _name should be set to Bool. From 043eab6dffaf8154601b5aca5338804e518cf467 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Wed, 11 Nov 2015 16:45:00 +0100 Subject: [PATCH 47/47] Release 1.3.0: Add Changelog Adds the change log and version increase for the **release 1.3.0** of `libSplash`. --- CHANGELOG.md | 47 ++++++++++++++++++++++++++++++++++ src/include/splash/version.hpp | 4 +-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6071c8b..ef52086 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,53 @@ Change Log for libSplash ================================================================ +Release 1.3.0 +------------- +**Date:** 2015-11-12 + +This release adds functionality for users to fulfill formatting for +`openPMD`. Support for array attributes, strings/chars, bools and +further `h5py` compatibility have been added. Additionally, read +functionality has improved by new meta calls to determine type +and size of a data set before reading. +The internal format was increased to version 3.3 + +**New Features** + + - bool types are now h5py compatible #153 #198 + - new interface `readMeta` in `DataCollector`s to determine type + and size before reading #203 + - new interfaces for `DataCollector`s `writeGlobalAttribute` to support + arrays via HDF5 simple data spaces (h5py compatible) #170 #171 + - `splashVersion` and `splashFormat` are now written to `/header` #183 + - header define `SPLASH_HDF5_VERSION` remembers HDF5 version of build #177 + - `char`s, fixed and variable length `string` support added #167 + + +**Interface Changes** + + - `ParallelDataCollector::writeGlobalAttribute` now writes to `/` instead of + `/custom` (`SerialDataCollector` unchanged) #182 + + +**Misc** + + - term "iteration" is now consequently preferred over + "time step" #157 #187 #188 #204 + - public includes do not throw on `-Wshadow` any more #201 + - `/header/compression` attribute in new bool representation #199 + - CMake: + - shared library detection refactored #192 + - FindHDF5 shipped with version support (pre CMake 3.3.0) #176 #169 + - doxygen project name updated #178 + - `DataSpace` refactored: prefer `DSP_DIM_MAX` over magic numbers #175 + - test scripts + - CI (travis) false-positive fixed #172 + - output improved #166 + - warn on missing dir argument #185 + - `INSTALL.md` now in project's root directory #158 + + Release 1.2.4 ------------- **Date:** 2015-01-25 diff --git a/src/include/splash/version.hpp b/src/include/splash/version.hpp index 82ece2d..f566dcc 100644 --- a/src/include/splash/version.hpp +++ b/src/include/splash/version.hpp @@ -25,8 +25,8 @@ /** the splash version reflects the changes in API */ #define SPLASH_VERSION_MAJOR 1 -#define SPLASH_VERSION_MINOR 2 -#define SPLASH_VERSION_PATCH 4 +#define SPLASH_VERSION_MINOR 3 +#define SPLASH_VERSION_PATCH 0 /** we can always handle files from the same major release * changes in the minor number have to be backwards compatible