Getting started¶
This page takes you from an empty environment to a program that parses a real LS-DYNA deck, navigates it, validates it, and reads a result file — in about ten minutes. Every snippet is shown in both languages; pick the tab for the one you use and the whole page follows.
Install¶
Requires Python 3.9+. Numeric data (node coordinates, element connectivity,
result channels) comes back as NumPy arrays, so numpy is pulled in as a
dependency. The published wheels bundle the signal feature, so filtering and
injury criteria work out of the box — nothing else to enable.
Verify the install:
Or add it to Cargo.toml:
Optional features — off by default so a plain build stays lean:
| Feature | Enables |
|---|---|
signal |
result-history signal processing (SAE J211 CFC, Butterworth, integrate/differentiate) and the injury criteria |
ffi |
a C ABI (and, through it, Fortran) for the parse + validate path |
typed-keywords |
a generated typed struct per keyword (~3,170; opt-in) |
See feature flags for the full matrix.
Prefer the command line? cargo install dynars installs a dynars binary that
parses a deck and prints its include tree — see CLI.
Your first program¶
parse_deck reads the root file and everything it *INCLUDEs in one parallel
pass, and hands back a single Deck. You validate and navigate off that one
handle — the id and reference indices are built lazily and cached on first use, so
a parse that only reads columns never pays for them.
import dynars
deck = dynars.parse_deck("main.k")
print(deck) # Deck(<n> files)
report = deck.validate([
dynars.Rule.references_resolve(), # every id reference resolves
dynars.Rule.duplicate_ids(), # no two entities share an id
dynars.Rule.include_missing(), # every *INCLUDE exists on disk
])
if report.is_clean():
print("no errors")
else:
for f in report.findings:
print(f"[{f.severity}] {f.location()} — {f.message}")
use dynars::deck::parse_deck;
use dynars::validate::Rule;
fn main() {
let deck = parse_deck(std::path::Path::new("main.k")).unwrap();
println!("{} files", deck.files.len());
let report = deck.validate([
Rule::references_resolve(), // every id reference resolves
Rule::duplicate_ids(), // no two entities share an id
Rule::include_missing(), // every *INCLUDE exists on disk
]);
if report.is_clean() {
println!("no errors");
} else {
for f in &report.findings {
println!("[{:?}] {} — {}", f.severity, f.location(), f.message);
}
}
}
A finding carries a severity, a human-readable message, and a clickable
file:line location(). A report is_clean() when it has no Error-severity
findings (warnings are allowed). There is no default rule set — you pass
exactly the checks you want.
A five-minute tour¶
The same Deck is your entry point for four different jobs. Here they are back
to back so you can see how they fit together.
1. Inspect what the deck contains¶
Get a census before diving in — the definition counts tell you what kinds of entity are defined and how many of each.
2. Navigate by id and follow references¶
Look an entity up by id, then walk the references in its fields — a *PART's
material and section, a load's curve, and so on. Ids resolve in the deck's
global namespace, so references that cross an *INCLUDE_TRANSFORM are followed
correctly.
if let Some(part) = deck.part(1) {
let mat = part.material(); // follow *PART.mid -> *MAT
let sec = part.section(); // follow *PART.secid -> *SECTION
println!("part {:?} ({})", part.id(), part.name());
if let Some(m) = mat {
println!(" density: {:?}", m.field("RO").and_then(|f| f.as_f64()));
}
let _ = sec;
}
3. Bulk-read the high-volume keywords as columns¶
For *NODE and *ELEMENT_* you rarely want per-entity handles — you want
columns. table reads every occurrence across the whole deck (root +
includes) at once.
4. Read the result files¶
Once the run has finished, the same package reads the binary output — d3plot
(geometry + per-state fields) and binout (time histories). Numeric data comes
back as NumPy arrays in Python, typed Vecs in Rust.
That is the whole surface in miniature: parse → inspect → navigate → validate → read results. The rest of the guides go deep on each.
What you get back¶
A few types show up everywhere; knowing them makes the rest of the docs read easily.
| Type | What it is |
|---|---|
Deck |
the parsed root + all includes; the single handle for navigation, columns, and validation |
Entity (Py) / Keyword (Rust) |
one entity — typed field(...) access, source file/line, and reference-following (material(), section(), reference(name)) |
Report |
the result of validate(...) — is_clean(), count(severity), and a list of findings |
Finding |
one violation — severity, rule, message, and a clickable location() |
D3plot / Binout |
the two result readers |
If those distinctions feel fuzzy, the Concepts page draws the mental model — deck vs. keyword file, global ids, includes and transforms.
Troubleshooting¶
parse_decksucceeds but an entity is missing. A missing*INCLUDEis never parsed, so its entities simply aren't there. AddRule.include_missing()to surface the missing file explicitly.- A reference "doesn't resolve" but the target is clearly present. Check
whether it lives behind an
*INCLUDE_TRANSFORM— ids are matched in the global namespace after offsets are applied; see Concepts → includes & transforms. deck.table("FOO")raises / returns nothing.FOOisn't in the built-in library. Register a schema and read it withtable_with.- Signal / injury functions missing in Rust. They live behind the
signalfeature:dynars = { version = "1.0", features = ["signal"] }. The Python wheels already include it. dynars.cfc/dynars.hic36raiseAttributeErrorin Python. Post- processing moved into submodules:from dynars import signal, injury, thensignal.cfc(...)/injury.hic36(...).
Next steps¶
- Concepts — the mental model behind the API.
- Decks & navigation — navigate by id, follow references, bulk-read, and edit decks.
- Validation — the full rule set and how to write your own checks.
- Workspace (batch) — do all of this across many decks at once without re-reading shared files.
- Results —
d3plot/binout, signal processing, injury criteria. - Recipes — short, task-oriented "how do I…" snippets.