2. Python environment setup for LS-DYNA automation

LS-DYNA keyword automation lives or dies by the reliability of the Python environment underneath it. A script that generates a 40,000-line *INCLUDE tree, parses d3plot results, or drives a batch of lsdyna runs must behave identically on your workstation, a colleague's laptop, and the cluster head node. That reproducibility does not come from the script alone — it comes from how you install Python, pin dependencies, and structure the workspace. This section walks through a setup that is boring, repeatable, and appropriate for keyword generation and post-processing work.

Choosing the Interpreter

Install a standalone CPython distribution rather than relying on the system Python. On Linux, /usr/bin/python3 is often tied to OS tooling and must not be modified. On Windows, the Microsoft Store Python has sandboxing quirks that break some binary wheels. The practical choice is the official python.org installer or a version manager such as pyenv (Linux/macOS) or pyenv-win. Target Python 3.11 or 3.12: both have mature wheels for NumPy, SciPy, and the visualization stack, and they are new enough to avoid end-of-life warnings from pip.

# Linux / macOS with pyenv
pyenv install 3.12.4
pyenv global 3.12.4
python -m venv ~/lsdyna-venv
source ~/lsdyna-venv/bin/activate

# Windows PowerShell
py -3.12 -m venv C:\lsdyna\venv
C:\lsdyna\venv\Scripts\Activate.ps1

Always work inside a virtual environment. A virtual environment isolates the packages your automation depends on from everything else on the machine, so upgrading lasso-python for one project cannot silently break another. The activation prompt should show the environment name; if it does not, you are installing into the global interpreter.

Managing Dependencies

Keyword automation typically needs three categories of packages. First, core numerics: numpy and scipy for array manipulation and interpolation of curves. Second, LS-DYNA-specific tooling: lasso-python for reading binout and d3plot files, and qd-plot or matplotlib for plotting. Third, text and file handling: pandas for tabular result summaries and jinja2 if you template keyword decks.

Pin versions in a requirements.txt and install with a single command. Unpinned installs are the most common cause of "it worked yesterday" failures.

# requirements.txt
numpy==2.0.1
scipy==1.14.0
pandas==2.2.2
matplotlib==3.9.1
lasso-python==2024.6.12
jinja2==3.1.4

pip install -r requirements.txt

For anything beyond a personal script, prefer a lock file. pip-tools or uv can resolve the full transitive dependency graph and freeze exact hashes, which matters when a cluster administrator rebuilds the environment months later. If your team already uses Conda for solver-adjacent tooling, environment.yml is acceptable, but keep the Python version explicit and avoid mixing conda install and pip install for the same package.

If lasso-python fails to install, check the wheel availability for your Python version and platform first. Building from source requires a C++ toolchain and is rarely worth the effort when a matching wheel exists.

Editors and IDEs

Two editor choices dominate this workflow. VS Code with the Python and Pylance extensions gives you IntelliSense, an integrated terminal, and a debugger that can attach to a running script — useful when a keyword generator produces malformed cards and you need to inspect the intermediate data structure. PyCharm Professional adds stronger refactoring and a built-in scientific mode, but the Community edition is sufficient for most automation work.

Whichever you pick, configure three things: the interpreter path (point it at your virtual environment, not the system Python), a formatter (black or ruff format), and a linter (ruff). Consistent formatting matters when multiple engineers edit the same keyword-generation templates. Add a .vscode/settings.json or .idea/ exclusion so editor metadata does not pollute the repository.

Organizing the Project Workspace

A keyword automation project has a predictable shape: input decks, generated decks, solver runs, and post-processing outputs. Keep them in separate directories so a regeneration never overwrites a result you still need. A workable layout is shown below.

lsdyna-automation/
├── pyproject.toml
├── requirements.txt
├── src/
│   └── kwgen/
│       ├── __init__.py
│       ├── deck_builder.py
│       ├── materials.py
│       └── postprocess.py
├── templates/
│   └── crash_box.k
├── cases/
│   └── baseline/
│       ├── params.yaml
│       └── run.sh
├── runs/
│   └── baseline_2024-07-15/
│       ├── model.k
│       ├── d3plot
│       └── binout
└── notebooks/
    └── result_review.ipynb

The src/ layout prevents accidental imports of local modules that shadow installed packages. Parameter files in cases/ keep case-specific values out of code, so a new load case is a new YAML file rather than a code branch. The runs/ directory is timestamped and treated as disposable output; it should be excluded from version control via .gitignore.

Verifying the Setup

Before writing any automation logic, confirm the environment can import every dependency and locate the solver. A short smoke test catches path and version problems early.

import numpy, lasso
from lasso.dyna import D3plot
print("numpy", numpy.__version__)
print("lasso", lasso.__version__)
# confirm solver is on PATH
import shutil
print("lsdyna:", shutil.which("lsdyna") or "NOT FOUND")

If shutil.which returns None, the solver is not on PATH and any subprocess call will fail with FileNotFoundError. Fix the environment variable rather than hard-coding an absolute path in the script. A successful run prints the versions and the solver location; that output is your baseline for troubleshooting later.

LS-DYNA Python Automation Environment Interpreter CPython 3.12 pyenv / venv isolated Dependencies numpy · scipy · pandas lasso-python · jinja2 pinned in requirements.txt Editor / IDE VS Code / PyCharm ruff · black debugger Workspace src/ templates/ cases/ runs/ notebooks/ Keyword Generation params.yaml → model.k jinja2 templates Solver Execution subprocess → lsdyna d3plot · binout Post-Processing lasso-python → arrays matplotlib → plots Smoke Test: import numpy, lasso → check versions → shutil.which("lsdyna") Failure symptom: FileNotFoundError on subprocess call → solver not on PATH Fix: set PATH in environment, never hard-code absolute solver paths in scripts

The diagram above shows how the four setup layers feed the three-stage automation pipeline. The interpreter and dependency layers determine what your scripts can import; the editor layer determines how quickly you can debug them; the workspace layer determines whether a run can be reproduced. The smoke test at the bottom is the gate: if it fails, no amount of script logic will save the run.

Common Pitfalls and How to Avoid Them

  • Mixing global and virtual environments. Symptom: pip list shows a package but import fails. Check sys.executable inside the script — it should point into the venv.
  • Unpinned dependencies. Symptom: a script that ran last month now raises an API error. Pin versions and commit the lock file.
  • Hard-coded solver paths. Symptom: works on your machine, fails on the cluster. Use shutil.which or an environment variable.
  • Writing outputs into the source tree. Symptom: git status is full of d3plot files. Keep runs/ separate and gitignored.

A clean environment is not overhead — it is the precondition for every keyword generator and post-processing script that follows. Spend the twenty minutes now, and the rest of the course will run on rails.