Read results from xdmf/h5 file to calculate the difference

Hi guys,
I am trying to read the velocity function i stored in xdmf/h5 file.

I tried this: with h5py.File(velocity.h5, ‘r’) as h5file:
print(h5file.keys())
for i in range(3):
dataset_name = f’/Function/f_0/{i}’
data = h5file[dataset_name]
the data has the size of (#nodes, dim=3), since i am running 3d test.
However to be able to calculate say the error i need to integrate over the domain, so i need to have u = fem.Function(V), which u.x.array[:] has length of the number of freedom.
Can anyone help me with that?

Thanks a lot!

See: GitHub - jorgensd/adios4dolfinx: Interface of ADIOS2 for DOLFINx
and
checkpointing slides

Thank you for your quick response! I am looking at it right now!

Sorry when i install dolfinx from conda on my virtual enviroment, it turns out i installed dolfinx 0.5.2:
DOLFINx version: 0.5.2 based on GIT commit: b76d44782540fa8dc1e59cd09a20e55f178d11bf of GitHub - FEniCS/dolfinx: Next generation FEniCS problem solving environment
MPI.COMM_WORLD.rank=0, MPI.COMM_WORLD.size=1
Traceback (most recent call last):
File “=write_checking.py”, line 15, in
adx.write_mesh(domain, checkpoint_file, engine=“BP4”)
File “=miniconda/envs/fenicsx-env/lib/python3.10/site-packages/adios4dolfinx/checkpointing.py”, line 53, in write_mesh
io.DefineAttribute(“LagrangeVariant”, np.array([mesh.geometry.cmap.variant], dtype=np.int32))
AttributeError: ‘dolfinx.cpp.fem.CoordinateElement’ object has no attribute ‘variant’

And this is the erorr when i try to run the code i provided in my dolfinx 0.6

Hi I try to install dolfinx 0.6.0 on my virtual environment, when I run the example (which works well on my local computer), returns me the following error:
The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File “/ix/wlayton/rui/write_checking.py”, line 16, in
adx.write_mesh(domain, mesh_checkpoint_file, engine=“BP4”)
File “/ix/wlayton/ruf10/miniconda3/envs/fenicsx-env/lib/python3.10/site-packages/adios4dolfinx/checkpointing.py”, line 53, in write_mesh
io.DefineAttribute(“LagrangeVariant”, np.array([mesh.geometry.cmap.variant], dtype=np.int32))
TypeError: Unable to convert function return value to a Python type! The signature was
(arg0: dolfinx.cpp.fem.CoordinateElement) → basix::element::lagrange_variant

Could you please help me with that soon?

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>

If you simply want to have plain-text data, you can set the encoder in dolfinx.io.XDMFFile to ASCII, ref: dolfinx/python/test/unit/fem/test_fem_pipeline.py at edd98116acf22cd5853e962c76bd079566075a99 · FEniCS/dolfinx · GitHub
i.e. you can set it for either read or write mode.