1. Course overview

Course overview 学习卡片

LS-DYNA writes two fundamentally different families of result data. Understanding that split is the foundation of everything in this course. The first family is the binary output — files such as d3plot, binout*, d3thdt, and intfor — written in a compact, machine-oriented format that stores full-field and time-history results for the entire model. The second family is the ASCII time-history output — files such as glstat, matsum, rcforc, nodout, elout, and secforc — written as plain text tables that are easy to read but expensive to parse at scale. Python is the natural tool for turning both families into structured, analyzable data, and this course teaches that workflow end to end.

The central object of study is the binout file. Unlike d3plot, which stores nodal and elemental state across the whole mesh, binout is a container of time-history channels organized by a two-level hierarchy: a branch (the result category, e.g. glstat, matsum, rcforc, nodout, secforc, sleout) and a variable within that branch (e.g. kinetic_energy, internal_energy, x_force). Each variable is a one-dimensional array sampled at the output intervals defined by *DATABASE_BINARY_D3PLOT and *DATABASE_BINARY_D3THDT. This hierarchy is why a single binout file can hold hundreds of independent curves, and why naive parsing fails: you cannot read it as a flat table.

Why not just read the ASCII files? ASCII outputs are convenient for a single glstat run, but they break down when you need to compare 40 drop-test simulations, extract one force channel from a 2 GB binout, or build a regression dashboard. Binary parsing gives you random access to a named channel without loading the whole file, which is the difference between a 3-second query and a 10-minute wait.

The Python Toolchain

Three libraries dominate this space, and knowing when to use each is a core skill.

  • lasso-python (formerly qd-ansa / lasso) — the modern, actively maintained reader. It exposes lasso.dyna.Binout and lasso.dyna.D3plot, supports branch/variable discovery, and returns NumPy arrays directly. This is the primary tool for the course.
  • qdBinout — the older reader bundled with LS-DYNA distributions. Still found in legacy scripts; its API is less Pythonic and its maintenance is uncertain.
  • numpy + pandas — the analysis layer. Once a channel is a NumPy array, everything from filtering to FFT to regression is available.

A minimal, reproducible read looks like this:

from lasso.dyna import Binout
import numpy as np

b = Binout("binout0000")

# Discover what is actually inside the file
print(b.read())                 # list of branches
print(b.read("glstat"))         # variables in the glstat branch

# Pull one channel as a NumPy array
time = b.read("glstat", "time")
ke   = b.read("glstat", "kinetic_energy")
ie   = b.read("glstat", "internal_energy")

# Energy balance check: total should be roughly conserved
total = ke + ie
print("max total energy:", np.max(total))
print("drift:", (total[-1] - total[0]) / total[0])

Two things in that snippet deserve emphasis. First, b.read() with no arguments is the discovery step — never assume a branch or variable name exists; query it. Second, the energy-drift calculation is a real sanity check, not decoration. In an explicit dynamics run, if total = kinetic + internal drifts by more than a few percent, you likely have hourglassing, an unstable time step, or a contact energy leak, and the model needs attention before any result is trusted.

Where the Data Comes From and Where It Goes

The technical context matters because it constrains what you can analyze. LS-DYNA writes binout incrementally during the solve; the file is only complete and consistent after normal termination. If a job is killed, the last record may be truncated, and a reader will either raise an error or silently return a short array. Always check that the time vector is monotonically increasing and that its length matches the expected number of output intervals.

On the output side, the analysis target is usually one of four things: a scalar time series (energy, momentum, time step), a force/displacement pair (crash pulse, penetration), a per-node or per-element history (acceleration at a sensor location), or a cross-run comparison (design variants, mesh convergence). Each has a different natural data structure, and choosing the right one early prevents painful reshaping later.

LS-DYNA Result Data Flow: From Solver Output to Python Analysis LS-DYNA Solver explicit / implicit time integration *DATABASE cards control output cadence Binary Output binout0000 d3plot / d3thdt intfor branch → variable hierarchy random access, compact ASCII Output glstat / matsum rcforc / nodout elout / secforc flat text tables human-readable, slow at scale Python Analysis Layer lasso.dyna.Binout branch / variable discovery + NumPy arrays numpy / pandas filter, resample, align, aggregate scipy / matplotlib FFT, integration, plotting Validation checks energy drift, monotonic time, truncation Deliverables curves · comparison tables · regression reports · dashboards Watch for truncated last record missing branch names unit inconsistency non-monotonic time energy drift > few %

What This Course Covers

The 30 chapters follow a deliberate progression. The first block establishes the data model and the reader API: how binout is structured, how to enumerate branches and variables, how to convert channels into NumPy arrays, and how to handle the common failure modes (missing branches, truncated files, unit mismatches). The second block moves into analysis: time alignment across runs, filtering and resampling, numerical differentiation and integration, energy and momentum checks, and frequency-domain inspection. The third block covers engineering workflows: crash pulse extraction, occupant-sensor histories, contact force analysis, and cross-run comparison for design studies. The final block addresses automation — batch processing hundreds of runs, building reusable extraction functions, and producing reports that a team can actually use.

By the end, you should be able to point at any LS-DYNA result directory and answer a specific engineering question with a short, verifiable Python script — not by opening a GUI and clicking, but by writing code that another engineer can read, rerun, and trust.

Prerequisite check. Before starting, confirm you can run python -c "import lasso.dyna, numpy, pandas; print('ok')" without errors. If lasso is missing, install it with pip install lasso-python. You will also need at least one completed LS-DYNA run with a binout0000 file to practice on; the course examples assume a crash or drop-test model with glstat, matsum, and rcforc branches present.

Key Concepts to Carry Forward

ConceptMeaning in This CourseTypical Pitfall
BranchTop-level result category inside binout (e.g. glstat)Assuming a branch exists without querying it
VariableNamed channel within a branch (e.g. kinetic_energy)Name spelling differs between LS-DYNA versions
Time vectorShared sampling axis for all channels in a branchAssuming uniform spacing; it is not guaranteed
Energy balanceKinetic + internal + hourglass + sliding ≈ constantIgnoring hourglass and contact energy terms
TruncationIncomplete final record after abnormal terminationSilent short arrays that corrupt statistics

The single most important habit this course builds is verify before you analyze. Query the branch list, check the time vector, run the energy balance, and only then compute the quantity you actually care about. A wrong number that looks plausible is far more dangerous than an obvious error, and in explicit dynamics the difference between a valid and an invalid result is often a few percent of energy drift that no plot will reveal unless you look for it.