diff --git a/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp b/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp index 6ab37a388f24beb17266d3828f77a1df4a906028..047b88dfb0502e284a78bfb21ce61059fafb1160 100644 --- a/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp +++ b/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp @@ -96,7 +96,10 @@ int main(int argc, char *argv[]) "Hello from rank: " + std::to_string(rank) + " and timestep: " + std::to_string(timeStep)); - bpWriter.PutSync(bpString, myString); + if (rank == 0) + { + bpWriter.PutSync(bpString, myString); + } bpWriter.EndStep(); } @@ -116,6 +119,9 @@ int main(int argc, char *argv[]) adios2::Variable<float> *bpFloats000 = ioReader.InquireVariable<float>("bpFloats000"); + adios2::Variable<std::string> *bpString = + ioReader.InquireVariable<std::string>("bpString"); + if (bpFloats000 != nullptr) { bpFloats000->SetSelection({{rank * Nx}, {Nx}}); @@ -125,7 +131,7 @@ int main(int argc, char *argv[]) bpReader.GetSync(*bpFloats000, data.data()); std::cout << "Data timestep " << bpFloats000->m_StepsStart - << " from rank " << rank << "\n"; + << " from rank " << rank << ": "; for (const auto datum : data) { std::cout << datum << " "; @@ -136,8 +142,17 @@ int main(int argc, char *argv[]) { std::cout << "Variable bpFloats000 not found\n"; } + + if (bpString != nullptr) + { + bpString->SetStepSelection({3, 1}); + + std::string myString; + bpReader.GetSync(*bpString, myString); + std::cout << myString << "\n"; + } + bpReader.Close(); - //} } } catch (std::invalid_argument &e) diff --git a/source/adios2/engine/bp/BPFileReader.tcc b/source/adios2/engine/bp/BPFileReader.tcc index 5fbecc0d91da68c15efa2691760f8e1b4dcb6487..743b4028909f2be8a42a2d6fbffde7e04253c9fc 100644 --- a/source/adios2/engine/bp/BPFileReader.tcc +++ b/source/adios2/engine/bp/BPFileReader.tcc @@ -16,10 +16,17 @@ namespace adios2 { +template <> +inline void BPFileReader::GetSyncCommon(Variable<std::string> &variable, + std::string *data) +{ + variable.SetData(data); + m_BP3Deserializer.GetStringFromMetadata(variable); +} + template <class T> -void BPFileReader::GetSyncCommon(Variable<T> &variable, T *data) +inline void BPFileReader::GetSyncCommon(Variable<T> &variable, T *data) { - // subfile info variable.SetData(data); const std::map<std::string, SubFileInfoMap> variableSubfileInfo = diff --git a/source/adios2/toolkit/format/bp3/BP3Base.tcc b/source/adios2/toolkit/format/bp3/BP3Base.tcc index ffd66cba53c7bb0652c894a07d075bd65077cf6f..3a807d2614805a3aa1743636fcc1a752a045ab6d 100644 --- a/source/adios2/toolkit/format/bp3/BP3Base.tcc +++ b/source/adios2/toolkit/format/bp3/BP3Base.tcc @@ -160,7 +160,7 @@ int8_t BP3Base::GetDataType<cldouble>() const noexcept } template <class T> -inline BP3Base::Characteristics<T> BP3Base::ReadElementIndexCharacteristics( +BP3Base::Characteristics<T> BP3Base::ReadElementIndexCharacteristics( const std::vector<char> &buffer, size_t &position, const DataTypes dataType, const bool untilTimeStep) const { diff --git a/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp b/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp index 99b668ffdde584408dc5d0a5c23ceefaffd7ce17..edf25648c899194f12f0c2daeea31721e66b6cd5 100644 --- a/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp +++ b/source/adios2/toolkit/format/bp3/BP3Deserializer.cpp @@ -65,6 +65,36 @@ void BP3Deserializer::ClipContiguousMemory( #undef declare_type } +void BP3Deserializer::GetStringFromMetadata( + Variable<std::string> &variable) const +{ + std::string *data = variable.GetData(); + const auto &buffer = m_Metadata.m_Buffer; + + for (size_t i = 0; i < variable.m_StepsCount; ++i) + { + *(data + i) = ""; + const size_t step = variable.m_StepsStart + i; + auto itStep = variable.m_IndexStepBlockStarts.find(step); + + if (itStep == variable.m_IndexStepBlockStarts.end()) + { + continue; + } + + for (auto position : itStep->second) + { + const Characteristics<std::string> characteristics = + ReadElementIndexCharacteristics<std::string>( + buffer, position, type_string, false); + + *(data + i) = characteristics.Statistics.Value; + } + + variable.m_Value = *(data + i); + } +} + // PRIVATE void BP3Deserializer::ParseMinifooter() { @@ -139,6 +169,13 @@ void BP3Deserializer::ParseVariablesIndex(IO &io) switch (header.DataType) { + // TODO: string + case (type_string): + { + DefineVariableInIO<std::string>(header, io, buffer, position); + break; + } + case (type_byte): { DefineVariableInIO<signed char>(header, io, buffer, position); @@ -225,7 +262,7 @@ void BP3Deserializer::ParseVariablesIndex(IO &io) position); break; } - // TODO: string + } // end switch }; diff --git a/source/adios2/toolkit/format/bp3/BP3Deserializer.h b/source/adios2/toolkit/format/bp3/BP3Deserializer.h index eb24da84f86b34ecdc080272f5d7a8e35429d48e..1cb508b6272dbf6d04d8880510b518442e1f8df0 100644 --- a/source/adios2/toolkit/format/bp3/BP3Deserializer.h +++ b/source/adios2/toolkit/format/bp3/BP3Deserializer.h @@ -59,6 +59,8 @@ public: const Box<Dims> &blockBox, const Box<Dims> &intersectionBox) const; + void GetStringFromMetadata(Variable<std::string> &variable) const; + private: std::map<std::string, SubFileInfoMap> m_DeferredVariables; diff --git a/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc b/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc index f36d3fb7fd4a279716490e62f9221d24370eb54d..3d49306b639e086e0ed07fe2d033680913d835e3 100644 --- a/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc +++ b/source/adios2/toolkit/format/bp3/BP3Deserializer.tcc @@ -37,11 +37,74 @@ void BP3Deserializer::GetDeferredVariable(Variable<T> &variable, T *data) } // PRIVATE +template <> +inline void BP3Deserializer::DefineVariableInIO<std::string>( + const ElementIndexHeader &header, IO &io, const std::vector<char> &buffer, + size_t position) const +{ + const size_t initialPosition = position; + + const Characteristics<std::string> characteristics = + ReadElementIndexCharacteristics<std::string>( + buffer, position, static_cast<DataTypes>(header.DataType)); + + std::string variableName(header.Name); + if (!header.Path.empty()) + { + variableName = header.Path + PathSeparator + header.Name; + } + + Variable<std::string> *variable = nullptr; + if (characteristics.Statistics.IsValue) + { + std::lock_guard<std::mutex> lock(m_Mutex); + variable = &io.DefineVariable<std::string>(variableName); + variable->m_Value = + characteristics.Statistics.Value; // assigning first step + } + else + { + // TODO: throw exception? + } + + // going back to get variable index position + variable->m_IndexStart = + initialPosition - (header.Name.size() + header.GroupName.size() + + header.Path.size() + 23); + + const size_t endPosition = + variable->m_IndexStart + static_cast<size_t>(header.Length) + 4; + + position = initialPosition; + + size_t currentStep = 0; // Starts at 1 in bp file + + while (position < endPosition) + { + const size_t subsetPosition = position; + + // read until step is found + const Characteristics<std::string> subsetCharacteristics = + ReadElementIndexCharacteristics<std::string>( + buffer, position, static_cast<DataTypes>(header.DataType), + false); + + if (subsetCharacteristics.Statistics.Step > currentStep) + { + currentStep = subsetCharacteristics.Statistics.Step; + variable->m_AvailableStepsCount = + subsetCharacteristics.Statistics.Step; + } + variable->m_IndexStepBlockStarts[currentStep].push_back(subsetPosition); + position = subsetPosition + subsetCharacteristics.EntryLength + 5; + } +} + template <class T> -void BP3Deserializer::DefineVariableInIO(const ElementIndexHeader &header, - IO &io, - const std::vector<char> &buffer, - size_t position) const +inline void +BP3Deserializer::DefineVariableInIO(const ElementIndexHeader &header, IO &io, + const std::vector<char> &buffer, + size_t position) const { const size_t initialPosition = position; diff --git a/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp b/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp index e0d72e8078667aa3b5262cba35a22fbf8d0f6f14..4aa708d8266a5af2b9c3e4c1c7229e1051a2484b 100644 --- a/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp +++ b/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp @@ -160,10 +160,10 @@ TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead1D8) adios2::Engine &bpReader = io.Open(fname, adios2::Mode::Read); - // auto var_iString = io.InquireVariable<std::string>("iString"); - // ASSERT_NE(var_iString, nullptr); - // ASSERT_EQ(var_iString->m_Shape.size(), 0); - // ASSERT_EQ(var_iString->m_AvailableStepsCount, NSteps); + auto var_iString = io.InquireVariable<std::string>("iString"); + ASSERT_NE(var_iString, nullptr); + ASSERT_EQ(var_iString->m_Shape.size(), 0); + ASSERT_EQ(var_iString->m_AvailableStepsCount, NSteps); auto var_i8 = io.InquireVariable<int8_t>("i8"); ASSERT_NE(var_i8, nullptr); @@ -228,7 +228,8 @@ TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead1D8) // TODO: other types SmallTestData testData; - std::vector<char> IString(testData.S1.size()); + + std::string IString; std::array<int8_t, Nx> I8; std::array<int16_t, Nx> I16; std::array<int32_t, Nx> I32; @@ -260,6 +261,8 @@ TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead1D8) for (size_t t = 0; t < NSteps; ++t) { + var_iString->SetStepSelection({t + 1, 1}); + var_i8->SetStepSelection({t + 1, 1}); var_i16->SetStepSelection({t + 1, 1}); var_i32->SetStepSelection({t + 1, 1}); @@ -277,6 +280,8 @@ TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead1D8) SmallTestData currentTestData = generateNewSmallTestData( m_TestData, static_cast<int>(t), mpiRank, mpiSize); + bpReader.GetSync(*var_iString, IString); + bpReader.GetDeferred(*var_i8, I8.data()); bpReader.GetDeferred(*var_i16, I16.data()); bpReader.GetDeferred(*var_i32, I32.data()); @@ -292,6 +297,8 @@ TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteRead1D8) bpReader.PerformGets(); + EXPECT_EQ(IString, currentTestData.S1); + for (size_t i = 0; i < Nx; ++i) { std::stringstream ss;