Commit ab73bf69 authored by Kenneth Leiter's avatar Kenneth Leiter
Browse files

ENH: Add XdmfExodusWriter to utils.

parent 906019df
......@@ -8,6 +8,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake ${CMAKE_CURRENT_SOURCE_D
add_subdirectory(core)
include_directories(${XdmfCore_INCLUDE_DIRS})
include_directories(tests/Cxx)
set(XdmfSources
XdmfAttribute
......
......@@ -282,19 +282,19 @@ void XdmfGrid::setTopology(const boost::shared_ptr<XdmfTopology> topology)
void XdmfGrid::traverse(const boost::shared_ptr<XdmfBaseVisitor> visitor)
{
if(mTime != NULL)
if(mTime)
{
mTime->accept(visitor);
}
if(mGeometry != NULL)
if(mGeometry)
{
mGeometry->accept(visitor);
}
if(mTopology != NULL)
if(mTopology)
{
mTopology->accept(visitor);
}
if(mMap != NULL)
if(mMap)
{
mMap->accept(visitor);
}
......
......@@ -265,7 +265,9 @@ protected:
XdmfGrid();
virtual void populateItem(const std::map<std::string, std::string> & itemProperties, std::vector<boost::shared_ptr<XdmfItem> > & childItems);
boost::shared_ptr<XdmfGeometry> mGeometry;
std::string mName;
boost::shared_ptr<XdmfTopology> mTopology;
private:
......@@ -273,11 +275,9 @@ private:
void operator=(const XdmfGrid & grid); // Not implemented.
std::vector<boost::shared_ptr<XdmfAttribute> > mAttributes;
boost::shared_ptr<XdmfGeometry> mGeometry;
boost::shared_ptr<XdmfMap> mMap;
std::vector<boost::shared_ptr<XdmfSet> > mSets;
boost::shared_ptr<XdmfTime> mTime;
boost::shared_ptr<XdmfTopology> mTopology;
};
#endif /* XDMFGRID_HPP_ */
......@@ -15,9 +15,12 @@ boost::shared_ptr<XdmfGridCollection> XdmfGridCollection::New()
};
XdmfGridCollection::XdmfGridCollection() :
XdmfGrid(),
mCollectionType(XdmfGridCollectionType::NoCollectionType())
{
mGeometry = boost::shared_ptr<XdmfGeometry>();
mName = "Collection";
mTopology = boost::shared_ptr<XdmfTopology>();
}
XdmfGridCollection::~XdmfGridCollection()
......
......@@ -28,7 +28,7 @@ boost::shared_ptr<XdmfItem> XdmfItemFactory::createItem(const std::string & item
{
boost::shared_ptr<XdmfItem> newItem = XdmfCoreItemFactory::createItem(itemTag, itemProperties);
if(newItem != NULL)
if(newItem)
{
return newItem;
}
......
......@@ -189,7 +189,7 @@ void XdmfMap::populateItem(const std::map<std::string, std::string> & itemProper
void XdmfMap::read()
{
if(mImpl->mLocalNodeIdsHDF5Controller != NULL && mImpl->mRemoteTaskIdsHDF5Controller != NULL && mImpl->mRemoteLocalNodeIdsHDF5Controller != NULL)
if(mImpl->mLocalNodeIdsHDF5Controller && mImpl->mRemoteTaskIdsHDF5Controller && mImpl->mRemoteLocalNodeIdsHDF5Controller)
{
assert(mImpl->mLocalNodeIdsHDF5Controller->size() == mImpl->mRemoteTaskIdsHDF5Controller->size() && mImpl->mLocalNodeIdsHDF5Controller->size() == mImpl->mRemoteLocalNodeIdsHDF5Controller->size());
boost::shared_ptr<XdmfArray> globalNodeIds = XdmfArray::New();
......
......@@ -164,7 +164,7 @@ boost::shared_ptr<std::vector<T> > XdmfArray::getValues()
boost::shared_ptr<std::vector<T> > currArray = boost::get<boost::shared_ptr<std::vector<T> > >(mArray);
return currArray;
}
catch(const boost::bad_get& exception)
catch(const boost::bad_get & exception)
{
return boost::shared_ptr<std::vector<T> >();
}
......
......@@ -14,7 +14,7 @@ if(XDMF_BUILD_EXODUS_IO)
if(EXODUS_FOUND)
include_directories(${EXODUS_INCLUDE_DIR} ${NetCDF_INCLUDE_DIR})
endif(EXODUS_FOUND)
set(XdmfUtilsSources ${XdmfUtilsSources} XdmfExodusReader)
set(XdmfUtilsSources ${XdmfUtilsSources} XdmfExodusReader XdmfExodusWriter)
set(XdmfUtilsLinkLibraries ${XdmfUtilsLinkLibraries} ${EXODUS_LIBRARIES} ${NetCDF_LIBRARIES})
endif(XDMF_BUILD_EXODUS_IO)
......
/*******************************************************************/
/* XDMF */
/* eXtensible Data Model and Format */
/* */
/* Id : Id */
/* Date : $Date$ */
/* Version : $Revision$ */
/* */
/* Author: */
/* Kenneth Leiter */
/* kenneth.leiter@arl.army.mil */
/* US Army Research Laboratory */
/* Aberdeen Proving Ground, MD */
/* */
/* Copyright @ 2009 US Army Research Laboratory */
/* All Rights Reserved */
/* See Copyright.txt or http://www.arl.hpc.mil/ice for details */
/* */
/* This software is distributed WITHOUT ANY WARRANTY; without */
/* even the implied warranty of MERCHANTABILITY or FITNESS */
/* FOR A PARTICULAR PURPOSE. See the above copyright notice */
/* for more information. */
/* */
/*******************************************************************/
#include <exodusII.h>
#include "XdmfArrayType.hpp"
#include "XdmfAttribute.hpp"
......@@ -71,6 +46,7 @@ boost::shared_ptr<XdmfGrid> XdmfExodusReader::read(const std::string & fileName,
char * title = new char[MAX_LINE_LENGTH+1];
int num_dim, num_nodes, num_elem, num_elem_blk, num_node_sets, num_side_sets;
ex_get_init (exodusHandle, title, &num_dim, &num_nodes, &num_elem, &num_elem_blk, &num_node_sets, &num_side_sets);
toReturn->setName(title);
delete [] title;
/*
......@@ -180,7 +156,7 @@ boost::shared_ptr<XdmfGrid> XdmfExodusReader::read(const std::string & fileName,
int elemIndex = 0;
for(unsigned int i=0; i<num_elem_blk; ++i)
{
ex_get_elem_conn(exodusHandle, blockIds[i], &connectivityPointer[elemIndex]);
ex_get_elem_conn(exodusHandle, blockIds[i], connectivityPointer + elemIndex);
elemIndex += numElemsInBlock[i] * numNodesPerElemInBlock[i];
}
......@@ -447,8 +423,8 @@ boost::shared_ptr<XdmfGrid> XdmfExodusReader::read(const std::string & fileName,
elemIndex = 0;
for (unsigned int j=0; j<num_elem_blk; ++j)
{
ex_get_elem_var(exodusHandle, 1, i+1, blockIds[j], numElemsInBlock[i], &((double*)attribute->getValuesPointer())[elemIndex]);
elemIndex = elemIndex + numElemsInBlock[i];
ex_get_elem_var(exodusHandle, 1, i+1, blockIds[j], numElemsInBlock[j], (double*)attribute->getValuesPointer() + elemIndex);
elemIndex += numElemsInBlock[j];
}
toReturn->insert(attribute);
if(heavyDataWriter)
......
#include <exodusII.h>
#include <sstream>
#include "XdmfArrayType.hpp"
#include "XdmfAttribute.hpp"
#include "XdmfAttributeCenter.hpp"
#include "XdmfExodusWriter.hpp"
#include "XdmfGeometry.hpp"
#include "XdmfGeometryType.hpp"
#include "XdmfGrid.hpp"
#include "XdmfGridCollection.hpp"
#include "XdmfGridCollectionType.hpp"
#include "XdmfSet.hpp"
#include "XdmfSetType.hpp"
#include "XdmfTopology.hpp"
#include "XdmfTopologyType.hpp"
/**
* PIMPL
*/
class XdmfExodusWriter::XdmfExodusWriterImpl {
public:
XdmfExodusWriterImpl()
{
};
~XdmfExodusWriterImpl()
{
};
/**
* Constructs attribute names for ExodusII files since exodus cannot store vectors. Deals with MAX_STR_LENGTH
* limitation.
*
* @param attributeName the attribute name in Xdmf.
* @param names a vector of names to add the constructed attribute names to.
* @param numComponents the number of components in the attribute (e.g. for an xyz vector this is 3)
*/
void constructAttributeNames(std::string attributeName, std::vector<std::string> & names, const int numComponents)
{
if(numComponents == 1)
{
if(attributeName.length() > MAX_STR_LENGTH)
{
attributeName = attributeName.substr(0, MAX_STR_LENGTH);
}
names.push_back(attributeName);
}
else if(numComponents > 1)
{
int numComponentDigits = int(numComponents / 10);
if(attributeName.length() + numComponentDigits > MAX_STR_LENGTH)
{
attributeName = attributeName.substr(0, MAX_STR_LENGTH - numComponentDigits);
}
for(unsigned int i=0; i<numComponents; ++i)
{
std::stringstream toAdd;
toAdd << attributeName << "-" << i+1;
names.push_back(toAdd.str());
}
}
}
};
boost::shared_ptr<XdmfExodusWriter> XdmfExodusWriter::New()
{
boost::shared_ptr<XdmfExodusWriter> p(new XdmfExodusWriter());
return p;
}
XdmfExodusWriter::XdmfExodusWriter() :
mImpl(new XdmfExodusWriterImpl())
{
}
XdmfExodusWriter::~XdmfExodusWriter()
{
delete mImpl;
}
void XdmfExodusWriter::write(const std::string & filePath, const boost::shared_ptr<XdmfGrid> gridToWrite) const
{
// Open Exodus File
int wordSize = 8;
int storeSize = 8;
int exodusHandle = ex_create(filePath.c_str(), EX_CLOBBER, &wordSize, &storeSize);
// Initialize Exodus File
std::string title = gridToWrite->getName();
if(title.size() > MAX_STR_LENGTH)
{
title = title.substr(0, MAX_STR_LENGTH);
}
boost::shared_ptr<XdmfGridCollection> gridCollection = boost::shared_ptr<XdmfGridCollection>();
boost::shared_ptr<XdmfGrid> currGrid = gridToWrite;
// Check if they are temporal collections and use the first grid to determine geometry and topology.
if(boost::shared_ptr<XdmfGridCollection> tmpGrid = boost::shared_dynamic_cast<XdmfGridCollection>(gridToWrite))
{
if(tmpGrid->getType() == XdmfGridCollectionType::Temporal() && tmpGrid->getNumberGrids() > 0)
{
currGrid = tmpGrid->getGrid(0);
gridCollection = tmpGrid;
}
else
{
// Only Temporal Collections are currently supported.
assert(false);
}
}
else
{
// This is expected to fail when we've already found a grid.
}
// Make sure geometry and topology are non null
assert(currGrid->getGeometry() && currGrid->getTopology());
int num_dim = currGrid->getGeometry()->getType()->getDimensions();
int num_nodes = currGrid->getGeometry()->getNumberPoints();
int num_elem = currGrid->getTopology()->getNumberElements();
int num_elem_blk = 1;
int num_node_sets = 0;
int num_side_sets = 0;
for (unsigned int i=0; i<currGrid->getNumberSets(); ++i)
{
if(currGrid->getSet(i)->getType() == XdmfSetType::Cell())
{
num_side_sets++;
}
else if(currGrid->getSet(i)->getType() == XdmfSetType::Node())
{
num_node_sets++;
}
}
ex_put_init(exodusHandle, title.c_str(), num_dim, num_nodes, num_elem, num_elem_blk, num_node_sets, num_side_sets);
double * x = new double[num_nodes];
double * y = new double[num_nodes];
double * z = new double[num_nodes];
// Write nodal coordinate values to exodus
if(currGrid->getGeometry()->getType() == XdmfGeometryType::XYZ() || currGrid->getGeometry()->getType() == XdmfGeometryType::XY())
{
currGrid->getGeometry()->getValuesCopy(0, x, num_nodes, 3);
currGrid->getGeometry()->getValuesCopy(1, y, num_nodes, 3);
if(currGrid->getGeometry()->getType() == XdmfGeometryType::XYZ())
{
currGrid->getGeometry()->getValuesCopy(2, z, num_nodes, 3);
}
ex_put_coord(exodusHandle, x ,y ,z);
}
else if(currGrid->getGeometry()->getType() == XdmfGeometryType::X_Y_Z() || currGrid->getGeometry()->getType() == XdmfGeometryType::X_Y())
{
currGrid->getGeometry()->getValuesCopy(0, x, num_nodes);
currGrid->getGeometry()->getValuesCopy(num_nodes, y, num_nodes);
if(currGrid->getGeometry()->getType() == XdmfGeometryType::X_Y_Z())
{
currGrid->getGeometry()->getValuesCopy(num_nodes * 2, z, num_nodes);
}
}
delete [] x;
delete [] y;
delete [] z;
// Write Element block parameters
std::string exodusTopologyType = this->xdmfToExodusTopologyType(currGrid->getTopology()->getType());
if (exodusTopologyType.compare("") == 0)
{
// Topology Type not supported by ExodusII
assert(false);
}
ex_put_elem_block(exodusHandle, 10, exodusTopologyType.c_str(), num_elem, currGrid->getTopology()->getType()->getNodesPerElement(), num_side_sets);
// Write Element Connectivity
int * elem_connectivity = new int[num_elem * currGrid->getTopology()->getType()->getNodesPerElement()];
currGrid->getTopology()->getValuesCopy(0, elem_connectivity, num_elem * currGrid->getTopology()->getType()->getNodesPerElement());
for(unsigned int i=0; i<num_elem * currGrid->getTopology()->getType()->getNodesPerElement(); ++i)
{
// Add 1 to connectivity array since exodus indices start at 1
elem_connectivity[i]++;
}
if(currGrid->getTopology()->getType() == XdmfTopologyType::Hexahedron_20() || currGrid->getTopology()->getType() == XdmfTopologyType::Hexahedron_27())
{
int * ptr = elem_connectivity;
int itmp[4];
// Exodus Node ordering does not match Xdmf, we must convert.
for(unsigned int i=0; i<num_elem; ++i)
{
ptr += 12;
for (unsigned int j=0; j<4; ++j, ++ptr)
{
itmp[j] = *ptr;
*ptr = ptr[4];
}
for(unsigned int j=0; j<4; ++j, ++ptr)
{
*ptr = itmp[j];
}
if(currGrid->getTopology()->getType() == XdmfTopologyType::Hexahedron_27())
{
itmp[0] = *ptr;
*(ptr++) = ptr[6];
itmp[1] = *ptr;
*(ptr++) = ptr[3];
itmp[2] = *ptr;
*(ptr++) = ptr[3];
itmp[3] = *ptr;
for (unsigned int j=0; j<4; ++j, ++ptr)
{
*ptr = itmp[j];
}
}
}
}
else if(currGrid->getTopology()->getType() == XdmfTopologyType::Wedge_15() || currGrid->getTopology()->getType() == XdmfTopologyType::Wedge_18())
{
int * ptr = elem_connectivity;
int itmp[3];
// Exodus Node ordering does not match Xdmf, we must convert.
for(unsigned int i=0; i<num_elem; ++i)
{
ptr += 9;
for(unsigned int j=0; j<3; ++j, ++ptr)
{
itmp[j] = *ptr;
*ptr = ptr[3];
}
for(unsigned int j=0; j<3; ++j, ++ptr)
{
*ptr = itmp[j];
}
if(currGrid->getTopology()->getType() == XdmfTopologyType::Wedge_18())
{
itmp[0] = *(ptr);
itmp[1] = *(ptr+1);
itmp[2] = *(ptr+2);
*(ptr++) = itmp[2];
*(ptr++) = itmp[0];
*(ptr++) = itmp[1];
}
}
}
ex_put_elem_conn(exodusHandle, 10, elem_connectivity);
delete [] elem_connectivity;
// Write Attributes
int numGlobalAttributes = 0;
int numNodalAttributes = 0;
int numElementAttributes = 0;
std::vector<int> globalComponents;
std::vector<int> nodalComponents;
std::vector<int> elementComponents;
std::vector<std::string> globalAttributeNames;
std::vector<std::string> nodalAttributeNames;
std::vector<std::string> elementAttributeNames;
for(unsigned int i=0; i<currGrid->getNumberAttributes(); ++i)
{
boost::shared_ptr<XdmfAttribute> currAttribute = currGrid->getAttribute(i);
if(currAttribute->getCenter() == XdmfAttributeCenter::Grid())
{
int numComponents = currAttribute->size();
globalComponents.push_back(numComponents);
numGlobalAttributes += numComponents;
mImpl->constructAttributeNames(currAttribute->getName(), globalAttributeNames, numComponents);
}
else if(currAttribute->getCenter() == XdmfAttributeCenter::Node())
{
int numComponents = currAttribute->size() / num_nodes;
nodalComponents.push_back(numComponents);
numNodalAttributes += numComponents;
mImpl->constructAttributeNames(currAttribute->getName(), nodalAttributeNames, numComponents);
}
else if(currAttribute->getCenter() == XdmfAttributeCenter::Cell())
{
int numComponents = currAttribute->size() / num_elem;
elementComponents.push_back(numComponents);
numElementAttributes += numComponents;
mImpl->constructAttributeNames(currAttribute->getName(), elementAttributeNames, numComponents);
}
}
ex_put_var_param(exodusHandle, "g", numGlobalAttributes);
ex_put_var_param(exodusHandle, "n", numNodalAttributes);
ex_put_var_param(exodusHandle, "e", numElementAttributes);
char ** globalNames = new char*[numGlobalAttributes];
char ** nodalNames = new char*[numNodalAttributes];
char ** elementNames = new char*[numElementAttributes];
for(int i=0; i<numGlobalAttributes; ++i)
{
globalNames[i] = (char*)globalAttributeNames[i].c_str();
}
for(int i=0; i<numNodalAttributes; ++i)
{
nodalNames[i] = (char*)nodalAttributeNames[i].c_str();
}
for(int i=0; i<numElementAttributes; ++i)
{
elementNames[i] = (char*)elementAttributeNames[i].c_str();
}
ex_put_var_names(exodusHandle, "g", numGlobalAttributes, globalNames);
ex_put_var_names(exodusHandle, "n", numNodalAttributes, nodalNames);
ex_put_var_names(exodusHandle, "e", numElementAttributes, elementNames);
delete [] globalNames;
delete [] nodalNames;
delete [] elementNames;
int numGrids = 1;
if(gridCollection)
{
numGrids = gridCollection->getNumberGrids();
}
for(unsigned int i=0; i<numGrids; ++i)
{
double * globalAttributeVals = new double[numGlobalAttributes];
int globalIndex = 0;
int globalComponentIndex = 0;
int nodalIndex = 0;
int nodalComponentIndex = 0;
int elementIndex = 0;
int elementComponentIndex = 0;
if(gridCollection)
{
currGrid = gridCollection->getGrid(i);
}
for(unsigned int j=0; j<currGrid->getNumberAttributes(); ++j)
{
boost::shared_ptr<XdmfAttribute> currAttribute = currGrid->getAttribute(j);
if(currAttribute->getCenter() == XdmfAttributeCenter::Grid())
{
for(unsigned int k=0; k<globalComponents[globalComponentIndex]; ++k)
{
currAttribute->getValuesCopy(k, globalAttributeVals + globalIndex, 1);
globalIndex++;
}
globalComponentIndex++;
}
else if(currAttribute->getCenter() == XdmfAttributeCenter::Node())
{
for(unsigned int k=0; k<nodalComponents[nodalComponentIndex]; ++k)
{
double * nodalValues = new double[num_nodes];
currAttribute->getValuesCopy(k, nodalValues, num_nodes, nodalComponents[nodalComponentIndex]);
ex_put_nodal_var(exodusHandle, i+1, nodalIndex+1, num_nodes, nodalValues);
ex_update(exodusHandle);
delete [] nodalValues;
nodalIndex++;
}
nodalComponentIndex++;
}
else if(currAttribute->getCenter() == XdmfAttributeCenter::Cell())
{
for(unsigned int k=0; k<elementComponents[elementComponentIndex]; ++k)
{
double * elementValues = new double[num_elem];
currAttribute->getValuesCopy(k, elementValues, num_elem, elementComponents[elementComponentIndex]);
ex_put_elem_var(exodusHandle, i+1, elementIndex+1, 10, num_elem, elementValues);
ex_update(exodusHandle);
delete [] elementValues;
elementIndex++;
}
elementComponentIndex++;
}
}
ex_put_glob_vars(exodusHandle, i+1, numGlobalAttributes, globalAttributeVals);
ex_update(exodusHandle);
delete [] globalAttributeVals;
// Write Sets
int setId = 20;
for(unsigned int j=0; j<currGrid->getNumberSets(); ++j)
{
boost::shared_ptr<XdmfSet> currSet = currGrid->getSet(j);
int numValues = currSet->size();
std::string name = currSet->getName();
if(name.size() > MAX_STR_LENGTH)
{
name = name.substr(0, MAX_STR_LENGTH);
}
if(currSet->getType() == XdmfSetType::Cell())
{
ex_put_side_set_param(exodusHandle, setId + i, numValues, 0);
int * values = new int[numValues];
unsigned int k=0;
for(XdmfSet::const_iterator iter = currSet->begin(); iter != currSet->end(); ++iter, ++k)
{
// Add 1 to xdmf ids because exodus ids begin at 1
values[k] = *iter + 1;
}
ex_put_side_set(exodusHandle, setId + i, values, NULL);
ex_put_name(exodusHandle, EX_SIDE_SET, setId + i, name.c_str());
delete [] values;
}
else if(currSet->getType() == XdmfSetType::Node())
{
ex_put_node_set_param(exodusHandle, setId + i, numValues, 0);
int * values = new int[numValues];
unsigned int k=0;
for(XdmfSet::const_iterator iter = currSet->begin(); iter != currSet->end(); ++iter, ++k)
{
// Add 1 to xdmf ids because exodus ids begin at 1
values[k] = *iter + 1;
}
ex_put_node_set(exodusHandle, setId + i, values);
ex_put_name(exodusHandle, EX_NODE_SET, setId + i, name.c_str());
delete [] values;
}
}
}
// Close Exodus File
ex_close(exodusHandle);