meshio
meshio copied to clipboard
Cannot parse XDMF time series
The following XDMF is understood by Paraview 5.6 but is not understood by meshio, which raises AssertionError: Unknown section 'Grid'.
It contains two <Grid>s inside of <Grid CollectionType="Temporal" GridType="Collection" Name="TimeSeries">.
<?xml version="1.0" encoding="utf-8"?>
<Xdmf xmlns:xi="http://www.w3.org/2001/XInclude" Version="3.0">
<Domain>
<Grid CollectionType="Temporal" GridType="Collection" Name="TimeSeries">
<Grid GridType="Uniform" Name="grid0">
<Time Value="0"/>
<Attribute AttributeType="Vector" Center="Other" ElementCell="triangle" ElementDegree="1"
ElementFamily="DG"
ItemType="FiniteElementFunction"
Name="u">
<DataItem Dimensions="2 6" Format="XML" Name="celldofs" NumberType="UInt">0 1 2 3 4 5
6 7 8 9 10 11
</DataItem>
<DataItem Dimensions="12 1" Format="XML" NumberType="Float">0
0
0
-0
-0
-0
-0
-0
-0
-0
-0
-0
</DataItem>
</Attribute>
<Topology NodesPerElement="3" NumberOfElements="2" TopologyType="Triangle">
<DataItem Dimensions="2 3" Format="XML" NumberType="UInt">0 1 2
1 2 3
</DataItem>
</Topology>
<Geometry GeometryType="XY">
<DataItem Dimensions="4 2" Format="XML">0 0
1 0
0 1
1 1
</DataItem>
</Geometry>
</Grid>
<Grid GridType="Uniform" Name="grid1">
<Time Value="0.001"/>
<Attribute AttributeType="Vector" Center="Other" ElementCell="triangle" ElementDegree="1"
ElementFamily="DG"
ItemType="FiniteElementFunction"
Name="u">
<DataItem Dimensions="2 6" Format="XML" Name="celldofs" NumberType="UInt">0 1 2 3 4 5
6 7 8 9 10 11
</DataItem>
<DataItem Dimensions="12 1" Format="XML" NumberType="Float">0
0
0
-0
-0
-0
-0
-0
-0
-0
-0
-0
</DataItem>
</Attribute>
<xi:include xpointer="xpointer(//Grid[@Name="TimeSeries"]/Grid[@Name="grid0"]/*[self::Topology or self::Geometry])"/>
</Grid>
</Grid>
</Domain>
</Xdmf>
Ok, I guess I am talking about unsupported feature: finite element functions. Feel free to close.
It's okay to leave it open, meshio should support this. This is a time series, so you'll have to tackle it in the main readme,
import meshio
reader = meshio.XdmfTimeSeriesReader("a.xdmf")
points, cells = reader.read_points_cells()
for k in range(reader.num_steps):
t, point_data, cell_data = reader.read_data(k)
However, this doesn't work yet. It chokes on GridType="Collection". I'll have a look one of these days.
To solve my problem (I have XDMF XML files which Paraview chockes on error: xmlSAX2Characters: huge text node: out of memory), I wrote this XDMF XML to binary converter. The idea is it does not need to be able to completely understand XDMF, it merely replaces DataItem nodes. Meshio was invaluable in developing this :wink: Feel free to reuse any portion of the following with MIT if useful.
from lxml import etree
import numpy
from meshio.common import write_xml
from meshio.xdmf_io.common import xdmf_to_numpy_type
def xdmf_xml_to_binary(infilename, outfilename):
"""Convert XDMF with XML data items into binary data items"""
outfilebase, ext = outfilename.rsplit(sep='.', maxsplit=1)
assert ext.lower() == 'xdmf'
parser = etree.XMLParser(remove_comments=True, huge_tree=True)
tree = etree.parse(infilename, parser)
# Loop over heavy data nodes
for i, e in enumerate(tree.getroot().iter('DataItem')):
# Extract shape
dims = [int(d) for d in e.get("Dimensions").split()]
# Extract dtype
dtype = e.get('NumberType', 'Float') # XDMF default
precision = e.get('Precision', '4') # XDMF default
dtype = xdmf_to_numpy_type[(dtype, precision)]
# Convert XML text to numpy array
assert e.get('Format') == 'XML'
data = numpy.array(e.text.split(), dtype=dtype).reshape(dims)
# Dump array to binary file
bin_filename = "{}{}.bin".format(outfilebase, i)
with open(bin_filename, "wb") as f:
data.tofile(f)
# Make XML point to binary file
e.text = bin_filename
e.set('Format', 'Binary')
write_xml(outfilename, tree.getroot())
if __name__ == '__main__':
import sys
xdmf_xml_to_binary(sys.argv[1], sys.argv[2])