Module conduction.tools.generate_timeseries_xdmf
Copyright 2017 Ben Mather
This file is part of Conduction https://git.dias.ie/itherc/conduction/
Conduction is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.
Conduction is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with Conduction. If not, see http://www.gnu.org/licenses/.
Expand source code
"""
Copyright 2017 Ben Mather
This file is part of Conduction <https://git.dias.ie/itherc/conduction/>
Conduction is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or any later version.
Conduction is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Conduction. If not, see <http://www.gnu.org/licenses/>.
"""
def generateTimeseriesXdmf(*args):
"""
Generate a XDMF file to visualise HDF5 fields and vectors in Paraview.
Supply an ordered list of HDF5 filenames to create a timeseries to write
a XDMF file to the working directory.
"""
import h5py
import os
# We only need the topology information from first HDF5 file
HDF5_filename = args[0]
filename = HDF5_filename
if HDF5_filename.endswith('.h5'):
filename = HDF5_filename[:-3]
else:
HDF5_filename += '.h5'
filename += '.xmf'
f = open(filename, 'w')
def write_header(f):
f.write('''<?xml version="1.0" ?>\n\
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>\n\
<Xdmf xmlns:xi="http://www.w3.org/2003/XInclude" Version="2.2">\n\
<Information Name="SampleLocation" Value="4"/>\n\
<Domain>\n''')
def write_footer(f):
f.write(''' </Grid>\n </Domain>\n</Xdmf>''')
def write_topology(f, dim, shape, origin, stride):
f.write(''' <Topology TopologyType="3DCORECTMesh" NumberOfElements="{1}"/>\n\
<Geometry GeometryType="ORIGIN_DXDYDZ">\n\
<DataItem Dimensions="{0}" NumberType="Float" Precision="4" Format="XML">\n\
{2}\n\
</DataItem>\n\
<DataItem Dimensions="{0}" NumberType="Float" Precision="4" Format="XML">\n\
{3}\n\
</DataItem>\n\
</Geometry>\n'''.format(dim, shape, origin, stride))
def write_timeseries(f, dim, trange):
f.write(''' <Grid Name="TimeSeries" GridType="Collection" CollectionType="Temporal">\n\
<Time TimeType="HyperSlab">\n\
<DataItem Format="XML" NumberType="Float" Dimensions="{0}">\n\
{1}\n\
</DataItem>\n\
</Time>\n'''.format(dim, trange))
def write_grid_header(f, step):
f.write(''' <Grid Name="t{}" GridType="Uniform">\n\
<Topology Reference="/Xdmf/Domain/Topology[1]"/>\n\
<Geometry Reference="/Xdmf/Domain/Geometry[1]"/>\n'''.format(step))
def write_grid_footer(f):
f.write(''' </Grid>\n''')
def write_attribute(f, attributeName, arrtype, dshape, dpath):
f.write(''' <Attribute Name="{0}" AttributeType="{1}" Center="Node">'\n\
<DataItem Dimensions="{2}" NumberType="Float" Precision="4" Format="HDF">{3}</DataItem>\n\
</Attribute>\n'''.format(attributeName, arrtype, dshape, dpath))
def array_to_string(array):
s = ""
for i in array:
s += "{} ".format(i)
return s
h5file = h5py.File(HDF5_filename, 'r')
basename = os.path.basename(HDF5_filename)
# get topology attributes
topo = h5file['topology']
minCoords = topo.attrs['minCoord']
maxCoords = topo.attrs['maxCoord']
shape = topo.attrs['shape']
dim = len(shape)
nsteps = len(args)
nodes = 1
for n in shape:
nodes *= n
stride = (maxCoords - minCoords)/shape
tshape = array_to_string(shape)
torigin = array_to_string(minCoords)
tstride = array_to_string(stride)
trange = array_to_string(list(range(0, nsteps)))
write_header(f)
write_topology(f, dim, tshape, torigin, tstride)
write_timeseries(f, dim, trange)
for step, HDF5_filename in enumerate(args):
h5file = h5py.File(HDF5_filename, 'r')
basename = os.path.basename(HDF5_filename)
write_grid_header(f, step)
for key in h5file:
dset = h5file[key]
# We only want datasets, topology group is not required
if type(dset) is h5py.Dataset:
dpath = basename + ":" + dset.name
dname = dset.name[1:]
dshape = array_to_string(dset.shape)
dnodes = 1
for n in dset.shape:
dnodes *= n
if dnodes%nodes != 0:
raise ValueError("Dataset {} is not a valid shape".format(dname))
elif dnodes/nodes > 1:
arrtype = "Vector"
elif dnodes/nodes == 1:
arrtype = "Scalar"
write_attribute(f, dname, arrtype, dshape, dpath)
write_grid_footer(f)
h5file.close()
write_footer(f)
f.close()
if __name__ == '__main__':
import sys
generateTimeseriesXdmf(sys.argv[1:])
Functions
def generateTimeseriesXdmf(*args)
-
Generate a XDMF file to visualise HDF5 fields and vectors in Paraview.
Supply an ordered list of HDF5 filenames to create a timeseries to write a XDMF file to the working directory.
Expand source code
def generateTimeseriesXdmf(*args): """ Generate a XDMF file to visualise HDF5 fields and vectors in Paraview. Supply an ordered list of HDF5 filenames to create a timeseries to write a XDMF file to the working directory. """ import h5py import os # We only need the topology information from first HDF5 file HDF5_filename = args[0] filename = HDF5_filename if HDF5_filename.endswith('.h5'): filename = HDF5_filename[:-3] else: HDF5_filename += '.h5' filename += '.xmf' f = open(filename, 'w') def write_header(f): f.write('''<?xml version="1.0" ?>\n\ <!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>\n\ <Xdmf xmlns:xi="http://www.w3.org/2003/XInclude" Version="2.2">\n\ <Information Name="SampleLocation" Value="4"/>\n\ <Domain>\n''') def write_footer(f): f.write(''' </Grid>\n </Domain>\n</Xdmf>''') def write_topology(f, dim, shape, origin, stride): f.write(''' <Topology TopologyType="3DCORECTMesh" NumberOfElements="{1}"/>\n\ <Geometry GeometryType="ORIGIN_DXDYDZ">\n\ <DataItem Dimensions="{0}" NumberType="Float" Precision="4" Format="XML">\n\ {2}\n\ </DataItem>\n\ <DataItem Dimensions="{0}" NumberType="Float" Precision="4" Format="XML">\n\ {3}\n\ </DataItem>\n\ </Geometry>\n'''.format(dim, shape, origin, stride)) def write_timeseries(f, dim, trange): f.write(''' <Grid Name="TimeSeries" GridType="Collection" CollectionType="Temporal">\n\ <Time TimeType="HyperSlab">\n\ <DataItem Format="XML" NumberType="Float" Dimensions="{0}">\n\ {1}\n\ </DataItem>\n\ </Time>\n'''.format(dim, trange)) def write_grid_header(f, step): f.write(''' <Grid Name="t{}" GridType="Uniform">\n\ <Topology Reference="/Xdmf/Domain/Topology[1]"/>\n\ <Geometry Reference="/Xdmf/Domain/Geometry[1]"/>\n'''.format(step)) def write_grid_footer(f): f.write(''' </Grid>\n''') def write_attribute(f, attributeName, arrtype, dshape, dpath): f.write(''' <Attribute Name="{0}" AttributeType="{1}" Center="Node">'\n\ <DataItem Dimensions="{2}" NumberType="Float" Precision="4" Format="HDF">{3}</DataItem>\n\ </Attribute>\n'''.format(attributeName, arrtype, dshape, dpath)) def array_to_string(array): s = "" for i in array: s += "{} ".format(i) return s h5file = h5py.File(HDF5_filename, 'r') basename = os.path.basename(HDF5_filename) # get topology attributes topo = h5file['topology'] minCoords = topo.attrs['minCoord'] maxCoords = topo.attrs['maxCoord'] shape = topo.attrs['shape'] dim = len(shape) nsteps = len(args) nodes = 1 for n in shape: nodes *= n stride = (maxCoords - minCoords)/shape tshape = array_to_string(shape) torigin = array_to_string(minCoords) tstride = array_to_string(stride) trange = array_to_string(list(range(0, nsteps))) write_header(f) write_topology(f, dim, tshape, torigin, tstride) write_timeseries(f, dim, trange) for step, HDF5_filename in enumerate(args): h5file = h5py.File(HDF5_filename, 'r') basename = os.path.basename(HDF5_filename) write_grid_header(f, step) for key in h5file: dset = h5file[key] # We only want datasets, topology group is not required if type(dset) is h5py.Dataset: dpath = basename + ":" + dset.name dname = dset.name[1:] dshape = array_to_string(dset.shape) dnodes = 1 for n in dset.shape: dnodes *= n if dnodes%nodes != 0: raise ValueError("Dataset {} is not a valid shape".format(dname)) elif dnodes/nodes > 1: arrtype = "Vector" elif dnodes/nodes == 1: arrtype = "Scalar" write_attribute(f, dname, arrtype, dshape, dpath) write_grid_footer(f) h5file.close() write_footer(f) f.close()