From 9f1c72b8c66f8daa248cf14fe209f9c34608605d Mon Sep 17 00:00:00 2001 From: Kenneth Leiter Date: Wed, 7 Jul 2010 16:38:40 -0400 Subject: [PATCH] ENH: Add Mode to XdmfWriter. Default mode ensures that all heavy data referenced by the XML file being written exists in a single heavy data file. A DistributedHeavyData mode can be set to allow heavy data referenced by the XML file to exist in more than one hdf5 file. --- core/XdmfHDF5Controller.cpp | 12 ++++++------ core/XdmfHDF5Controller.hpp | 4 ++-- core/XdmfHDF5Writer.cpp | 18 ++++++++++++++---- core/XdmfHDF5Writer.hpp | 21 ++++++++++++++++++++- core/XdmfWriter.cpp | 34 ++++++++++++++++++++++++++++++---- core/XdmfWriter.hpp | 33 ++++++++++++++++++++++++++++++++- tests/Cxx/TestXdmfReader.cpp | 1 + tests/Cxx/TestXdmfWriter.cpp | 2 ++ 8 files changed, 107 insertions(+), 18 deletions(-) diff --git a/core/XdmfHDF5Controller.cpp b/core/XdmfHDF5Controller.cpp index b7330075..59219089 100644 --- a/core/XdmfHDF5Controller.cpp +++ b/core/XdmfHDF5Controller.cpp @@ -14,8 +14,8 @@ XdmfHDF5Controller::XdmfHDF5Controller(const std::string & dataSetPath, const un size_t colonLocation = dataSetPath.find(":"); if(colonLocation != std::string::npos) { - mHDF5FilePath = dataSetPath.substr(0, colonLocation); - if(colonLocation + 1 != mHDF5FilePath.size()) + mFilePath = dataSetPath.substr(0, colonLocation); + if(colonLocation + 1 != mFilePath.size()) { mDataSetName = dataSetPath.substr(colonLocation + 1, dataSetPath.size()); } @@ -42,13 +42,13 @@ std::string XdmfHDF5Controller::getDataSetName() const std::string XdmfHDF5Controller::getDataSetPath() const { std::stringstream toReturn; - toReturn << mHDF5FilePath << ":" << mDataSetName; + toReturn << mFilePath << ":" << mDataSetName; return toReturn.str(); } -std::string XdmfHDF5Controller::getHDF5FilePath() const +std::string XdmfHDF5Controller::getFilePath() const { - return mHDF5FilePath; + return mFilePath; } unsigned int XdmfHDF5Controller::getSize() const @@ -63,7 +63,7 @@ boost::shared_ptr XdmfHDF5Controller::getType() const void XdmfHDF5Controller::read(XdmfArray * const array) { - hid_t hdf5Handle = H5Fopen(mHDF5FilePath.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); + hid_t hdf5Handle = H5Fopen(mFilePath.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); hid_t dataset = H5Dopen(hdf5Handle, mDataSetName.c_str(), H5P_DEFAULT); hid_t dataspace = H5Dget_space(dataset); hssize_t numVals = H5Sget_simple_extent_npoints(dataspace); diff --git a/core/XdmfHDF5Controller.hpp b/core/XdmfHDF5Controller.hpp index 65feb341..3d7744de 100644 --- a/core/XdmfHDF5Controller.hpp +++ b/core/XdmfHDF5Controller.hpp @@ -49,7 +49,7 @@ public: * * @return a std::string containing the path to the hdf5 file. */ - std::string getHDF5FilePath() const; + std::string getFilePath() const; /** * Get the size of the hdf5 data set owned by this controller. @@ -82,7 +82,7 @@ private: void operator=(const XdmfHDF5Controller & hdf5Controller); // Not implemented. std::string mDataSetName; - std::string mHDF5FilePath; + std::string mFilePath; unsigned int mSize; boost::shared_ptr mType; }; diff --git a/core/XdmfHDF5Writer.cpp b/core/XdmfHDF5Writer.cpp index 95768c26..b6a31b80 100644 --- a/core/XdmfHDF5Writer.cpp +++ b/core/XdmfHDF5Writer.cpp @@ -15,7 +15,7 @@ class XdmfHDF5Writer::XdmfHDF5WriterImpl { public: XdmfHDF5WriterImpl(const std::string & hdf5FilePath) : - mHDF5FilePath(hdf5FilePath), + mFilePath(hdf5FilePath), mLastWrittenDataSet(""), mDataSetId(0), mMode(Default) @@ -25,7 +25,7 @@ public: { }; int mDataSetId; - std::string mHDF5FilePath; + std::string mFilePath; std::string mLastWrittenDataSet; Mode mMode; }; @@ -107,11 +107,21 @@ XdmfHDF5Writer::~XdmfHDF5Writer() std::cout << "Deleted XdmfHDF5Writer " << this << std::endl; } +std::string XdmfHDF5Writer::getFilePath() const +{ + return mImpl->mFilePath; +} + std::string XdmfHDF5Writer::getLastWrittenDataSet() const { return mImpl->mLastWrittenDataSet; } +XdmfHDF5Writer::Mode XdmfHDF5Writer::getMode() const +{ + return mImpl->mMode; +} + void XdmfHDF5Writer::setMode(const Mode mode) { mImpl->mMode = mode; @@ -137,14 +147,14 @@ void XdmfHDF5Writer::visit(XdmfArray & array, const boost::shared_ptrmHDF5FilePath; + std::string hdf5FilePath = mImpl->mFilePath; std::stringstream dataSetName; if((mImpl->mMode == Overwrite || mImpl->mMode == Append) && array.mHDF5Controller) { // Write to the previous dataset dataSetName << array.mHDF5Controller->getDataSetName(); - hdf5FilePath = array.mHDF5Controller->getHDF5FilePath(); + hdf5FilePath = array.mHDF5Controller->getFilePath(); } else { diff --git a/core/XdmfHDF5Writer.hpp b/core/XdmfHDF5Writer.hpp index e8d82e05..a3832161 100644 --- a/core/XdmfHDF5Writer.hpp +++ b/core/XdmfHDF5Writer.hpp @@ -45,7 +45,12 @@ public: return p; } - void setMode(const Mode mode); + /** + * Get the path to the hdf5 file on disk this writer is writing to. + * + * @return a std::string containing the path to the hdf5 file on disk this writer is writing to. + */ + std::string getFilePath() const; /** * Get the path to the last written data set written by this writer. @@ -54,6 +59,20 @@ public: */ std::string getLastWrittenDataSet() const; + /** + * Get the Mode of operation for this writer. + * + * @return the Mode of operation for this writer. + */ + Mode getMode() const; + + /** + * Set the mode of operation for this writer. + * + * @param mode the Mode of operation for this writer. + */ + void setMode(const Mode mode); + /** * Write an XdmfArray to HDF5. * diff --git a/core/XdmfWriter.cpp b/core/XdmfWriter.cpp index f607c715..b9be95e5 100644 --- a/core/XdmfWriter.cpp +++ b/core/XdmfWriter.cpp @@ -5,6 +5,7 @@ #include #include "XdmfArray.hpp" #include "XdmfItem.hpp" +#include "XdmfHDF5Controller.hpp" #include "XdmfHDF5Writer.hpp" #include "XdmfWriter.hpp" @@ -18,18 +19,22 @@ public: XdmfWriterImpl(const std::string & xmlFilePath, const boost::shared_ptr hdf5Writer) : mHDF5Writer(hdf5Writer), mLightDataLimit(100), - mXMLFilePath(xmlFilePath), - mTraverseLevel(0) + mMode(Default), + mTraverseLevel(0), + mXMLCurrentNode(NULL), + mXMLDocument(NULL), + mXMLFilePath(xmlFilePath) { }; ~XdmfWriterImpl() { }; boost::shared_ptr mHDF5Writer; - unsigned int mTraverseLevel; unsigned int mLightDataLimit; - xmlDocPtr mXMLDocument; + Mode mMode; + unsigned int mTraverseLevel; xmlNodePtr mXMLCurrentNode; + xmlDocPtr mXMLDocument; std::string mXMLFilePath; }; @@ -79,11 +84,21 @@ boost::shared_ptr XdmfWriter::getHDF5Writer() const return mImpl->mHDF5Writer; } +std::string XdmfWriter::getFilePath() const +{ + return mImpl->mXMLFilePath; +} + unsigned int XdmfWriter::getLightDataLimit() const { return mImpl->mLightDataLimit; } +XdmfWriter::Mode XdmfWriter::getMode() const +{ + return mImpl->mMode; +} + void XdmfWriter::openFile() { mImpl->mXMLDocument = xmlNewDoc((xmlChar*)"1.0"); @@ -96,9 +111,20 @@ void XdmfWriter::setLightDataLimit(const unsigned int numValues) mImpl->mLightDataLimit = numValues; } +void XdmfWriter::setMode(const Mode mode) +{ + mImpl->mMode = mode; +} + void XdmfWriter::visit(XdmfArray & array, const boost::shared_ptr visitor) { std::stringstream xmlTextValues; + + if(array.getHDF5Controller() && array.getHDF5Controller()->getFilePath().compare(mImpl->mHDF5Writer->getFilePath()) != 0 && mImpl->mMode == Default) + { + array.read(); + } + if(array.getHDF5Controller() || array.getSize() > mImpl->mLightDataLimit) { mImpl->mHDF5Writer->visit(array, mImpl->mHDF5Writer); diff --git a/core/XdmfWriter.hpp b/core/XdmfWriter.hpp index c5129831..9889eaf5 100644 --- a/core/XdmfWriter.hpp +++ b/core/XdmfWriter.hpp @@ -11,10 +11,16 @@ class XdmfHDF5Writer; /** * @brief Traverse the Xdmf graph and write light and heavy data stored to disk. * - * XdmfWriter visits each node of an Xdmf graph structure and writes the data to disk. Writing begins by calling the + * XdmfWriter visits each node of an Xdmf graph structure and writes data to disk. Writing begins by calling the * accept() operation on any XdmfItem and supplying this writer as the parameter. The XdmfItem as well as all children * attached to the XdmfItem are written to disk. Heavy data is written to HDF5 format using the XdmfHDF5Writer and light * data is written to XML. + * + * By default, the XdmfWriter writes all heavy data to a single heavy data file specified by the XdmfHDF5Writer. + * If a dataset is encountered that resides in a different heavy data file on disk, the dataset is read from disk and written + * to the new hdf5 file. If this is undesired, the XdmfWriter can be set to DistributedHeavyData mode in which the writer + * will automatically reference any hdf5 dataset even if it resides in a different file than the one currently being written to. + * written. */ class XdmfWriter : public XdmfVisitor, public Loki::Visitor { @@ -23,6 +29,10 @@ public: virtual ~XdmfWriter(); + enum Mode { + Default, DistributedHeavyData + }; + /** * Create a new XdmfWriter to write Xdmf data to disk. This will create its own hdf5 writer based on the xmlFileName. * For example, if supplied "output.xmf" the created hdf5 writer would write to file "output.h5". @@ -50,6 +60,13 @@ public: return p; } + /** + * Get the path to the XML file on disk this writer is writing to. + * + * @return a std::string containing the path to the XML file on disk this writer is writing to. + */ + std::string getFilePath() const; + /** * Get the hdf5 writer that this XdmfWriter uses to write heavy data to disk. * @@ -71,6 +88,13 @@ public: */ unsigned int getLightDataLimit() const; + /** + * Get the Mode of operation for this writer. + * + * @return the Mode of operation for this writer. + */ + Mode getMode() const; + /** * Set the number of values that this writer writes to light data (XML) before switching to a heavy data format. * @@ -78,6 +102,13 @@ public: */ void setLightDataLimit(const unsigned int numValues); + /** + * Set the mode of operation for this writer. + * + * @param mode the Mode of operation for this writer. + */ + void setMode(const Mode mode); + /** * Write an XdmfArray to disk * diff --git a/tests/Cxx/TestXdmfReader.cpp b/tests/Cxx/TestXdmfReader.cpp index a4910a7d..9035c51f 100644 --- a/tests/Cxx/TestXdmfReader.cpp +++ b/tests/Cxx/TestXdmfReader.cpp @@ -21,6 +21,7 @@ int main(int argc, char* argv[]) boost::shared_ptr readDomain = boost::shared_dynamic_cast(reader->read("TestXdmfReader1.xmf")); boost::shared_ptr writer2 = XdmfWriter::New("TestXdmfReader2.xmf"); + writer2->setMode(XdmfWriter::DistributedHeavyData); readDomain->accept(writer2); // Compare two files for equality diff --git a/tests/Cxx/TestXdmfWriter.cpp b/tests/Cxx/TestXdmfWriter.cpp index ba6025ec..e0824511 100644 --- a/tests/Cxx/TestXdmfWriter.cpp +++ b/tests/Cxx/TestXdmfWriter.cpp @@ -5,7 +5,9 @@ int main(int argc, char* argv[]) { boost::shared_ptr writer = XdmfWriter::New("output.xmf"); + assert(writer->getFilePath().compare("output.xmf") == 0); writer->setLightDataLimit(10); + assert(writer->getLightDataLimit() == 10); boost::shared_ptr grid = XdmfTestDataGenerator::createHexahedron(); -- GitLab