1. Inspect d3plot file structure and state inventory
Why a State Inventory Comes First
A d3plot database is LS-DYNA's binary state database. Every output interval writes one state containing the full model geometry (nodal coordinates, element connectivity, part/element material IDs) plus the requested result variables (displacement, velocity, acceleration, stress, strain, and so on). Before any extraction task — a nodal time history, an element stress tensor, a section force — you need to know exactly what the file contains: how many states exist, what simulation time each state corresponds to, and which result variables were actually written. Guessing at these facts is the most common cause of misaligned time axes, empty arrays, and silently wrong component ordering downstream.
This case establishes that baseline inventory. You will open a d3plot database, enumerate every state with its time value, and list the available result variables per state. The output is a small, reusable inventory that later extraction tasks can consume directly.
What a d3plot File Actually Contains
A d3plot file is a sequence of records. The control record at the start of the file declares the number of states, the number of nodes, the number of solid/beam/shell elements, and the word size (single or double precision). Each state then begins with a state header carrying the simulation time, followed by geometry blocks and result blocks. LS-DYNA may also split large databases into family files (d3plot01, d3plot02, …) when the model exceeds the per-file size limit; the state count in the control record refers to the whole family, not just the first file.
Two practical consequences follow. First, the number of states is a property of the database, not of any single file. Second, the result variables present in a state depend on what was requested in the *DATABASE_BINARY_D3PLOT and *DATABASE_EXTENT_BINARY keywords — a database written with only displacement will not contain stress, no matter how you query it.
Opening the Database and Enumerating States
Two paths are practical. In LS-PrePost, load the database via File → Open → LS-DYNA → d3plot; the state slider at the bottom of the viewport shows the total state count, and the State panel lists each state with its time. The Fringe component selector then reveals which result variables are available. This is the fastest sanity check and is worth doing before writing any script, because it confirms the file is readable and the state count is what you expect.
For a scriptable inventory, use the lasso-python reader (the maintained successor to the older lasso package). The following script opens a database, walks every state, and writes a CSV inventory. It is self-contained and runs against any valid d3plot.
import csv
from pathlib import Path
from lasso.dyna import D3plot, ArrayType
D3PLOT = Path("run/d3plot") # first file of the family
OUT_CSV = Path("inventory.csv")
ds = D3plot(str(D3PLOT))
# --- database-level facts from the control record ---
n_states = ds.get_global("state_count") if hasattr(ds, "get_global") else None
if n_states is None:
n_states = len(ds.arrays[ArrayType.global_simulation_time])
times = ds.arrays[ArrayType.global_simulation_time]
# --- which result arrays are actually populated ---
candidate_vars = {
"disp": ArrayType.node_displacement,
"vel": ArrayType.node_velocity,
"accel": ArrayType.node_acceleration,
"stress": ArrayType.element_solid_stress,
"strain": ArrayType.element_solid_strain,
"energy": ArrayType.element_solid_energy,
}
available = {}
for name, key in candidate_vars.items():
try:
arr = ds.arrays[key]
available[name] = arr.shape
except KeyError:
pass
print(f"states: {n_states}")
print(f"time range: {times[0]:.6g} .. {times[-1]:.6g}")
for name, shape in available.items():
print(f" {name:8s} shape={shape}")
# --- per-state inventory ---
with OUT_CSV.open("w", newline="") as fh:
w = csv.writer(fh)
w.writerow(["state", "time", "variables"])
for i, t in enumerate(times):
w.writerow([i, f"{t:.9g}", ";".join(sorted(available))])
print(f"wrote {OUT_CSV}")
Two details in the script matter. First, ArrayType.global_simulation_time is the authoritative per-state time vector; do not derive time from a nominal output interval, because LS-DYNA may write extra states at termination or on adaptive remeshing. Second, the try/except KeyError pattern is the correct way to test for a result block: the reader raises KeyError when a block was never written, which is exactly the "absent block" condition described above. Do not assume a block exists because the keyword was present in the input deck — check the file.
d3plot) to the reader. The reader follows the family automatically; the state count in the control record already covers all files. Passing d3plot01 directly will give you a partial inventory.Reading the Inventory and Judging It
A correct inventory for a typical explicit run looks like this (values are illustrative for a 41-state, 20 ms simulation):
| Check | Expected result | Failure symptom |
|---|---|---|
| State count | Matches control record nstates | Reader returns fewer states than the slider shows in LS-PrePost — family file missing or truncated |
| Time vector | Strictly increasing, starts at 0.0 | Duplicate or non-monotonic times — restart appended states; de-duplicate before extraction |
| Variable list | Identical across all states | A variable present in early states but absent later — output request changed mid-run; extraction must handle ragged arrays |
| Array shapes | disp is (nstates, nnodes, 3); stress is (nstates, nsolid, 6) | Shape mismatch with control record — wrong word size or corrupted file |
The shape check is the most valuable single test. For a database with 41 states, 128,450 nodes, and 96,200 solids, node_displacement.shape must be (41, 128450, 3) and element_solid_stress.shape must be (41, 96200, 6). The trailing dimension of 6 for solid stress reflects the six tensor components in LS-DYNA's stored order (σxx, σyy, σzz, σxy, σyz, σzx); confirming this now prevents component-ordering errors in later tensor extraction. If the shapes disagree with the control record, stop and re-check the file before proceeding — every downstream extraction will inherit the error.
Deliverable: Baseline Inventory Record
Keep the generated inventory.csv alongside the database and record the following header facts in your run notes. This is the artifact later extraction tasks reference.
| Field | Example value | Source |
|---|---|---|
| Database path | run/d3plot | Input |
| State count | 41 | Control record / time vector length |
| Time range | 0.0 – 20.0 ms | global_simulation_time[0], [-1] |
| Nodes / solids | 128,450 / 96,200 | Control record |
| Available variables | disp, vel | Populated ArrayType keys |
| Word size | double | Control record |
| Family files | none | Directory listing |
*DATABASE_EXTENT_BINARY set to suppress element results will produce a database with no stress block. The inventory must come from the file, and the KeyError test in the script is the reliable way to detect absence.With the inventory in hand — state count, time vector, variable list, and array shapes all confirmed against the control record — you have a trustworthy baseline. Any later extraction that disagrees with this baseline (a time axis that does not match, a variable that suddenly appears) is a signal to re-inspect the database rather than to patch the extraction code.