Commit a6be5bff authored by Kenneth Leiter's avatar Kenneth Leiter

BUG: Fix incorrect getNumberElements() in XdmfTopology when Mixed topology

type is specified. Previously, for mixed topology types, this would return
0.0. This would result in unreadable xdmf files being written to disk.

For mixed topology types, the function now examines the connectivity table
and parses topology type ids to count the number of elements. An improved
comment was added to XdmfTopology to explain how mixed topologies are stored.
A test for mixed topologies was also added, dealing with a quadrilateral and
a polyline in 2D.
parent 86ae3272
......@@ -22,6 +22,7 @@
/*****************************************************************************/
#include <sstream>
#include "XdmfError.hpp"
#include "XdmfTopology.hpp"
#include "XdmfTopologyType.hpp"
......@@ -66,7 +67,43 @@ XdmfTopology::getItemProperties() const
unsigned int
XdmfTopology::getNumberElements() const
{
// deal with special cases first (mixed / no topology)
if(mType->getNodesPerElement() == 0) {
if(mType == XdmfTopologyType::Mixed()) {
unsigned int index = 0;
unsigned int numberElements = 0;
// iterate over all values in connectivity, pulling topology type ids
// and counting number of elements
while(index < this->getSize()) {
const unsigned int id = this->getValue<unsigned int>(index);
const boost::shared_ptr<const XdmfTopologyType> topologyType =
XdmfTopologyType::New(id);
if(topologyType == NULL) {
XdmfError::message(XdmfError::FATAL,
"Invalid topology type id found in connectivity "
"when parsing mixed topology.");
}
if(topologyType == XdmfTopologyType::Polyvertex()) {
const unsigned int numberPolyvertexElements =
this->getValue<unsigned int>(index + 1);
numberElements += numberPolyvertexElements;
index += numberPolyvertexElements + 2;
}
else if(topologyType == XdmfTopologyType::Polyline() ||
topologyType == XdmfTopologyType::Polygon(0)) {
const unsigned int numberNodes =
this->getValue<unsigned int>(index + 1);
numberElements += 1;
index += numberNodes + 2;
}
else {
// add 1 to element count and move to next element id
numberElements += 1;
index += topologyType->getNodesPerElement() + 1;
}
}
return numberElements;
}
return 0;
}
return this->getSize() / mType->getNodesPerElement();
......
......@@ -38,6 +38,19 @@ class XdmfTopologyType;
* connectivity information for all points contained in an
* XdmfGrid. XdmfTopology contains an XdmfTopologyType property which
* should be set that specifies the element type stored.
*
* In the case of mixed topology types, the connectivity stores
* topology type ids prior to each element's connectivity
* information. For element types of varying sizes (Polyvertex,
* Polyline, and Polygon), the topology type id is followed by a
* number specifying the number of nodes in the element. For example,
* a tetrahedron element (id 6) followed by a polygon element (id 3)
* with 5 points would look similar the following:
*
* 6 20 25 100 200 3 5 300 301 302 303 304
*
* The tetrahedron is composed of nodes 20, 25, 100, and 200. The
* polygon is composed of nodes 300 to 304.
*/
class XDMF_EXPORT XdmfTopology : public XdmfArray {
......
......@@ -23,8 +23,8 @@
#include <cctype>
#include <sstream>
#include "XdmfTopologyType.hpp"
#include "XdmfError.hpp"
#include "XdmfTopologyType.hpp"
// Supported XdmfTopologyTypes
boost::shared_ptr<const XdmfTopologyType>
......@@ -243,6 +243,90 @@ XdmfTopologyType::Mixed()
return p;
}
boost::shared_ptr<const XdmfTopologyType>
XdmfTopologyType::New(const unsigned int id)
{
if(id == XdmfTopologyType::NoTopologyType()->getID()) {
return XdmfTopologyType::NoTopologyType();
}
else if(id == XdmfTopologyType::Polyvertex()->getID()) {
return XdmfTopologyType::Polyvertex();
}
else if(id == XdmfTopologyType::Polyline()->getID()) {
return XdmfTopologyType::Polyline();
}
else if(id == XdmfTopologyType::Polygon(0)->getID()) {
return XdmfTopologyType::Polygon(0);
}
else if(id == XdmfTopologyType::Triangle()->getID()) {
return XdmfTopologyType::Triangle();
}
else if(id == XdmfTopologyType::Quadrilateral()->getID()) {
return XdmfTopologyType::Quadrilateral();
}
else if(id == XdmfTopologyType::Tetrahedron()->getID()) {
return XdmfTopologyType::Tetrahedron();
}
else if(id == XdmfTopologyType::Pyramid()->getID()) {
return XdmfTopologyType::Pyramid();
}
else if(id == XdmfTopologyType::Wedge()->getID()) {
return XdmfTopologyType::Wedge();
}
else if(id == XdmfTopologyType::Hexahedron()->getID()) {
return XdmfTopologyType::Hexahedron();
}
else if(id == XdmfTopologyType::Edge_3()->getID()) {
return XdmfTopologyType::Edge_3();
}
else if(id == XdmfTopologyType::Triangle_6()->getID()) {
return XdmfTopologyType::Triangle_6();
}
else if(id == XdmfTopologyType::Quadrilateral_8()->getID()) {
return XdmfTopologyType::Quadrilateral_8();
}
else if(id == XdmfTopologyType::Quadrilateral_9()->getID()) {
return XdmfTopologyType::Quadrilateral_9();
}
else if(id == XdmfTopologyType::Tetrahedron_10()->getID()) {
return XdmfTopologyType::Tetrahedron_10();
}
else if(id == XdmfTopologyType::Pyramid_13()->getID()) {
return XdmfTopologyType::Pyramid_13();
}
else if(id == XdmfTopologyType::Wedge_15()->getID()) {
return XdmfTopologyType::Wedge_15();
}
else if(id == XdmfTopologyType::Wedge_18()->getID()) {
return XdmfTopologyType::Wedge_18();
}
else if(id == XdmfTopologyType::Hexahedron_20()->getID()) {
return XdmfTopologyType::Hexahedron_20();
}
else if(id == XdmfTopologyType::Hexahedron_24()->getID()) {
return XdmfTopologyType::Hexahedron_24();
}
else if(id == XdmfTopologyType::Hexahedron_27()->getID()) {
return XdmfTopologyType::Hexahedron_27();
}
else if(id == XdmfTopologyType::Hexahedron_64()->getID()) {
return XdmfTopologyType::Hexahedron_64();
}
else if(id == XdmfTopologyType::Hexahedron_64_GLL()->getID()) {
return XdmfTopologyType::Hexahedron_64_GLL();
}
else if(id == XdmfTopologyType::Hexahedron_125()->getID()) {
return XdmfTopologyType::Hexahedron_125();
}
else if(id == XdmfTopologyType::Hexahedron_125_GLL()->getID()) {
return XdmfTopologyType::Hexahedron_125_GLL();
}
else if(id == XdmfTopologyType::Mixed()->getID()) {
return XdmfTopologyType::Mixed();
}
return boost::shared_ptr<const XdmfTopologyType>();
}
XdmfTopologyType::XdmfTopologyType(const unsigned int nodesPerElement,
const std::string & name,
const CellType cellType,
......
......@@ -82,7 +82,9 @@ class XDMF_EXPORT XdmfTopologyType : public XdmfItemProperty {
Structured
};
// Supported Xdmf Topology Types
/**
* Supported Xdmf Topology Types
*/
static boost::shared_ptr<const XdmfTopologyType> NoTopologyType();
static boost::shared_ptr<const XdmfTopologyType> Polyvertex();
static boost::shared_ptr<const XdmfTopologyType> Polyline();
......@@ -111,6 +113,16 @@ class XDMF_EXPORT XdmfTopologyType : public XdmfItemProperty {
static boost::shared_ptr<const XdmfTopologyType> Hexahedron_125_GLL();
static boost::shared_ptr<const XdmfTopologyType> Mixed();
/**
* Get a topology type from id.
*
* @param id of the topology type.
*
* @return topology type corresponding to id - if no topology type is found
* an NULL pointer is returned.
*/
static boost::shared_ptr<const XdmfTopologyType> New(const unsigned int id);
/**
* Get the cell type associated with this topology type.
*
......
......@@ -21,6 +21,7 @@ ADD_TEST_CXX(TestXdmfRectilinearGrid)
ADD_TEST_CXX(TestXdmfSet)
ADD_TEST_CXX(TestXdmfTime)
ADD_TEST_CXX(TestXdmfTopology)
ADD_TEST_CXX(TestXdmfTopologyMixed)
ADD_TEST_CXX(TestXdmfUnstructuredGrid)
ADD_TEST_CXX(TestXdmfVisitorValueCounter)
ADD_TEST_CXX(TestXdmfWriter)
......@@ -60,6 +61,9 @@ CLEAN_TEST_CXX(TestXdmfRegularGrid
CLEAN_TEST_CXX(TestXdmfSet)
CLEAN_TEST_CXX(TestXdmfTime)
CLEAN_TEST_CXX(TestXdmfTopology)
CLEAN_TEST_CXX(TestXdmfTopologyMixed
TestXdmfTopologyMixed1.xmf
TestXdmfTopologyMixed2.xmf)
CLEAN_TEST_CXX(TestXdmfUnstructuredGrid)
CLEAN_TEST_CXX(TestXdmfVisitorValueCounter)
CLEAN_TEST_CXX(TestXdmfWriter
......
#include "XdmfDomain.hpp"
#include "XdmfGeometry.hpp"
#include "XdmfGeometryType.hpp"
#include "XdmfReader.hpp"
#include "XdmfTopology.hpp"
#include "XdmfTopologyType.hpp"
#include "XdmfUnstructuredGrid.hpp"
#include "XdmfWriter.hpp"
#include "XdmfTestCompareFiles.hpp"
int main(int, char *)
{
//
// Create a unstructured grid consisting of a quadrilateral element
// and a polyline element connected to each other by a single node at
// the corner of each.
//
boost::shared_ptr<XdmfUnstructuredGrid> grid = XdmfUnstructuredGrid::New();
grid->setName("Mixed");
// Set Geometry
double points[] = {0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 2.0, 2.0, 3.0,
1.0, 4.0, 2.0, 5.0, 1.0, 6.0, 2.0};
grid->getGeometry()->setType(XdmfGeometryType::XY());
grid->getGeometry()->insert(0, &points[0], 18);
// Set Topology
boost::shared_ptr<XdmfTopology> topology = grid->getTopology();
topology->setType(XdmfTopologyType::Mixed());
topology->pushBack(XdmfTopologyType::Quadrilateral()->getID());
topology->pushBack(0);
topology->pushBack(1);
topology->pushBack(2);
topology->pushBack(3);
topology->pushBack(XdmfTopologyType::Polyline()->getID());
topology->pushBack(6);
topology->pushBack(2);
topology->pushBack(4);
topology->pushBack(5);
topology->pushBack(6);
topology->pushBack(7);
topology->pushBack(8);
assert(topology->getNumberElements() == 2);
boost::shared_ptr<XdmfDomain> domain = XdmfDomain::New();
domain->insert(grid);
boost::shared_ptr<XdmfWriter> writer =
XdmfWriter::New("TestXdmfTopologyMixed1.xmf");
domain->accept(writer);
boost::shared_ptr<XdmfReader> reader = XdmfReader::New();
boost::shared_ptr<XdmfDomain> readDomain =
boost::shared_dynamic_cast<XdmfDomain>
(reader->read("TestXdmfTopologyMixed1.xmf"));
boost::shared_ptr<XdmfWriter> writer2 =
XdmfWriter::New("TestXdmfTopologyMixed2.xmf");
readDomain->accept(writer2);
assert(XdmfTestCompareFiles::compareFiles("TestXdmfTopologyMixed1.xmf",
"TestXdmfTopologyMixed2.xmf"));
return 0;
}
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