Commit 996d9c05 authored by Kenneth Leiter's avatar Kenneth Leiter

ENH: Have all dataitems inherit directly from XdmfArray. Modify writing to support this.

parent 99ace678
......@@ -10,7 +10,6 @@ swig -v -c++ -python -o XdmfPython.cpp Xdmf.i
#include <XdmfArrayType.hpp>
#include <XdmfCoreItemFactory.hpp>
#include <XdmfCoreReader.hpp>
#include <XdmfDataItem.hpp>
#include <XdmfHDF5Controller.hpp>
#include <XdmfHDF5Writer.hpp>
#include <XdmfInformation.hpp>
......
......@@ -70,8 +70,14 @@ void XdmfAttribute::populateItem(const std::map<std::string, std::string> & item
}
mAttributeCenter = XdmfAttributeCenter::New(itemProperties);
mAttributeType = XdmfAttributeType::New(itemProperties);
XdmfDataItem::populateItem(itemProperties, childItems);
for(std::vector<boost::shared_ptr<XdmfItem> >::const_iterator iter = childItems.begin(); iter != childItems.end(); ++iter)
{
if(boost::shared_ptr<XdmfArray> array = boost::shared_dynamic_cast<XdmfArray>(*iter))
{
this->swap(array);
}
// TODO: If multiple dataitems.
}
}
void XdmfAttribute::setCenter(const boost::shared_ptr<const XdmfAttributeCenter> attributeCenter)
......
......@@ -6,7 +6,7 @@ class XdmfAttributeCenter;
class XdmfAttributeType;
// Includes
#include "XdmfDataItem.hpp"
#include "XdmfArray.hpp"
/**
* @brief Handles computed values attached to an XdmfGrid.
......@@ -14,7 +14,7 @@ class XdmfAttributeType;
* XdmfAttribute contains two properties that should be set, XdmfAttributeCenter and XdmfAttributeType.
* XdmfAttribute is a subclass of XdmfDataItem, meaning it contains an XdmfArray to store values.
*/
class XdmfAttribute : public XdmfDataItem {
class XdmfAttribute : public XdmfArray {
public:
......@@ -27,7 +27,7 @@ public:
virtual ~XdmfAttribute();
LOKI_DEFINE_VISITABLE(XdmfAttribute, XdmfDataItem)
LOKI_DEFINE_VISITABLE(XdmfAttribute, XdmfArray)
static const std::string ItemTag;
/**
......
......@@ -5,7 +5,6 @@
* Author: kleiter
*/
#include "XdmfArray.hpp"
#include "XdmfGeometry.hpp"
#include "XdmfGeometryType.hpp"
......@@ -45,7 +44,7 @@ unsigned int XdmfGeometry::getNumberPoints() const
{
return 0;
}
return this->getArray()->size() / mGeometryType->getDimensions();
return this->size() / mGeometryType->getDimensions();
}
boost::shared_ptr<const XdmfGeometryType> XdmfGeometry::getType() const
......@@ -56,7 +55,14 @@ boost::shared_ptr<const XdmfGeometryType> XdmfGeometry::getType() const
void XdmfGeometry::populateItem(const std::map<std::string, std::string> & itemProperties, std::vector<boost::shared_ptr<XdmfItem> > & childItems)
{
mGeometryType = XdmfGeometryType::New(itemProperties);
XdmfDataItem::populateItem(itemProperties, childItems);
for(std::vector<boost::shared_ptr<XdmfItem> >::const_iterator iter = childItems.begin(); iter != childItems.end(); ++iter)
{
if(boost::shared_ptr<XdmfArray> array = boost::shared_dynamic_cast<XdmfArray>(*iter))
{
this->swap(array);
}
// TODO: If multiple dataitems.
}
}
void XdmfGeometry::setType(const boost::shared_ptr<const XdmfGeometryType> geometryType)
......
......@@ -5,7 +5,7 @@
class XdmfGeometryType;
// Includes
#include "XdmfDataItem.hpp"
#include "XdmfArray.hpp"
/**
* @brief Handles the coordinate positions of points in an XdmfGrid.
......@@ -14,7 +14,7 @@ class XdmfGeometryType;
* of all points contained in an XdmfGrid. XdmfGeometry contains an XdmfGeometryType property
* which should be set that specifies the types of coordinate values stored.
*/
class XdmfGeometry : public XdmfDataItem {
class XdmfGeometry : public XdmfArray {
public:
......@@ -27,7 +27,7 @@ public:
virtual ~XdmfGeometry();
LOKI_DEFINE_VISITABLE(XdmfGeometry, XdmfDataItem)
LOKI_DEFINE_VISITABLE(XdmfGeometry, XdmfArray)
static const std::string ItemTag;
std::map<std::string, std::string> getItemProperties() const;
......
......@@ -16,7 +16,8 @@ class XdmfGridCollectionType;
*
* It is valid to nest collections. A spatial collection within a temporal collection is commonly used.
*/
class XdmfGridCollection : public XdmfGrid, public XdmfDomain {
class XdmfGridCollection : public XdmfGrid,
public XdmfDomain {
public:
......
......@@ -6,7 +6,6 @@
*/
#include <sstream>
#include "XdmfArray.hpp"
#include "XdmfTopology.hpp"
#include "XdmfTopologyType.hpp"
......@@ -51,7 +50,7 @@ unsigned int XdmfTopology::getNumberElements() const
{
return 0;
}
return this->getArray()->size() / mTopologyType->getNodesPerElement();
return this->size() / mTopologyType->getNodesPerElement();
}
boost::shared_ptr<const XdmfTopologyType> XdmfTopology::getType() const
......@@ -62,7 +61,14 @@ boost::shared_ptr<const XdmfTopologyType> XdmfTopology::getType() const
void XdmfTopology::populateItem(const std::map<std::string, std::string> & itemProperties, std::vector<boost::shared_ptr<XdmfItem> > & childItems)
{
mTopologyType = XdmfTopologyType::New(itemProperties);
XdmfDataItem::populateItem(itemProperties, childItems);
for(std::vector<boost::shared_ptr<XdmfItem> >::const_iterator iter = childItems.begin(); iter != childItems.end(); ++iter)
{
if(boost::shared_ptr<XdmfArray> array = boost::shared_dynamic_cast<XdmfArray>(*iter))
{
this->swap(array);
}
// TODO: If multiple dataitems.
}
}
void XdmfTopology::setType(const boost::shared_ptr<const XdmfTopologyType> topologyType)
......
......@@ -5,7 +5,7 @@
class XdmfTopologyType;
// Includes
#include "XdmfDataItem.hpp"
#include "XdmfArray.hpp"
/**
* @brief Handles the connectivity information in an XdmfGrid.
......@@ -14,7 +14,7 @@ class XdmfTopologyType;
* between all points contained in an XdmfGrid. XdmfTopology contains an XdmfTopologyType property
* which should be set that specifies the element type stored.
*/
class XdmfTopology : public XdmfDataItem {
class XdmfTopology : public XdmfArray {
public:
......@@ -27,7 +27,7 @@ public:
virtual ~XdmfTopology();
LOKI_DEFINE_VISITABLE(XdmfTopology, XdmfDataItem)
LOKI_DEFINE_VISITABLE(XdmfTopology, XdmfArray)
static const std::string ItemTag;
std::map<std::string, std::string> getItemProperties() const;
......
......@@ -25,7 +25,6 @@ set(XdmfCoreSources
XdmfArrayType
XdmfCoreItemFactory
XdmfCoreReader
XdmfDataItem
XdmfHDF5Controller
XdmfHDF5Writer
XdmfInformation
......
......@@ -698,16 +698,19 @@ void XdmfArray::swap(const boost::shared_ptr<XdmfArray> array)
int tmpArrayPointerNumValues = array->mArrayPointerNumValues;
bool tmpHaveArray = array->mHaveArray;
bool tmpHaveArrayPointer = array->mHaveArrayPointer;
boost::shared_ptr<XdmfHDF5Controller> tmpHDF5Controller = array->mHDF5Controller;
array->mArray = mArray;
array->mArrayPointer = mArrayPointer;
array->mArrayPointerNumValues = mArrayPointerNumValues;
array->mHaveArray = mHaveArray;
array->mHaveArrayPointer = mHaveArrayPointer;
array->mHDF5Controller = mHDF5Controller;
mArray = tmpArray;
mArrayPointer = tmpArrayPointer;
mArrayPointerNumValues = tmpArrayPointerNumValues;
mHaveArray = tmpHaveArray;
mHaveArrayPointer = tmpHaveArrayPointer;
mHDF5Controller = tmpHDF5Controller;
}
......@@ -11,7 +11,6 @@ swig -v -c++ -python -o XdmfCorePython.cpp XdmfCore.i
#include <XdmfCoreItemFactory.hpp>
#include <XdmfCoreReader.hpp>
#include <XdmfCoreWriter.hpp>
#include <XdmfDataItem.hpp>
#include <XdmfHDF5Controller.hpp>
#include <XdmfInformation.hpp>
#include <XdmfItem.hpp>
......@@ -37,7 +36,6 @@ swig -v -c++ -python -o XdmfCorePython.cpp XdmfCore.i
%shared_ptr(XdmfCoreItemFactory)
%shared_ptr(XdmfCoreReader)
%shared_ptr(XdmfCoreWriter)
%shared_ptr(XdmfDataItem)
%shared_ptr(XdmfHDF5Controller)
%shared_ptr(XdmfHDF5Writer)
%shared_ptr(XdmfInformation)
......
/*
* XdmfDataItem.cpp
*
* Created on: Jan 29, 2010
* Author: kleiter
*/
#include "XdmfArray.hpp"
#include "XdmfDataItem.hpp"
XdmfDataItem::XdmfDataItem() :
mArray(XdmfArray::New())
{
}
XdmfDataItem::~XdmfDataItem()
{
}
boost::shared_ptr<XdmfArray> XdmfDataItem::getArray()
{
return boost::const_pointer_cast<XdmfArray>(static_cast<const XdmfDataItem &>(*this).getArray());
}
boost::shared_ptr<const XdmfArray> XdmfDataItem::getArray() const
{
return mArray;
}
void XdmfDataItem::populateItem(const std::map<std::string, std::string> & itemProperties, std::vector<boost::shared_ptr<XdmfItem> > & childItems)
{
for(std::vector<boost::shared_ptr<XdmfItem> >::const_iterator iter = childItems.begin(); iter != childItems.end(); ++iter)
{
if(boost::shared_ptr<XdmfArray> array = boost::shared_dynamic_cast<XdmfArray>(*iter))
{
if(mArray->size() == 0)
{
this->setArray(array);
}
else
{
// Support old Xdmf format that could contain multiple data items. Just append the values to the first array.
if(!mArray->isInitialized())
{
mArray->read();
}
const unsigned int oldSize = mArray->size();
mArray->resize(oldSize + array->size(), 0);
mArray->copyValues(oldSize, array, 0, array->size(), 1, 1);
}
}
}
}
void XdmfDataItem::setArray(const boost::shared_ptr<XdmfArray> array)
{
mArray = array;
}
void XdmfDataItem::traverse(const boost::shared_ptr<XdmfBaseVisitor> visitor) const
{
mArray->accept(visitor);
}
#ifndef XDMFDATAITEM_HPP_
#define XDMFDATAITEM_HPP_
// Forward Declarations
class XdmfArray;
// Includes
#include "XdmfItem.hpp"
/**
* @brief A type of XdmfItem that holds data values in an XdmfArray.
*
* XdmfDataItem is an abstract base class. Any part of the Xdmf graph structure that holds values
* in an XdmfArray inherits from this. XdmfDataItem imbues the ability to store and retrieve XdmfArrays.
*/
class XdmfDataItem : public XdmfItem {
public:
virtual ~XdmfDataItem();
LOKI_DEFINE_VISITABLE(XdmfDataItem, XdmfItem)
/**
* Get the XdmfArray attached to this XdmfDataItem.
*
* @return a smart pointer to the XdmfArray.
*/
boost::shared_ptr<XdmfArray> getArray();
/**
* Get the XdmfArray attached to this XdmfDataItem (const version).
*
* @return a smart pointer to the XdmfArray.
*/
boost::shared_ptr<const XdmfArray> getArray() const;
/**
* Attach an XdmfArray to this XdmfDataItem.
*
* @param array a smart pointer to the XdmfArray.
*/
void setArray(const boost::shared_ptr<XdmfArray> array);
virtual void traverse(const boost::shared_ptr<XdmfBaseVisitor> visitor) const;
protected:
XdmfDataItem();
virtual void populateItem(const std::map<std::string, std::string> & itemProperties, std::vector<boost::shared_ptr<XdmfItem > > & childItems);
private:
XdmfDataItem(const XdmfDataItem & dataItem); // Not implemented.
void operator=(const XdmfDataItem & dataItem); // Not implemented.
boost::shared_ptr<XdmfArray> mArray;
};
#endif /* XDMFDATAITEM_HPP_ */
......@@ -21,6 +21,7 @@ public:
mHDF5Writer(hdf5Writer),
mLightDataLimit(100),
mMode(Default),
mWriteXPaths(true),
mXMLCurrentNode(NULL),
mXMLDocument(NULL),
mXPathCount(0),
......@@ -53,6 +54,7 @@ public:
boost::shared_ptr<XdmfHDF5Writer> mHDF5Writer;
unsigned int mLightDataLimit;
Mode mMode;
bool mWriteXPaths;
xmlNodePtr mXMLCurrentNode;
xmlDocPtr mXMLDocument;
std::string mXMLFilePath;
......@@ -124,13 +126,9 @@ XdmfWriter::Mode XdmfWriter::getMode() const
return mImpl->mMode;
}
void XdmfWriter::moveToLastWrittenNode()
bool XdmfWriter::getWriteXPaths() const
{
mImpl->mXMLCurrentNode = mImpl->mXMLCurrentNode->last;
}
void XdmfWriter::moveToParentNode()
{
mImpl->mXMLCurrentNode = mImpl->mXMLCurrentNode->parent;
return mImpl->mWriteXPaths;
}
void XdmfWriter::setLightDataLimit(const unsigned int numValues)
......@@ -143,8 +141,20 @@ void XdmfWriter::setMode(const Mode mode)
mImpl->mMode = mode;
}
void XdmfWriter::setWriteXPaths(const bool writeXPaths)
{
mImpl->mWriteXPaths = writeXPaths;
}
void XdmfWriter::visit(XdmfArray & array, const boost::shared_ptr<XdmfBaseVisitor> visitor)
{
bool isSubclassed = array.getItemTag().compare(XdmfArray::ItemTag) != 0;
if(isSubclassed)
{
this->visit(dynamic_cast<XdmfItem &>(array), visitor);
}
if(array.size() > 0)
{
std::stringstream xmlTextValues;
......@@ -176,8 +186,24 @@ void XdmfWriter::visit(XdmfArray & array, const boost::shared_ptr<XdmfBaseVisito
xmlTextValues << array.getValuesString();
}
this->visit(dynamic_cast<XdmfItem &>(array), visitor);
xmlAddChild(mImpl->mXMLCurrentNode->last, xmlNewText((xmlChar*)xmlTextValues.str().c_str()));
if(isSubclassed)
{
boost::shared_ptr<XdmfArray> arrayToWrite = XdmfArray::New();
array.swap(arrayToWrite);
mImpl->mXMLCurrentNode = mImpl->mXMLCurrentNode->last;
bool oldWriteXPaths = mImpl->mWriteXPaths;
mImpl->mWriteXPaths = false;
this->visit(dynamic_cast<XdmfItem &>(*arrayToWrite.get()), visitor);
xmlAddChild(mImpl->mXMLCurrentNode->last, xmlNewText((xmlChar*)xmlTextValues.str().c_str()));
mImpl->mXMLCurrentNode = mImpl->mXMLCurrentNode->parent;
mImpl->mWriteXPaths = oldWriteXPaths;
array.swap(arrayToWrite);
}
else
{
this->visit(dynamic_cast<XdmfItem &>(array), visitor);
xmlAddChild(mImpl->mXMLCurrentNode->last, xmlNewText((xmlChar*)xmlTextValues.str().c_str()));
}
}
}
......@@ -188,41 +214,56 @@ void XdmfWriter::visit(XdmfItem & item, const boost::shared_ptr<XdmfBaseVisitor>
mImpl->openFile();
}
mImpl->mXPathCount++;
if(mImpl->mWriteXPaths)
{
mImpl->mXPathCount++;
std::string parentXPathString = mImpl->mXPathString;
std::string parentXPathString = mImpl->mXPathString;
std::stringstream newXPathString;
newXPathString << mImpl->mXPathString << "/" << mImpl->mXPathCount;
mImpl->mXPathString = newXPathString.str();
std::stringstream newXPathString;
newXPathString << mImpl->mXPathString << "/" << mImpl->mXPathCount;
mImpl->mXPathString = newXPathString.str();
std::map<const XdmfItem * const, std::string>::const_iterator iter = mImpl->mXPath.find(&item);
if(iter != mImpl->mXPath.end())
{
// Inserted before --- just xpath location of previously written node
mImpl->mXMLCurrentNode = xmlNewChild(mImpl->mXMLCurrentNode, NULL, (xmlChar*)"xi:include", NULL);
xmlNewProp(mImpl->mXMLCurrentNode, (xmlChar*)"xpointer", (xmlChar*)iter->second.c_str());
std::map<const XdmfItem * const, std::string>::const_iterator iter = mImpl->mXPath.find(&item);
if(iter != mImpl->mXPath.end())
{
// Inserted before --- just xpath location of previously written node
mImpl->mXMLCurrentNode = xmlNewChild(mImpl->mXMLCurrentNode, NULL, (xmlChar*)"xi:include", NULL);
xmlNewProp(mImpl->mXMLCurrentNode, (xmlChar*)"xpointer", (xmlChar*)iter->second.c_str());
}
else
{
// Not inserted before --- need to write all data and traverse.
mImpl->mXMLCurrentNode = xmlNewChild(mImpl->mXMLCurrentNode, NULL, (xmlChar*)item.getItemTag().c_str(), NULL);
std::stringstream xPathProp;
xPathProp << "element(/1" << mImpl->mXPathString << ")";
mImpl->mXPath[&item] = xPathProp.str();
const std::map<std::string, std::string> itemProperties = item.getItemProperties();
for(std::map<std::string, std::string>::const_iterator iter = itemProperties.begin(); iter != itemProperties.end(); ++iter)
{
xmlNewProp(mImpl->mXMLCurrentNode, (xmlChar*)iter->first.c_str(), (xmlChar*)iter->second.c_str());
}
unsigned int parentCount = mImpl->mXPathCount;
mImpl->mXPathCount = 0;
item.traverse(visitor);
mImpl->mXPathCount = parentCount;
}
mImpl->mXPathString = parentXPathString;
}
else
{
// Not inserted before --- need to write all data and traverse.
mImpl->mXMLCurrentNode = xmlNewChild(mImpl->mXMLCurrentNode, NULL, (xmlChar*)item.getItemTag().c_str(), NULL);
std::stringstream xPathProp;
xPathProp << "element(/1" << mImpl->mXPathString << ")";
mImpl->mXPath[&item] = xPathProp.str();
const std::map<std::string, std::string> itemProperties = item.getItemProperties();
for(std::map<std::string, std::string>::const_iterator iter = itemProperties.begin(); iter != itemProperties.end(); ++iter)
{
xmlNewProp(mImpl->mXMLCurrentNode, (xmlChar*)iter->first.c_str(), (xmlChar*)iter->second.c_str());
}
unsigned int parentCount = mImpl->mXPathCount;
mImpl->mXPathCount = 0;
item.traverse(visitor);
mImpl->mXPathCount = parentCount;
}
this->moveToParentNode();
mImpl->mXPathString = parentXPathString;
mImpl->mXMLCurrentNode = mImpl->mXMLCurrentNode->parent;
if(mImpl->mXPathString.compare("") == 0)
{
......
......@@ -80,6 +80,13 @@ public:
*/
unsigned int getLightDataLimit() const;
/**
* Get whether this writer is set to write xpaths.
*
* @return bool whether this writer is set to write xpaths.
*/
bool getWriteXPaths() const;
/**
* Get the Mode of operation for this writer.
*
......@@ -101,6 +108,13 @@ public:
*/
void setMode(const Mode mode);
/**
* Set whether to write xpaths for this writer.
*
* @param writeXPaths, whether to write xpaths for this writer.
*/
void setWriteXPaths(const bool writeXPaths = true);
/**
* Write an XdmfArray to disk
*
......@@ -123,9 +137,6 @@ protected:
XdmfWriter(const std::string & xmlFilePath);
XdmfWriter(const std::string & xmlFilePath, boost::shared_ptr<XdmfHDF5Writer> hdf5Writer);
void moveToLastWrittenNode();
void moveToParentNode();
private:
/**
......
......@@ -11,15 +11,15 @@ int main(int argc, char* argv[])
// First write and release heavy data
boost::shared_ptr<XdmfHDF5Writer> hdf5Writer = XdmfHDF5Writer::New("output.h5");
grid->getGeometry()->accept(hdf5Writer);
grid->getGeometry()->getArray()->release();
grid->getGeometry()->release();
grid->getTopology()->accept(hdf5Writer);
grid->getTopology()->getArray()->release();
grid->getTopology()->release();
for(int i=0; i<grid->getNumberAttributes(); ++i)
{
grid->getAttribute(i)->accept(hdf5Writer);
grid->getAttribute(i)->getArray()->release();
grid->getAttribute(i)->release();
}
// Now insert into domain and write light data
......
......@@ -34,13 +34,13 @@ public:
double points[] = {0.1, 0.1, 1.1, 1.1, 0.1, 1.1, 3.1, 0.1, 2.1, 0.1, 1.1, 1.1, 1.1, 1.1, 1.1, 3.1, 2.1, 2.1,
0.1, 0.1, -1.1, 1.1, 0.1, -1.1, 3.1, 0.1, -2.1, 0.1, 1.1, -1.1, 1.1, 1.1, -1.1, 3.1, 2.1, -2.1};
grid->getGeometry()->setType(XdmfGeometryType::XYZ());
grid->getGeometry()->getArray()->copyValues(0, &points[0], 36);
grid->getGeometry()->getArray()->setName("Geom 1");
grid->getGeometry()->copyValues(0, &points[0], 36);
//grid->getGeometry()->setName("Geom 1");
// Set Topology
int connectivity[] = {0, 1, 7, 6, 3, 4, 10, 9, 1, 2, 8, 7, 4, 5, 11, 10};
grid->getTopology()->setType(XdmfTopologyType::Hexahedron());
grid->getTopology()->getArray()->copyValues(0, &connectivity[0], 16);
grid->getTopology()->copyValues(0, &connectivity[0], 16);
// Add Node Attribute
boost::shared_ptr<XdmfAttribute> nodalAttribute = XdmfAttribute::New();
......@@ -48,7 +48,7 @@ public:
nodalAttribute->setName("Nodal Attribute");
nodalAttribute->setType(XdmfAttributeType::Scalar());
nodalAttribute->setCenter(XdmfAttributeCenter::Node());
nodalAttribute->getArray()->copyValues(0, &nodeValues[0], 12);
nodalAttribute->copyValues(0, &nodeValues[0], 12);
// Add Cell Attribute
boost::shared_ptr<XdmfAttribute> cellAttribute = XdmfAttribute::New();
......@@ -56,7 +56,7 @@ public:
cellAttribute->setName("Cell Attribute");
cellAttribute->setType(XdmfAttributeType::Scalar());
cellAttribute->setCenter(XdmfAttributeCenter::Cell());
cellAttribute->getArray()->copyValues(0, &cellValues[0], 2);
cellAttribute->copyValues(0, &cellValues[0], 2);
// Add Node Set
boost::shared_ptr<XdmfSet> nodeSet = XdmfSet::New();
......@@ -65,7 +65,7 @@ public:
nodeSet->setType(XdmfSetType::Node());
nodeSet->insert(nodeIds, nodeIds + 3);
// Add time
// Add Time
boost::shared_ptr<XdmfTime> time = XdmfTime::New(100);
grid->setTime(time);
......
......@@ -10,7 +10,6 @@ swig -v -c++ -python -o XdmfUtilsPython.cpp XdmfUtils.i
#include <XdmfArrayType.hpp>
#include <XdmfCoreItemFactory.hpp>
#include <XdmfCoreReader.hpp>
#include <XdmfDataItem.hpp>
#include <XdmfHDF5Controller.hpp>
#include <XdmfHDF5Writer.hpp>
#include <XdmfInformation.hpp>
......
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