Converting to PyG graphs

Again, start from a PyVista dataset:

Hide code cell content

%load_ext autoreload
%autoreload 2
The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload
from cooldata.pyvista_flow_field_dataset import PyvistaFlowFieldDataset

ds_pv = PyvistaFlowFieldDataset.load_from_huggingface(
    num_samples=2, data_dir="datasets/pyvista"
)
ds_pv[0]
Loaded 2 samples from '/Users/ole/Documents/software/flow_field_dataset/docs/usage/datasets/pyvista'.
Loaded 2 samples from 'datasets/pyvista'.
2025-06-09 07:10:06.424 ( 461.604s) [          760B75]      vtkCGNSReader.cxx:4267  WARN| vtkCGNSReader (0x3201dc720): Skipping BC_t node: BC_t type 'BCInflow' not supported yet.
2025-06-09 07:10:06.425 ( 461.605s) [          760B75]      vtkCGNSReader.cxx:4267  WARN| vtkCGNSReader (0x3201dc720): Skipping BC_t node: BC_t type 'BCSymmetryPlane' not supported yet.
2025-06-09 07:10:06.425 ( 461.605s) [          760B75]      vtkCGNSReader.cxx:4267  WARN| vtkCGNSReader (0x3201dc720): Skipping BC_t node: BC_t type 'BCTunnelOutflow' not supported yet.

Design ID: 125002

Quader 1\nTemp: 24.8\nPos: (0.02, 0.07)\nSize: (0.15, 0.05) Quader 2\nTemp: 72.1\nPos: (0.08, 0.09)\nSize: (0.14, 0.06) Quader 3\nTemp: 40.7\nPos: (0.20, 1.00)\nSize: (0.05, 0.01) Quader 4\nTemp: 29.5\nPos: (0.12, 0.03)\nSize: (0.08, 0.01) Cylinder 1\nTemp: 70.8\nPos: (0.07, 1.00)\nRadius: 0.00 Cylinder 2\nTemp: 79.8\nPos: (0.11, 1.00)\nRadius: 0.01

Bounding Box (xmin, xmax, ymin, ymax): (-0.00, 0.50, 0.00, 0.10)

Now, let us convert the PyVista dataset to a DGL graph. This requires some computation, and is implemented in a parallelized way. Also, you need to install the dgl library (see here).

from cooldata.pyg_flow_field_dataset import PyGSurfaceFlowFieldDataset

ds_pyg_surface = PyGSurfaceFlowFieldDataset(
    "datasets/pyg_surface", ds_pv, normalize=False

)

Let us now explore what the graphs look like:

ds_pyg_surface[0]
Data(edge_index=[2, 286210], Pressure=[35771], Temperature=[35771], pos=[35771, 3], ShearStress=[35771, 3], Normal=[35771, 3], CellArea=[35771], SurfaceType=[35771], BodyID=[35771], HeatTransferCoefficient=[35771], edge_attr=[286210, 3])

Again, we can visualize the graph:

Hide code cell content

import pyvista as pv
pv.set_jupyter_backend('static')
ds_pyg_surface.plot_surface(ds_pyg_surface[0],"Pressure")
../_images/4ecd9466f6aacc52273cbc40ce2358b581e5c6814a2a03653c205afbd70e8fba.png

Now, let us normalize the data:

ds_pyg_surface[0]["Pressure"].mean()
tensor(0.1086)
ds_pyg_surface.do_normalization = True
ds_pyg_surface[0]["Pressure"].mean()
tensor(0.3887)

You can find a full training script here.

It is possible to use the volumetric data as a graph as well:

from cooldata.pyg_flow_field_dataset import PyGVolumeFlowFieldDataset


ds_pyg_volume = PyGVolumeFlowFieldDataset("datasets/pyg_volume", ds_pv)

The graphs will have a significantly larger number of nodes and edges:

ds_pyg_volume[0]
Data(edge_index=[2, 4550210], Pressure=[187194], Temperature=[187194], pos=[187194, 3], Velocity=[187194, 3], TurbulentDissipationRate=[187194], TurbulentKineticEnergy=[187194], Volume=[187194], edge_attr=[4550210, 3])

Again, we can normalize the graph features:

ds_pyg_volume[0]["Pressure"].mean(), ds_pyg_volume[0]["Pressure"].std(),
(tensor(0.0291), tensor(0.7165))
ds_pyg_volume.normalize()
ds_pyg_volume[0]["Pressure"].mean(),ds_pyg_volume[0]["Pressure"].std()
(tensor(0.3601), tensor(0.3279))