Commit 7a8eade9 authored by Kenneth Leiter's avatar Kenneth Leiter

ENH: Add ability to XPath a file when opening in order to only read a part of the file.

parent 49cd1fb0
...@@ -141,6 +141,11 @@ void XdmfMap::insert(const unsigned int localNodeId, const unsigned int remoteTa ...@@ -141,6 +141,11 @@ void XdmfMap::insert(const unsigned int localNodeId, const unsigned int remoteTa
} }
} }
bool XdmfMap::isInitialized() const
{
return mImpl->mMap.size() > 0;
}
void XdmfMap::populateItem(const std::map<std::string, std::string> & itemProperties, std::vector<boost::shared_ptr<XdmfItem> > & childItems) void XdmfMap::populateItem(const std::map<std::string, std::string> & itemProperties, std::vector<boost::shared_ptr<XdmfItem> > & childItems)
{ {
std::vector<boost::shared_ptr<XdmfArray> > arrayVector; std::vector<boost::shared_ptr<XdmfArray> > arrayVector;
...@@ -213,7 +218,7 @@ void XdmfMap::read() ...@@ -213,7 +218,7 @@ void XdmfMap::read()
void XdmfMap::release() void XdmfMap::release()
{ {
mImpl->mMap.clear();
} }
void XdmfMap::traverse(const boost::shared_ptr<XdmfBaseVisitor> visitor) void XdmfMap::traverse(const boost::shared_ptr<XdmfBaseVisitor> visitor)
......
...@@ -38,6 +38,11 @@ public: ...@@ -38,6 +38,11 @@ public:
void insert(const unsigned int localNodeId, const unsigned int remoteTaskId, const unsigned int remoteLocalNodeId); void insert(const unsigned int localNodeId, const unsigned int remoteTaskId, const unsigned int remoteLocalNodeId);
/**
* Returns whether the map is initialized (contains values in memory).
*/
bool isInitialized() const;
/** /**
* Read data from disk into memory. * Read data from disk into memory.
*/ */
......
...@@ -24,3 +24,8 @@ boost::shared_ptr<XdmfItem> XdmfReader::read(const std::string & filePath) const ...@@ -24,3 +24,8 @@ boost::shared_ptr<XdmfItem> XdmfReader::read(const std::string & filePath) const
{ {
return XdmfCoreReader::read(filePath); return XdmfCoreReader::read(filePath);
} }
std::vector<boost::shared_ptr<XdmfItem> > XdmfReader::read(const std::string & filePath, const std::string & xPath) const
{
return XdmfCoreReader::read(filePath, xPath);
}
...@@ -25,6 +25,8 @@ public: ...@@ -25,6 +25,8 @@ public:
boost::shared_ptr<XdmfItem> read(const std::string & filePath) const; boost::shared_ptr<XdmfItem> read(const std::string & filePath) const;
std::vector<boost::shared_ptr<XdmfItem> > read(const std::string & filePath, const std::string & xPath) const;
protected: protected:
XdmfReader(); XdmfReader();
......
...@@ -67,8 +67,6 @@ public: ...@@ -67,8 +67,6 @@ public:
return myItems; return myItems;
} }
private:
/** /**
* Reads a single xmlNode into an XdmfItem object in memory. The constructed XdmfItem is added to myItems and an entry is added mapping the xmlNodePtr to the new XdmfItem in the xPathMap. * Reads a single xmlNode into an XdmfItem object in memory. The constructed XdmfItem is added to myItems and an entry is added mapping the xmlNodePtr to the new XdmfItem in the xPathMap.
*/ */
...@@ -144,3 +142,34 @@ boost::shared_ptr<XdmfItem> XdmfCoreReader::read(const std::string & filePath) c ...@@ -144,3 +142,34 @@ boost::shared_ptr<XdmfItem> XdmfCoreReader::read(const std::string & filePath) c
return toReturn[0]; return toReturn[0];
} }
std::vector<boost::shared_ptr<XdmfItem> > XdmfCoreReader::read(const std::string & filePath, const std::string & xPath) const
{
std::string xmlDir = XdmfSystemUtils::getRealPath(filePath);
size_t index = xmlDir.find_last_of("/\\");
if(index != std::string::npos)
{
xmlDir = xmlDir.substr(0, index + 1);
}
const xmlDocPtr document = xmlReadFile(filePath.c_str(), NULL, 0);
const xmlXPathContextPtr xPathContext = xmlXPtrNewContext(document, NULL, NULL);
if(document == NULL)
{
assert(false);
}
std::vector<boost::shared_ptr<XdmfItem> > toReturn;
std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > xPathMap;
xmlXPathObjectPtr xPathObject = xmlXPathEvalExpression((xmlChar*)xPath.c_str(), xPathContext);
for(unsigned int i=0; i<xPathObject->nodesetval->nodeNr; ++i)
{
mImpl->readSingleNode(xPathObject->nodesetval->nodeTab[i], xPathContext, xPathMap, toReturn, xmlDir);
}
xmlXPathFreeObject(xPathObject);
xmlXPathFreeContext(xPathContext);
xmlFreeDoc(document);
xmlCleanupParser();
return toReturn;
}
...@@ -8,6 +8,7 @@ class XdmfItem; ...@@ -8,6 +8,7 @@ class XdmfItem;
// Includes // Includes
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <string> #include <string>
#include <vector>
/** /**
* @brief Reads an Xdmf structured file stored on disk into memory. * @brief Reads an Xdmf structured file stored on disk into memory.
...@@ -29,6 +30,15 @@ public: ...@@ -29,6 +30,15 @@ public:
*/ */
virtual boost::shared_ptr<XdmfItem> read(const std::string & filePath) const; virtual boost::shared_ptr<XdmfItem> read(const std::string & filePath) const;
/**
* Read part of an Xdmf file from disk into memory.
*
* @param filePath the path of the Xdmf file to read in from disk.
* @param xPath an XPath corresponding to the portion of the file to read.
* @return a vector of XdmfItems that are included in the XPath.
*/
virtual std::vector<boost::shared_ptr<XdmfItem> > read(const std::string & filePath, const std::string & xPath) const;
protected: protected:
/** /**
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "XdmfArrayType.hpp" #include "XdmfArrayType.hpp"
#include "XdmfHDF5Controller.hpp" #include "XdmfHDF5Controller.hpp"
#include "XdmfHDF5Writer.hpp" #include "XdmfHDF5Writer.hpp"
#include "XdmfSystemUtils.hpp"
/** /**
* PIMPL * PIMPL
...@@ -16,14 +17,16 @@ class XdmfHDF5Writer::XdmfHDF5WriterImpl { ...@@ -16,14 +17,16 @@ class XdmfHDF5Writer::XdmfHDF5WriterImpl {
public: public:
XdmfHDF5WriterImpl(const std::string & hdf5FilePath) : XdmfHDF5WriterImpl(const std::string & hdf5FilePath) :
mFilePath(hdf5FilePath), mFilePath(XdmfSystemUtils::getRealPath(hdf5FilePath)),
mDataSetId(0), mDataSetId(0),
mMode(Default) mMode(Default)
{ {
}; };
~XdmfHDF5WriterImpl() ~XdmfHDF5WriterImpl()
{ {
}; };
int mDataSetId; int mDataSetId;
std::string mFilePath; std::string mFilePath;
Mode mMode; Mode mMode;
......
...@@ -25,10 +25,10 @@ public: ...@@ -25,10 +25,10 @@ public:
mWriteXPaths(true), mWriteXPaths(true),
mXMLCurrentNode(NULL), mXMLCurrentNode(NULL),
mXMLDocument(NULL), mXMLDocument(NULL),
mXMLFilePath(XdmfSystemUtils::getRealPath(xmlFilePath)),
mXPathCount(0), mXPathCount(0),
mXPathString("") mXPathString("")
{ {
mXMLFilePath = XdmfSystemUtils::getRealPath(xmlFilePath);
}; };
~XdmfWriterImpl() ~XdmfWriterImpl()
...@@ -191,18 +191,18 @@ void XdmfWriter::visit(XdmfArray & array, const boost::shared_ptr<XdmfBaseVisito ...@@ -191,18 +191,18 @@ void XdmfWriter::visit(XdmfArray & array, const boost::shared_ptr<XdmfBaseVisito
xmlTextValues << array.getValuesString(); xmlTextValues << array.getValuesString();
} }
bool oldWriteXPaths = mImpl->mWriteXPaths;
mImpl->mWriteXPaths = false;
// Write XML (metadata) description // Write XML (metadata) description
if(isSubclassed) if(isSubclassed)
{ {
boost::shared_ptr<XdmfArray> arrayToWrite = XdmfArray::New(); boost::shared_ptr<XdmfArray> arrayToWrite = XdmfArray::New();
array.swap(arrayToWrite); array.swap(arrayToWrite);
mImpl->mXMLCurrentNode = mImpl->mXMLCurrentNode->last; mImpl->mXMLCurrentNode = mImpl->mXMLCurrentNode->last;
bool oldWriteXPaths = mImpl->mWriteXPaths;
mImpl->mWriteXPaths = false;
this->visit(dynamic_cast<XdmfItem &>(*arrayToWrite.get()), visitor); this->visit(dynamic_cast<XdmfItem &>(*arrayToWrite.get()), visitor);
xmlAddChild(mImpl->mXMLCurrentNode->last, xmlNewText((xmlChar*)xmlTextValues.str().c_str())); xmlAddChild(mImpl->mXMLCurrentNode->last, xmlNewText((xmlChar*)xmlTextValues.str().c_str()));
mImpl->mXMLCurrentNode = mImpl->mXMLCurrentNode->parent; mImpl->mXMLCurrentNode = mImpl->mXMLCurrentNode->parent;
mImpl->mWriteXPaths = oldWriteXPaths;
array.swap(arrayToWrite); array.swap(arrayToWrite);
} }
else else
...@@ -210,6 +210,8 @@ void XdmfWriter::visit(XdmfArray & array, const boost::shared_ptr<XdmfBaseVisito ...@@ -210,6 +210,8 @@ void XdmfWriter::visit(XdmfArray & array, const boost::shared_ptr<XdmfBaseVisito
this->visit(dynamic_cast<XdmfItem &>(array), visitor); this->visit(dynamic_cast<XdmfItem &>(array), visitor);
xmlAddChild(mImpl->mXMLCurrentNode->last, xmlNewText((xmlChar*)xmlTextValues.str().c_str())); xmlAddChild(mImpl->mXMLCurrentNode->last, xmlNewText((xmlChar*)xmlTextValues.str().c_str()));
} }
mImpl->mWriteXPaths = oldWriteXPaths;
} }
} }
......
...@@ -10,10 +10,12 @@ int main(int argc, char* argv[]) ...@@ -10,10 +10,12 @@ int main(int argc, char* argv[])
boost::shared_ptr<XdmfWriter> writer = XdmfWriter::New("TestXdmfReader1.xmf"); boost::shared_ptr<XdmfWriter> writer = XdmfWriter::New("TestXdmfReader1.xmf");
writer->setLightDataLimit(10); writer->setLightDataLimit(10);
boost::shared_ptr<XdmfGrid> grid = XdmfTestDataGenerator::createHexahedron(); boost::shared_ptr<XdmfGrid> grid1 = XdmfTestDataGenerator::createHexahedron();
boost::shared_ptr<XdmfGrid> grid2 = XdmfTestDataGenerator::createHexahedron();
boost::shared_ptr<XdmfDomain> domain = XdmfDomain::New(); boost::shared_ptr<XdmfDomain> domain = XdmfDomain::New();
domain->insert(grid); domain->insert(grid1);
domain->insert(grid2);
domain->accept(writer); domain->accept(writer);
boost::shared_ptr<XdmfReader> reader = XdmfReader::New(); boost::shared_ptr<XdmfReader> reader = XdmfReader::New();
...@@ -25,5 +27,14 @@ int main(int argc, char* argv[]) ...@@ -25,5 +27,14 @@ int main(int argc, char* argv[])
assert(XdmfTestCompareFiles::compareFiles("TestXdmfReader1.xmf", "TestXdmfReader2.xmf")); assert(XdmfTestCompareFiles::compareFiles("TestXdmfReader1.xmf", "TestXdmfReader2.xmf"));
std::vector<boost::shared_ptr<XdmfItem> > readItems = reader->read("TestXdmfReader1.xmf", "/Xdmf/Domain/Grid[1]");
assert(readItems.size() == 1);
boost::shared_ptr<XdmfGrid> readGrid = boost::shared_dynamic_cast<XdmfGrid>(readItems[0]);
assert(readGrid->getName().compare("Hexahedron") == 0);
std::vector<boost::shared_ptr<XdmfItem> > readItems2 = reader->read("TestXdmfReader1.xmf", "//Attribute");
assert(readItems2.size() == 4);
boost::shared_ptr<XdmfAttribute> readAttribute = boost::shared_dynamic_cast<XdmfAttribute>(readItems2[0]);
assert(readAttribute->getName().compare("Nodal Attribute") == 0 || readAttribute->getName().compare("Cell Attribute"));
return 0; return 0;
} }
...@@ -42,6 +42,7 @@ extern "C" ...@@ -42,6 +42,7 @@ extern "C"
#include "XdmfGridCollection.hpp" #include "XdmfGridCollection.hpp"
#include "XdmfGridCollectionType.hpp" #include "XdmfGridCollectionType.hpp"
#include "XdmfHDF5Writer.hpp" #include "XdmfHDF5Writer.hpp"
#include "XdmfMap.hpp"
#include "XdmfPartitioner.hpp" #include "XdmfPartitioner.hpp"
#include "XdmfSet.hpp" #include "XdmfSet.hpp"
#include "XdmfSetType.hpp" #include "XdmfSetType.hpp"
...@@ -60,30 +61,30 @@ boost::shared_ptr<XdmfGridCollection> XdmfPartitioner::partition(const boost::sh ...@@ -60,30 +61,30 @@ boost::shared_ptr<XdmfGridCollection> XdmfPartitioner::partition(const boost::sh
boost::shared_ptr<XdmfHDF5Writer> heavyDataWriter) const boost::shared_ptr<XdmfHDF5Writer> heavyDataWriter) const
{ {
int metisElementType; int metisElementType;
int numNodesPerElement; int nodesPerElement;
boost::shared_ptr<const XdmfTopologyType> topologyType = gridToPartition->getTopology()->getType(); boost::shared_ptr<const XdmfTopologyType> topologyType = gridToPartition->getTopology()->getType();
if(topologyType == XdmfTopologyType::Triangle() || topologyType == XdmfTopologyType::Triangle_6()) if(topologyType == XdmfTopologyType::Triangle() || topologyType == XdmfTopologyType::Triangle_6())
{ {
metisElementType = 1; metisElementType = 1;
numNodesPerElement = 3; nodesPerElement = 3;
} }
else if(topologyType == XdmfTopologyType::Quadrilateral() || topologyType == XdmfTopologyType::Quadrilateral_8()) else if(topologyType == XdmfTopologyType::Quadrilateral() || topologyType == XdmfTopologyType::Quadrilateral_8())
{ {
metisElementType = 4; metisElementType = 4;
numNodesPerElement = 4; nodesPerElement = 4;
} }
else if(topologyType == XdmfTopologyType::Tetrahedron() || topologyType == XdmfTopologyType::Tetrahedron_10()) else if(topologyType == XdmfTopologyType::Tetrahedron() || topologyType == XdmfTopologyType::Tetrahedron_10())
{ {
metisElementType = 2; metisElementType = 2;
numNodesPerElement = 4; nodesPerElement = 4;
} }
else if(topologyType == XdmfTopologyType::Hexahedron() || topologyType == XdmfTopologyType::Hexahedron_20() || else if(topologyType == XdmfTopologyType::Hexahedron() || topologyType == XdmfTopologyType::Hexahedron_20() ||
topologyType == XdmfTopologyType::Hexahedron_24() || topologyType == XdmfTopologyType::Hexahedron_27() || topologyType == XdmfTopologyType::Hexahedron_24() || topologyType == XdmfTopologyType::Hexahedron_27() ||
topologyType == XdmfTopologyType::Hexahedron_64()) topologyType == XdmfTopologyType::Hexahedron_64())
{ {
metisElementType = 3; metisElementType = 3;
numNodesPerElement = 8; nodesPerElement = 8;
} }
else else
{ {
...@@ -96,20 +97,20 @@ boost::shared_ptr<XdmfGridCollection> XdmfPartitioner::partition(const boost::sh ...@@ -96,20 +97,20 @@ boost::shared_ptr<XdmfGridCollection> XdmfPartitioner::partition(const boost::sh
} }
int numElements = gridToPartition->getTopology()->getNumberElements(); int numElements = gridToPartition->getTopology()->getNumberElements();
idxtype * metisConnectivity = new idxtype[numNodesPerElement * numElements]; idxtype * metisConnectivity = new idxtype[nodesPerElement * numElements];
for(unsigned int i=0; i<numElements; ++i) for(unsigned int i=0; i<numElements; ++i)
{ {
gridToPartition->getTopology()->getValuesCopy(i*topologyType->getNodesPerElement(), &metisConnectivity[i*numNodesPerElement], numNodesPerElement); gridToPartition->getTopology()->getValuesCopy(i*topologyType->getNodesPerElement(), &metisConnectivity[i*nodesPerElement], nodesPerElement);
} }
int numNodes = gridToPartition->getGeometry()->getNumberPoints(); int numNodes = gridToPartition->getGeometry()->getNumberPoints();
// Need to remap connectivity for nonlinear elements so that metis handles it properly. // Need to remap connectivity for nonlinear elements so that metis handles it properly.
std::map<idxtype, idxtype> xdmfIdToMetisId; std::map<idxtype, idxtype> xdmfIdToMetisId;
if(numNodesPerElement != topologyType->getNodesPerElement()) if(nodesPerElement != topologyType->getNodesPerElement())
{ {
unsigned int index = 0; unsigned int index = 0;
for (unsigned int i=0; i<numElements * numNodesPerElement; ++i) for (unsigned int i=0; i<numElements * nodesPerElement; ++i)
{ {
std::map<idxtype, idxtype>::const_iterator val = xdmfIdToMetisId.find(metisConnectivity[i]); std::map<idxtype, idxtype>::const_iterator val = xdmfIdToMetisId.find(metisConnectivity[i]);
if (val != xdmfIdToMetisId.end()) if (val != xdmfIdToMetisId.end())
...@@ -173,8 +174,7 @@ boost::shared_ptr<XdmfGridCollection> XdmfPartitioner::partition(const boost::sh ...@@ -173,8 +174,7 @@ boost::shared_ptr<XdmfGridCollection> XdmfPartitioner::partition(const boost::sh
} }
delete [] elementsPartition; delete [] elementsPartition;
boost::shared_ptr<XdmfAttribute> globalNodeIds = gridToPartition->getAttribute("GlobalNodeId"); bool generateGlobalNodeIds = !gridToPartition->getAttribute("GlobalNodeId");
bool generateGlobalNodeIds = !globalNodeIds;
boost::shared_ptr<XdmfGridCollection> partitionedGrids = XdmfGridCollection::New(); boost::shared_ptr<XdmfGridCollection> partitionedGrids = XdmfGridCollection::New();
partitionedGrids->setType(XdmfGridCollectionType::Spatial()); partitionedGrids->setType(XdmfGridCollectionType::Spatial());
...@@ -243,7 +243,7 @@ boost::shared_ptr<XdmfGridCollection> XdmfPartitioner::partition(const boost::sh ...@@ -243,7 +243,7 @@ boost::shared_ptr<XdmfGridCollection> XdmfPartitioner::partition(const boost::sh
if (generateGlobalNodeIds) if (generateGlobalNodeIds)
{ {
globalNodeIds = XdmfAttribute::New(); boost::shared_ptr<XdmfAttribute> globalNodeIds = XdmfAttribute::New();
globalNodeIds->setName("GlobalNodeId"); globalNodeIds->setName("GlobalNodeId");
globalNodeIds->setType(XdmfAttributeType::GlobalId()); globalNodeIds->setType(XdmfAttributeType::GlobalId());
globalNodeIds->setCenter(XdmfAttributeCenter::Node()); globalNodeIds->setCenter(XdmfAttributeCenter::Node());
...@@ -395,6 +395,29 @@ boost::shared_ptr<XdmfGridCollection> XdmfPartitioner::partition(const boost::sh ...@@ -395,6 +395,29 @@ boost::shared_ptr<XdmfGridCollection> XdmfPartitioner::partition(const boost::sh
} }
currSet->release(); currSet->release();
} }
// Add XdmfMap to map boundary nodes between partitions
std::vector<boost::shared_ptr<XdmfAttribute> > globalNodeIds;
for(unsigned int i=0; i<partitionedGrids->getNumberGrids(); ++i)
{
boost::shared_ptr<XdmfAttribute> globalNodeId = partitionedGrids->getGrid(i)->getAttribute("GlobalNodeId");
globalNodeId->read();
globalNodeIds.push_back(globalNodeId);
}
std::vector<boost::shared_ptr<XdmfMap> > maps = XdmfMap::New(globalNodeIds);
for(unsigned int i=0; i<partitionedGrids->getNumberGrids(); ++i)
{
boost::shared_ptr<XdmfMap> map = maps[i];
partitionedGrids->getGrid(i)->setMap(map);
if(heavyDataWriter)
{
globalNodeIds[i]->release();
map->accept(heavyDataWriter);
map->release();
}
}
return partitionedGrids; return partitionedGrids;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment