Generate an Abaqus FEA training dataset for surrogate / ML models. Latin Hypercube Sampling (or sparse-pattern sampling) over a parameterized design vector, one case folder per sample, batch-submit Abaqus jobs via subprocess, recover from crashes, and write a unified dataset index. Use when the user wants to "build a training set for a surrogate model", "sweep design parameters in Abaqus", "run N FEA simulations", or "sample a design space".
Scanned 9/8/2026
Install to Claude Code
npx -y skills add nobodyonlyc/skills --skill abaqus-lhs-batch-dataset --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Abaqus Lhs Batch Dataset?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/nobodyonlyc-abaqus-lhs-batch-dataset)More formats (shields.io, HTML) on the badges page.
---
name: abaqus-lhs-batch-dataset
description: Generate an Abaqus FEA training dataset for surrogate / ML models. Latin Hypercube Sampling (or sparse-pattern sampling) over a parameterized design vector, one case folder per sample, batch-submit Abaqus jobs via subprocess, recover from crashes, and write a unified dataset index. Use when the user wants to "build a training set for a surrogate model", "sweep design parameters in Abaqus", "run N FEA simulations", or "sample a design space".
difficulty: intermediate
category: engineering-simulation
tags: [abaqus, fea, finite-element, simulation, machine-learning, surrogate-model, latin-hypercube, dataset-generation]
platforms: [claude, openclaw, opencode, cursor, codex, cline]
quality: community
allowed-tools:
- Read
- Write
- Edit
- Glob
- Grep
- Bash
---
# Abaqus LHS Batch Dataset Generator
End-to-end workflow for producing FEA training datasets from a parameterized Abaqus model. Designed for **surrogate model training** (Ridge, MLP, Gaussian Process, etc.) where you need hundreds to thousands of FEA samples covering a design space.
## When to Use This Skill
Activate when the user wants to:
- Build a training set for a surrogate / ML model from Abaqus FEA
- Sweep a multi-dimensional design vector (e.g. force amplitudes, geometry parameters, material properties)
- Run N independent Abaqus jobs in batch with progress tracking and crash recovery
- Generate inputs for inverse-design / topology-optimization pipelines
Do NOT use this skill for:
- Single-case Abaqus runs (use `abaqus-job` instead)
- Parametric sweeps that don't need ML-ready CSV output (use `abaqus-job` + manual analysis)
- Optimization loops where each evaluation depends on the previous one (use a different driver)
## Core Pattern
```
template_dir/ per-case_dir/ dataset_root/
├ Parameters.dat ──copy──> ├ Parameters.dat ├ sample_design.csv (the design matrix)
├ MaterialParams.dat ├ MaterialParams.dat ├ dataset_index.csv (one row per case)
├ ChannelParams.dat ├ ChannelParams.dat ├ sample_00001/
├ InData.txt ├ InData.txt │ ├ ForceAmplitude.dat <- NEW
└ solver_script.py ├ ForceAmplitude.dat <- NEW │ ├ Membrane2D1.odb
├ <run abaqus cae noGUI> │ ├ node_displacement.csv
├ Membrane2D1.odb <- new │ ├ run_stdout.log
├ node_displacement.csv <- new │ └ run_stderr.log
└ run_*.log <- new ├ sample_00002/
└ ...
```
The pattern is template-driven: you keep one **canonical case** with all the static input files (geometry, material, mesh, step parameters), and per sample you only overwrite the **design vector file** (e.g. `ForceAmplitude.dat`).
## Required Inputs
The user must provide:
1. **`template_dir/`** — A folder containing one **working Abaqus case** with all the static input files. Verify by running it once standalone and confirming the .odb is produced. Required files vary by setup, but typically include:
- `Parameters.dat` — geometry (length, width, thickness, Es, μ)
- `StepParameters.dat` — analysis step config (StepType, time, damping)
- `MaterialParameters.dat` — material model
- `ChannelParameters.dat` — design dimension (number of channels / patches / load regions)
- `InData.txt` — driver flags (output mode, force-continuity flag)
- Optional: `PatchGrid2D.dat`, `DisturbParameters.dat`
2. **`solver_script.py`** — The Abaqus/Python solver script that:
- Reads the template `.dat` files
- Reads the per-case design file (e.g. `ForceAmplitude.dat`)
- Builds the model, submits the job, opens the ODB, and writes a per-node CSV (e.g. `node_displacement.csv` with columns `frame_id, time, node_id, x0, y0, z0, ux, uy, uz, x_def, y_def, z_def`)
- Is invoked via `abaqus cae noGUI="<path>"` from inside the case dir
3. **Design dimension `D`** — number of free parameters per sample (e.g. 16 channels)
4. **Sampling strategy** + bounds (e.g. LHS in `[-0.5, +0.5]^16`)
## Sampling Strategies
Pick one (or combine) based on the design space:
| Strategy | When to use | Implementation |
|---|---|---|
| **LHS** (Latin Hypercube) | Dense, isotropic coverage of a continuous box | Stratified per-dim shuffle (no scipy needed) — see `references/sampling.py` |
| **Uniform random** | Baseline / sanity check | `random.uniform(lo, hi)` per dim |
| **Sparse-k** | Inverse problems with sparsity prior — k of D dims are non-zero | Random k-subset selection with discrete amplitude levels |
| **Single-active** | Channel-by-channel impulse response (basis dataset) | One non-zero entry, sweep over (channel × amplitude) |
| **Pair / block** | Local correlation patterns between adjacent design slots | Enumerate (i, j) adjacencies + amplitude sweeps |
Combine them: a typical surrogate dataset uses **600 LHS + 200 sparse-k + 200 single-active** = 1000 samples.
## Workflow Steps
When the user invokes you, do this:
### Step 1 — Read the template, validate
```bash
# Read ChannelParameters.dat → channel_num (= design dimension D)
# Read PatchGrid2D.dat (if present) → grid shape, boundary mode
# Verify all required files exist
```
### Step 2 — Generate the design matrix
- Build a list of (design_id, vector) tuples per the chosen strategy
- Deduplicate (use a string key from the rounded values to drop near-duplicates)
- Write `sample_design.csv` with header `design_id, active_count, amplitude_1, ..., amplitude_D`
### Step 3 — Per-sample case execution
For each sample `i = 1..N`:
1. `case_dir = dataset_root / f"sample_{i:05d}"`
2. Copy all files from `template_dir/` into `case_dir/` (`shutil.copy2`)
3. **Overwrite** `ForceAmplitude.dat` in `case_dir/` with the new design vector — this is the only file that changes between cases. Format (Abaqus *Amplitude blocks):
```
*Amplitude, name=Amplitude 1
0.000000000000000, -0.376581075439650
1.000000000000000, -0.376581075439650
*Amplitude, name=Amplitude 2
0.000000000000000, 0.123456789012345
1.000000000000000, 0.123456789012345
...
```
For static loads, the two-point amplitude is constant. For ramp loading, set `(0, 0), (t_ramp, val), (1, val)`.
4. Run Abaqus with timeout via `subprocess.run`:
```python
subprocess.run(
'abaqus cae noGUI="<solver_script>"',
cwd=str(case_dir),
shell=True,
text=True,
capture_output=True,
timeout=timeout_s, # default 3600
)
```
5. Capture `proc.returncode`, `proc.stdout` → `run_stdout.log`, `proc.stderr` → `run_stderr.log`, elapsed time
6. Detect success: `Membrane2D1.odb` exists AND `node_displacement.csv` exists AND `returncode == 0`
7. Append a row to `dataset_index.csv`:
```
sample_id, design_id, case_folder, channel_num, grid_nx, grid_ny,
amplitude_1, ..., amplitude_D,
max_abs_uz, status, odb_exists, csv_exists, return_code, elapsed_seconds, error_msg
```
### Step 4 — Resume / retry support
- Before running a case, check if `dataset_index.csv` already has a `completed` row for that `sample_id` → skip if `--reuse-existing`
- For `failed` rows, optionally retry with longer timeout
### Step 5 — Report
- Print summary: `N completed / M total, mean elapsed = X s`
- List failed sample IDs for manual inspection of `run_stderr.log`
## Critical Implementation Details
### 1. Working directory MUST be the case dir
Abaqus reads `*.dat` files relative to the launch directory. Always set `cwd=case_dir` in `subprocess.run`. **NEVER** invoke the solver from the dataset root or template dir.
### 2. Abaqus must be on PATH
Verify with `abaqus --help` before starting. On Windows, the install adds `C:\SIMULIA\Commands` to PATH.
### 3. CPU contention
Each `abaqus cae` job uses 1 CPU by default. Running batch jobs **serially** is the simplest correct approach. For parallelism, ensure `numCpus * concurrent_jobs ≤ physical_cores` and watch out for license token contention.
### 4. Disk usage
Each case generates ~50-200 MB (`.odb` + `.dat` + `.csv` + lockfiles). For 1000 samples, plan for **100-200 GB**. Optionally delete `.odb` and intermediate files after extracting the per-node CSV (see the `abaqus-odb-to-grid-csv` skill).
### 5. Failure modes (in order of frequency)
- **License timeout**: solver hangs waiting for a token → use Abaqus's `lic_check_freq` env var or detect via `*** ERROR: TIMED OUT WAITING FOR LICENSE` in stderr
- **Convergence failure**: nonlinear solve diverges (typical with extreme amplitudes) → status = "failed", check `.msg` file
- **Mesh distortion**: too-large displacements warp elements past Jacobian threshold → reduce amplitude bounds or refine mesh
- **File lock / leftover .lck files**: previous crashed run left `*.lck` → script should `rm -f *.lck` before submitting
- **Time budget**: a single case taking > timeout_s → mark as `timeout`, increase per-case budget for retry
### 6. Reproducibility
Always seed the RNG (`random.Random(seed)`) and write the seed to `dataset_meta.json`. LHS with the same seed + same N gives identical samples.
## Reference Implementation
A complete, dependency-free Python implementation is in `references/batch_runner.py` (~400 lines). It's parameterized via argparse so it works as a CLI:
```bash
python batch_runner.py \
--template-dir ./template_case \
--solver-script ./MyAbaqusSolver.py \
--dataset-root ./datasets \
--strategy lhs \
--n-samples 1000 \
--bounds-min -0.5 \
--bounds-max 0.5 \
--seed 42 \
--timeout-s 3600
```
The `references/sampling.py` module contains pure-stdlib LHS, sparse-k, single-active, pair-adj, and block-2x2 samplers.
## Output Schema
After a complete run:
```
datasets/run_YYYYMMDD_HHMMSS/
├ sample_design.csv # design_id, active_count, amplitude_1..D
├ dataset_index.csv # sample_id, design_id, ..., status, return_code, elapsed
├ dataset_meta.json # seed, strategy, bounds, template path, abaqus version
├ sample_00001/
│ ├ ForceAmplitude.dat # the per-case design vector
│ ├ Parameters.dat # (copied from template)
│ ├ ...other .dat files
│ ├ Membrane2D1.odb # the FEA result
│ ├ Membrane2D1.msg # solver log
│ ├ node_displacement.csv # per-node ux/uy/uz per frame
│ ├ input_vector.csv # (channel_id, amplitude_value)
│ ├ sample_summary.csv # geometry + step metadata
│ ├ run_stdout.log
│ └ run_stderr.log
├ sample_00002/
└ ...
```
The next step in the pipeline is typically the **abaqus-odb-to-grid-csv** skill, which collapses each `node_displacement.csv` into a single row of a wide-table `Y_grid_uz.csv` (sample_id × N²), giving you ML-ready `(X, Y)` matrices.
## Quick Sanity Checks
After a run completes, ask the agent to verify:
1. **Index integrity**: `pandas.read_csv("dataset_index.csv")` — count `status == "completed"`
2. **Sample diversity**: max-pairwise-correlation of `sample_design.csv` rows — should be < 0.7 for LHS
3. **Output range**: `dataset_index.csv["max_abs_uz"]` distribution — should span at least 1 order of magnitude (else the design space is too narrow)
4. **Failed cases**: `cat sample_XXXXX/run_stderr.log` for the first 3 failures
If a high failure rate (> 5%) appears, narrow the design bounds or check the solver script — don't blindly retry.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!