2. Python environment for CAE automation

PAM-CRASH automation scripts rarely live in isolation. A single workflow may need to parse LS-DYNA or PAM-CRASH keyword files, drive the solver from the command line, post-process THP or DSY result files, and push summary data into a report. Each of those tasks pulls in different third-party libraries, and those libraries evolve at different speeds. Without a controlled Python environment, a script that worked last quarter can break after an unrelated package upgrade. This chapter establishes the environment discipline that every later automation example assumes.

Why a Virtual Environment Is Not Optional

A virtual environment is an isolated Python interpreter plus its own site-packages directory. When activated, python and pip resolve to that environment, so installing or upgrading a package affects only that project. For CAE automation this matters for three concrete reasons:

  • Version pinning across solver generations. PAM-CRASH installations are often upgraded on a fixed corporate cadence, while Python libraries such as numpy, pandas, or lxml may be upgraded independently. A pinned environment guarantees the script sees the same library versions regardless of what the solver team installs.
  • Conflicting dependencies. A mesh-processing library may require numpy<2.0 while a newer plotting library requires numpy>=2.0. Separate environments let both coexist.
  • Reproducibility for audit. Crash simulation results are frequently reviewed months later. A frozen requirements.txt or lock file lets a colleague rebuild the exact environment that produced a report.

The standard tool is venv, shipped with CPython since 3.3. Create and activate an environment on Windows (the most common PAM-CRASH platform):

py -3.11 -m venv .venv
.venv\Scripts\activate
python -m pip install --upgrade pip

On Linux clusters where PAM-CRASH is often run headless, the equivalent is:

python3.11 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip

After activation, where python (Windows) or which python (Linux) should point inside .venv. If it still points to a system interpreter, activation failed and every subsequent pip install will pollute the global environment.

Package Management: Pinning, Locking, and Offline Installs

For a CAE automation project, keep a requirements.txt with explicit versions rather than loose ranges. A minimal starting set for PAM-CRASH post-processing looks like this:

numpy==1.26.4
pandas==2.2.2
lxml==5.2.2
matplotlib==3.8.4
pyyaml==6.0.1

Install with pip install -r requirements.txt. To capture the full transitive dependency graph for archival, use pip freeze > requirements.lock. The lock file is what you commit alongside the script; the human-readable requirements.txt is what you edit.

Many engineering workstations sit behind a proxy or have no internet access. In that case, download wheels on a connected machine with pip download -r requirements.txt -d wheels/, copy the wheels/ directory to the target machine, and install offline:

pip install --no-index --find-links=wheels -r requirements.txt

This pattern is common on isolated solver nodes and avoids the "works on my laptop" failure mode entirely.

Integrating with the PAM-CRASH Installation Directory

PAM-CRASH ships its own executables, license utilities, and sometimes a bundled Python. The automation environment should not replace that bundled interpreter; instead, it should call the solver as a subprocess and read its outputs. The integration points are:

ItemTypical location (Windows)How automation uses it
Solver executableC:\Program Files\ESI\PAM-CRASH\2023.0\bin\pamcrash.exeInvoked via subprocess.run
License serverSet by ESI_LICENSE_FILE or LM_LICENSE_FILERead from environment, never hard-coded
Result filesWorking directory of the runParsed by numpy/pandas
Bundled Python...\tools\pythonLeft untouched; used only if ESI scripts require it

Resolve the installation root from an environment variable rather than a literal path, so the same script runs against 2022.0 and 2023.0:

import os, subprocess, pathlib

PAM_ROOT = pathlib.Path(os.environ["PAM_CRASH_HOME"])
solver = PAM_ROOT / "bin" / "pamcrash.exe"

result = subprocess.run(
    [str(solver), "-i", "model_input.pc", "-o", "run_01"],
    cwd="run_01",
    capture_output=True,
    text=True,
)
if result.returncode != 0:
    raise RuntimeError(result.stderr[-2000:])

Set PAM_CRASH_HOME in the activation script so it is available whenever the environment is active. On Windows, add a set PAM_CRASH_HOME=... line to .venv\Scripts\activate.bat; on Linux, append export PAM_CRASH_HOME=... to .venv/bin/activate. This keeps the solver path out of source code and makes the environment self-describing.

Tip: Keep the virtual environment outside the PAM-CRASH installation tree. Installing packages into C:\Program Files\ESI\... often fails due to permissions and can be wiped by the next solver upgrade.

Verifying the Environment Before a Run

A short pre-flight check catches most environment problems before a long solver run is wasted. The script below confirms the interpreter, the key packages, and the solver path:

import sys, os, pathlib, importlib

print("Python:", sys.executable)
for pkg in ("numpy", "pandas", "lxml"):
    m = importlib.import_module(pkg)
    print(f"{pkg}: {m.__version__}")

root = pathlib.Path(os.environ.get("PAM_CRASH_HOME", ""))
solver = root / "bin" / "pamcrash.exe"
print("Solver exists:", solver.is_file())

Expected output shows the interpreter inside .venv, the pinned versions, and Solver exists: True. If sys.executable points to a system Python, the environment was not activated. If Solver exists: False, PAM_CRASH_HOME is unset or wrong. If a package import fails, the lock file was not installed into this environment.

Common failure: Running the script from an IDE that uses its own interpreter instead of the project .venv. Configure the IDE's interpreter path explicitly to .venv\Scripts\python.exe (Windows) or .venv/bin/python (Linux).
Python Automation Environment for PAM-CRASH Virtual Environment (.venv) python.exe / python3.11 site-packages (pinned versions) requirements.txt / requirements.lock PAM-CRASH Installation bin/pamcrash.exe License server (env var) Result files (THP, DSY) subprocess.run() PAM_CRASH_HOME parse results Automation Workflow 1. Activate .venv 2. Pre-flight check 3. Run solver 4. Parse & report Isolation guarantees reproducibility across solver upgrades and machines

Practical Notes on Reproducibility

Two habits make the environment genuinely reproducible. First, commit both requirements.txt and requirements.lock to version control; the lock file is the source of truth for rebuilds. Second, record the environment in the run metadata: write sys.version, the output of pip freeze, and the value of PAM_CRASH_HOME into a run_environment.json next to the solver output. When a result is questioned six months later, that file answers "which Python, which libraries, which solver" without guesswork.

With the environment established, subsequent chapters can focus on the automation logic itself — keyword manipulation, batch execution, and result extraction — knowing that the interpreter and dependencies are stable and traceable.