Hi, is there an example on how to convert a .xdmf/.h5 file to a single .xdmf file, wherein the data are embedded? Right now the structure of the example.xdmf file is like this;
<Xdmf Version="3.0"><Domain><Grid Name="Grid"><Geometry GeometryType="XYZ"><DataItem DataType="Float" Dimensions="... 3" Format="HDF" Precision="4">example.h5:/data0</DataItem></Geometry><Topology TopologyType="Mixed" NumberOfElements="..."><DataItem DataType="Int" Dimensions="..." Format="HDF" Precision="8">example.h5:/data1</DataItem></Topology><Attribute Name="CellEntityIds" AttributeType="Scalar" Center="Cell"><DataItem DataType="Int" Dimensions="..." Format="HDF" Precision="4">example.h5:/data2</DataItem></Attribute></Grid></Domain></Xdmf>
I rather want it to have a structure with the data included directly in the example.xdmf file, without the necessity to load those data from the example.h5 file. Is adios4dolfinx suitable to achieve this, or would another solution be preferable in this case?
Right now I made use of this code, but this gave me issues with the correct connectivity.
import h5py
import xml.etree.ElementTree as ET
import xml.dom.minidom
import numpy as np
def read_h5_data(h5_file_path, dataset_name):
"""Reads data from an HDF5 file."""
with h5py.File(h5_file_path, 'r') as file:
data = np.array(file[dataset_name])
return data
def format_data_for_xdmf(data):
"""Formats numpy array data into a space-separated string for XDMF."""
if data.ndim == 2:
# Each row starts on a new line with values space-separated
return '\n'.join(' '.join(map(str, row)) for row in data)
elif data.ndim == 1:
# Each value on a new line
return '\n'.join(map(str, data))
else:
raise ValueError("Unsupported data dimension for XDMF embedding.")
def create_complete_xdmf(h5_file_path, xdmf_file_path):
# Read data from HDF5 file
points = read_h5_data(h5_file_path, 'data0')
connectivity = read_h5_data(h5_file_path, 'data1')
materials = read_h5_data(h5_file_path, 'data2')
# Format data for embedding
points_formatted = format_data_for_xdmf(points)
connectivity_formatted = format_data_for_xdmf(connectivity)
materials_formatted = format_data_for_xdmf(materials)
# Create the XDMF file structure
xdmf = ET.Element('Xdmf', Version="3.0")
domain = ET.SubElement(xdmf, 'Domain')
grid = ET.SubElement(domain, 'Grid', Name="Grid")
# Embed geometry
geometry = ET.SubElement(grid, 'Geometry', GeometryType="XYZ")
data_item_geo = ET.SubElement(geometry, 'DataItem', DataType="Float", Dimensions=f"{points.shape[0]} {points.shape[1]}", Format="XML", Precision="8")
data_item_geo.text = points_formatted
# Embed topology
topology = ET.SubElement(grid, 'Topology', TopologyType="Tetrahedron", NumberOfElements=f"{connectivity.shape[0]}")
data_item_topo = ET.SubElement(topology, 'DataItem', DataType="Int", Dimensions=f"{connectivity.shape[0]} 4", Format="XML", Precision="4")
data_item_topo.text = connectivity_formatted
# Embed materials attribute
attribute = ET.SubElement(grid, 'Attribute', Name="materials", AttributeType="Scalar", Center="Cell")
data_item_attr = ET.SubElement(attribute, 'DataItem', DataType="Int", Dimensions=f"{materials.shape[0]}", Format="XML", Precision="4")
data_item_attr.text = materials_formatted
# Generate a pretty-printed XML string
rough_string = ET.tostring(xdmf, 'utf-8')
reparsed = xml.dom.minidom.parseString(rough_string)
pretty_xml_str = reparsed.toprettyxml(indent=" ")
# Write to a file
with open(xdmf_file_path, "w") as file:
file.write(pretty_xml_str)
# Example usage
h5_file_path = '/path/to/example.h5'
xdmf_file_path = '/path/to/example.xdmf'
create_complete_xdmf(h5_file_path, xdmf_file_path)
Then the structure becomes in the right format, but issues occur with the connectivity. Below an example of such a snippet;
<?xml version="1.0" ?>
<Xdmf Version="3.0">
<Domain>
<Grid Name="Grid">
<Geometry GeometryType="XYZ">
<DataItem DataType="Float" Dimensions="... 3" Format="XML" Precision="8">0.33 1.33 1.22
1.11 1.22 2.22
2.10 1.77 1.88
3.55 0.90 1.90 .....
6.99 7.11 4.33
3.22 5.33 6.44</DataItem>
</Geometry>
<Topology TopologyType="Tetrahedron" NumberOfElements="...">
<DataItem DataType="Int" Dimensions="... 4" Format="XML" Precision="4">0 1 2
2 3 4
4 5 6
6 7 8 .....
8 9 10
11 12 13</DataItem>
</Topology>
<Attribute Name="materials" AttributeType="Scalar" Center="Cell">
<DataItem DataType="Int" Dimensions="..." Format="XML" Precision="4">1
1
1
1
1 .....
3
3
3
3
2
2
2
2
2
2
2
2
3
3</DataItem>
</Attribute>
</Grid>
</Domain>
</Xdmf>