Enabling d3plot2hdf5 to export results from DEM analyses has been a recent feature request. The following model of a funnel injection is directly taken from the LS-DYNA examples homepage.
Below is a screenshot of the model in ParaView
The state file can be downloaded here: funnelInjection.pvsm (1.1 MB)
Once the simulation with LS-DYNA is finished, we end up with these d3plot database files:
ll -h d3plot*
-rw-r--r--@ 1 larski larski 2.6M Jul 8 2024 d3plot
-rw-r--r--@ 1 larski larski 133M Jul 8 2024 d3plot01
-rw-r--r--@ 1 larski larski 133M Jul 8 2024 d3plot02
-rw-r--r--@ 1 larski larski 133M Jul 8 2024 d3plot03
-rw-r--r--@ 1 larski larski 133M Jul 8 2024 d3plot04
-rw-r--r--@ 1 larski larski 133M Jul 8 2024 d3plot05
-rw-r--r--@ 1 larski larski 133M Jul 8 2024 d3plot06
-rw-r--r--@ 1 larski larski 133M Jul 8 2024 d3plot07
-rw-r--r--@ 1 larski larski 133M Jul 8 2024 d3plot08
-rw-r--r--@ 1 larski larski 133M Jul 8 2024 d3plot09
-rw-r--r--@ 1 larski larski 133M Jul 8 2024 d3plot10
-rw-r--r--@ 1 larski larski 8.9M Jul 8 2024 d3plot11
-rw-r--r--@ 1 larski larski 8.9M Jul 8 2024 d3plot12
The converter is simply invoked by
d3plot2hdf5 d3plot
which then produces this output
+--------------------------------------------------------------------+
| |
| T A I L S I T |
| ------------- |
| |
| Program :: d3plot2hdf5 |
| Purpose :: convert d3plot to h5/xdmf |
| Build :: v0.10.0 [6fa1851] |
| Date :: Apr 28 2025,15:55:30 |
| News, discussions, bugs :: https://discourse.tailsit.com |
| |
| Terms: https://tailsit.com/downloads/TAILSIT_B2B_GTC.pdf |
| |
| For non-commercial use only |
| |
| Copyright, 2025 by TAILSIT GMBH. All rights reserved. |
| www.tailsit.com |
| |
+--------------------------------------------------------------------+
Options:
-- timeSteps: all
-- split files: false
Title/Part/Contact information:
-- Header: Funnel Injection
-- Parts:
[mat-id:1] Steel funnel and plate
[mat-id:2] DES
-- Contacts: (NONE)
LS-DYNA files:
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot"
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot01"
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot02"
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot03"
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot04"
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot05"
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot06"
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot07"
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot08"
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot09"
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot10"
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot11"
-- "/home/larski/git/d3plot2hdf5/tests/dem/FunnelInjection/complete/d3plot12"
LS-DYNA file information:
-- Title: Funnel Injection
-- Version: DEV
-- Creation date: Mon Jul 1 09:18:32 2024
-- Format: double precision
Additional ASCII Data:
-- NONE
State information:
-- max. no. of states found: 152
-- actual no. of states found: 152
-- state range: [0:151]
Output written to:
-- d3plot.03.xdmf
-- d3plot.23.xdmf
-- d3plot.h5
N O R M A L T E R M I N A T I O N 04/28/25 16:02:31
The converter took about 4 seconds to produce these files:
ll -h *.xdmf *.h5
-rw-rw-r-- 1 larski larski 1.4M Apr 26 07:38 d3plot.03.xdmf
-rw-rw-r-- 1 larski larski 1.3M Apr 26 07:38 d3plot.23.xdmf
-rw-rw-r-- 1 larski larski 1.5G Apr 26 07:38 d3plot.h5
All the heavy data is stored in the hdf5-file d3plot.h5
while the .xdmf
files contain lightweight references to the .h5
file. The .xdmf
files can then directly be processed by tools like ParaView.
The particle data is referenced from d3plot.03.xdmf
while references to the structural data are stored in d3plot.23.xdmf
.
Below is a tiny animation of the results. It displays the particles’ velocities through a period of roughly 2.8 seconds.
Scripting
A word on scripting. .xdmf
stores references to the data in such a way that ParaView can digest the heavy data. However, it is the .h5
file that stores the data iteself. So, if you want to script your post-processing tasks it is a good idea to get accustomed to the structure of the .h5
file.
We recommend using command line tools to investigate the contents of the .h5
file. On Debian based systems those command line tools can be installed with
sudo apt install hdf5-helpers
Other Linux distributions supply the hdf5-helpers, too. Simply use the respective package manager. Alternatively, those tools are typically bundled with the binary distributions of HDF5. Simply go to
for further information. This destination might be helpful for Windows installations, too.
Once the hdf5 tools are installed you can work, e.g., with h5dump
or h5ls
. The latter gives you a condensed view of the contents while the output of h5dump
can be rather exhaustive. In many ways the HDF5 format can be viewed as a kind of filesystem, and this is exactly how h5ls
behaves like.
So, let’s get started. Calling
h5ls d3plot.h5 | column
is likely to produce this lengthy output:
annotation Group d3plot_stp025 Group d3plot_stp051 Group d3plot_stp077 Group d3plot_stp103 Group d3plot_stp129 Group
d3plot_stp000 Group d3plot_stp026 Group d3plot_stp052 Group d3plot_stp078 Group d3plot_stp104 Group d3plot_stp130 Group
d3plot_stp001 Group d3plot_stp027 Group d3plot_stp053 Group d3plot_stp079 Group d3plot_stp105 Group d3plot_stp131 Group
d3plot_stp002 Group d3plot_stp028 Group d3plot_stp054 Group d3plot_stp080 Group d3plot_stp106 Group d3plot_stp132 Group
d3plot_stp003 Group d3plot_stp029 Group d3plot_stp055 Group d3plot_stp081 Group d3plot_stp107 Group d3plot_stp133 Group
d3plot_stp004 Group d3plot_stp030 Group d3plot_stp056 Group d3plot_stp082 Group d3plot_stp108 Group d3plot_stp134 Group
d3plot_stp005 Group d3plot_stp031 Group d3plot_stp057 Group d3plot_stp083 Group d3plot_stp109 Group d3plot_stp135 Group
d3plot_stp006 Group d3plot_stp032 Group d3plot_stp058 Group d3plot_stp084 Group d3plot_stp110 Group d3plot_stp136 Group
d3plot_stp007 Group d3plot_stp033 Group d3plot_stp059 Group d3plot_stp085 Group d3plot_stp111 Group d3plot_stp137 Group
d3plot_stp008 Group d3plot_stp034 Group d3plot_stp060 Group d3plot_stp086 Group d3plot_stp112 Group d3plot_stp138 Group
d3plot_stp009 Group d3plot_stp035 Group d3plot_stp061 Group d3plot_stp087 Group d3plot_stp113 Group d3plot_stp139 Group
d3plot_stp010 Group d3plot_stp036 Group d3plot_stp062 Group d3plot_stp088 Group d3plot_stp114 Group d3plot_stp140 Group
d3plot_stp011 Group d3plot_stp037 Group d3plot_stp063 Group d3plot_stp089 Group d3plot_stp115 Group d3plot_stp141 Group
d3plot_stp012 Group d3plot_stp038 Group d3plot_stp064 Group d3plot_stp090 Group d3plot_stp116 Group d3plot_stp142 Group
d3plot_stp013 Group d3plot_stp039 Group d3plot_stp065 Group d3plot_stp091 Group d3plot_stp117 Group d3plot_stp143 Group
d3plot_stp014 Group d3plot_stp040 Group d3plot_stp066 Group d3plot_stp092 Group d3plot_stp118 Group d3plot_stp144 Group
d3plot_stp015 Group d3plot_stp041 Group d3plot_stp067 Group d3plot_stp093 Group d3plot_stp119 Group d3plot_stp145 Group
d3plot_stp016 Group d3plot_stp042 Group d3plot_stp068 Group d3plot_stp094 Group d3plot_stp120 Group d3plot_stp146 Group
d3plot_stp017 Group d3plot_stp043 Group d3plot_stp069 Group d3plot_stp095 Group d3plot_stp121 Group d3plot_stp147 Group
d3plot_stp018 Group d3plot_stp044 Group d3plot_stp070 Group d3plot_stp096 Group d3plot_stp122 Group d3plot_stp148 Group
d3plot_stp019 Group d3plot_stp045 Group d3plot_stp071 Group d3plot_stp097 Group d3plot_stp123 Group d3plot_stp149 Group
d3plot_stp020 Group d3plot_stp046 Group d3plot_stp072 Group d3plot_stp098 Group d3plot_stp124 Group d3plot_stp150 Group
d3plot_stp021 Group d3plot_stp047 Group d3plot_stp073 Group d3plot_stp099 Group d3plot_stp125 Group d3plot_stp151 Group
d3plot_stp022 Group d3plot_stp048 Group d3plot_stp074 Group d3plot_stp100 Group d3plot_stp126 Group narbs Group
d3plot_stp023 Group d3plot_stp049 Group d3plot_stp075 Group d3plot_stp101 Group d3plot_stp127 Group
d3plot_stp024 Group d3plot_stp050 Group d3plot_stp076 Group d3plot_stp102 Group d3plot_stp128 Group
As you can see there are 152 time steps stored in d3plot.h5
. If you now want to investigate a single time step a bit further you can do:
h5ls d3plot.h5/d3plot_stp000
which will give you:
fields03 Group
fields23 Group
grid03 Group
grid23 Group
gridXY
stores the geometry information (or links to it), while fieldsXY
stores the simulation data itself. Let’s investigate the latter a bit further. X
denotes the reference dimension while Y
denotes the dimension of the physical world. Hence, fields03
stores the particle data. Since this is the data we are interested in, we proceed with
h5ls d3plot.h5/d3plot_stp000/fields03
and obtain
cell Group
grid Group
node Group
These three groups denote to which entities the data is attached to. In a Finite Element simulation node
would denote nodal or point data, cell
would be element data, and grid
would collect data such as energies or time series values which are global quantities that can neither be attached to a cell nor to a node.
Let’s assume we are further interested in the grid data. This time we invoke h5ls
with the -r
option which avoids further cycles and lists all groups recursively. So, entering
h5ls -r d3plot.h5/d3plot_stp000/fields03/grid
yields
/scalar Group
/scalar/internal\ energy(PART_0) Dataset {1}
/scalar/internal\ energy(PART_1) Dataset {1}
/scalar/internal\ energy(PART_ALL) Dataset {1}
/scalar/kinetic\ energy(PART_0) Dataset {1}
/scalar/kinetic\ energy(PART_1) Dataset {1}
/scalar/kinetic\ energy(PART_ALL) Dataset {1}
/scalar/mass(PART_0) Dataset {1}
/scalar/mass(PART_1) Dataset {1}
/scalar/time Dataset {1}
/scalar/total\ energy(PART_0) Dataset {1}
/scalar/total\ energy(PART_1) Dataset {1}
/scalar/total\ energy(PART_ALL) Dataset {1}
/vector Group
/vector/rigid\ body\ velocity(PART_0) Dataset {3}
/vector/rigid\ body\ velocity(PART_1) Dataset {3}
/vector/rigid\ body\ velocity(PART_ALL) Dataset {3}
This time we get to the data itself. We can see that grid
contains a scalar
and a vector
group. So, if we are interested in the energies over time we now know exactly where the data of interest is stored. Clearly, you do not need to process the data soley with h5ls
. You could also use software packages like, e.g., octave, Matlab, or Mathematica to accomplish this task. Feel free in the choice of your tools. And if you want to use a freely available tool that provides a graphical user interface we recommend HDFView.
Finally, this scripting section would be rather incomplete without a script itself. Now that we know the structure of the .h5
file we can create a simple Python-script that plots the energies over time. The script looks like:
#!/usr/bin/env python3
import h5py
import re
import matplotlib.pyplot as plt
import numpy as np
import sys
def extract_data( h5file: str, part: str ):
data = []
with h5py.File( h5file, 'r' ) as f:
group_names = list(f.keys())
pattern = re.compile( r'^d3plot_stp\d{3}$')
for group_name in group_names:
if pattern.match(group_name):
base = f"/{group_name}/fields03/grid/scalar"
# time
time = f"{base}/time"
# kinetic energy
ke = f"{base}/kinetic energy({part})"
# internal energy
ie = f"{base}/internal energy({part})"
# total energy
te = f"{base}/total energy({part})"
t = f[time][:][0]
kw = f[ke][:][0]
iw = f[ie][:][0]
tw = f[te][:][0]
data.append( [t, kw, iw, tw] )
return np.array(data)
def plot( data, part ):
t = data[:,0]
kw = data[:,1]
iw = data[:,2]
tw = data[:,3]
plt.figure(figsize=(12,8))
plt.plot(t,tw,marker='o', linestyle='-',color='b',label='Total')
plt.plot(t,iw, linestyle='-',color='g',label='Internal')
plt.plot(t,kw, linestyle='-',color='m',label='Kinetic')
plt.xlabel('time [s]')
plt.ylabel('energy')
plt.title(f'Energies over time [{part}]')
plt.grid(True)
plt.legend()
plt.savefig(f'energy_{part}.png', format='png', dpi=300)
plt.show()
if __name__ == "__main__":
try:
if len(sys.argv) is not 3:
raise ValueError(f"Usage: {sys.argv[0]} h5-file part, part = 0|1|ALL")
#
# PARSE COMMAND LINE
h5file = sys.argv[1]
part = "PART_"
part = f"{part}{sys.argv[2]}"
#
## EXTRACT DATA
data = extract_data( h5file, part )
#
# PLOT DATA
plot(data,part)
#
# DONE
except ValueError as e:
print( f"An error has ocurred: {e}")
The script can be downloaded here:
processEnergies.py (2.0 KB)
And the required packages can be found herein:
requirements.txt (255 Bytes)
Calling
python3 -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
./processEnergies.py d3plot.h5 ALL
then produces the following plot
That’s it!