4. Data generation and management

A surrogate model is only as trustworthy as the dataset behind it. In a CAE-driven workflow, the surrogate learns a mapping from design or operating parameters to simulation outputs, and every downstream claim about accuracy, robustness, or optimization quality inherits the biases and gaps of that training set. This chapter treats data generation and management as a first-class engineering activity: how to launch batch simulations reliably, how to extract and validate results, how to clean and reconcile them, and how to structure the final dataset so that training, validation, and later uncertainty quantification remain defensible.

Design of Experiments as the Data Contract

Before a single solver run is launched, the sampling plan defines what the surrogate can ever learn. A Latin Hypercube or Sobol sequence over the parameter space gives better coverage than a naive grid, especially when the input dimension exceeds three or four. The sampling plan should be treated as a contract: it fixes parameter names, units, bounds, and the exact ordering of runs, and it is versioned alongside the code that consumes it. A practical convention is to store the plan as a plain table with one row per run and one column per input, plus a stable run_id that never changes once assigned.

Two decisions deserve explicit attention. First, bounds must reflect physically admissible values, not merely convenient ranges; a surrogate trained on a parameter window that the optimizer will later exceed is extrapolating silently. Second, the sampling density should be tied to the expected nonlinearity of the response. If a preliminary screening run shows a sharp resonance or a bifurcation, the plan should be refined locally rather than uniformly densified, because uniform refinement wastes solver budget in flat regions.

Running Batch Simulations

Batch execution is where most data-generation failures originate. A robust harness separates three concerns: generating per-run input decks, dispatching jobs to a scheduler or local pool, and collecting exit status. The following pattern is representative of a Python driver that templates a solver input file and submits runs through a job array:

import csv, subprocess, pathlib

runs = list(csv.DictReader(open("doe_plan.csv")))
for r in runs:
    workdir = pathlib.Path("runs") / r["run_id"]
    workdir.mkdir(parents=True, exist_ok=True)
    deck = TEMPLATE.format(
        thickness=float(r["thickness_mm"]),
        load=float(r["load_kN"]),
        mesh_level=int(r["mesh_level"]),
    )
    (workdir / "case.inp").write_text(deck)
    proc = subprocess.run(
        ["solver", "-i", "case.inp", "-o", "case.out"],
        cwd=workdir, capture_output=True, text=True,
    )
    (workdir / "exit_code").write_text(str(proc.returncode))

In production this loop is replaced by a scheduler submission, but the invariant is the same: every run writes its own directory, its own input deck, its own log, and an explicit exit code. Never infer success from the presence of an output file alone; solvers frequently write partial results before diverging. A run is valid only when the exit code is zero and a convergence or completion marker appears in the log.

Silent failures are the most expensive data defect. A solver that terminates with a warning, produces a plausible-looking but unconverged field, or clamps a parameter to a default will contaminate the dataset without any visible error. Always parse the log for convergence flags and residual thresholds, and record them per run.

Extracting Results

Extraction should be deterministic and scripted, never manual. For each run, define a small set of scalar quantities of interest (QoIs) — maximum von Mises stress, first natural frequency, peak displacement, mass — and parse them from the solver output with a fixed parser. Store the raw extracted values alongside the run identifier, and keep the parser version in the metadata. When the parser changes, re-extract from archived outputs rather than re-running the solver, which is usually the dominant cost.

Where the response is a field rather than a scalar, reduce it deliberately. A common approach is to project the field onto a small basis (POD/PCA) and store the modal coefficients as features, retaining the basis vectors for reconstruction. This keeps the dataset compact while preserving the spatial information the surrogate may need.

Cleaning and Reconciliation

Cleaning is not cosmetic; it is where physical consistency is enforced. The checks that matter most are: unit consistency across runs, duplicate detection on the input vector, detection of clamped or defaulted parameters, and outlier screening against physically plausible bounds. A stress value that is negative in magnitude, a frequency that is exactly zero, or a mass that does not scale with density and volume are all signals of a broken run rather than an interesting design.

Outliers should be investigated before deletion. A genuine extreme response near a resonance is valuable training data; a spurious one from a diverged solve is poison. The distinguishing evidence is usually in the log and the convergence history, which is why those artifacts must be retained. When a run is discarded, record the reason in a status column so the dataset remains auditable and the sampling plan can be repaired rather than silently shrunk.

Structuring the Dataset for Training

The final artifact is a tidy table: one row per valid run, input columns, QoI columns, and metadata columns for run_id, solver version, parser version, and status. Normalize inputs and outputs using statistics computed only on the training split, and persist those scaler parameters with the model so inference uses identical transforms. Split the data by run, not by row, and hold out a validation set that covers the parameter space rather than a random scatter, so that reported error reflects interpolation quality across the design domain.

The diagram below summarizes the pipeline from sampling plan to training-ready dataset, including the decision points where runs are accepted, repaired, or rejected.

DOE Plan Sobol / LHS run_id, bounds, units Batch Execution per-run workdir deck + log + exit_code Extraction parse QoIs POD for fields Cleaning units, duplicates outlier screening exit=0 AND converged? Reject / Repair log reason refine DOE locally yes Training-Ready Dataset run_id | inputs | QoIs | status scaler params persisted split by run, not by row validation covers domain refined samples Provenance Metadata solver version · parser version DOE hash · timestamp rejection reasons

Provenance and Reproducibility

Every dataset should carry enough metadata to reconstruct it: the DOE hash, solver and parser versions, the date of generation, and the list of rejected runs with reasons. This is not bureaucracy; it is what allows a later reviewer to distinguish a genuine accuracy improvement from a change in the data. When the surrogate underperforms, the first question is always whether the training data changed, and provenance answers it in seconds rather than days.

A useful discipline is to treat the dataset as an immutable release. Once a version is tagged and used for training, it is never edited in place; corrections produce a new version with a changelog. This keeps model comparisons honest and makes rollback trivial.

With a clean, well-structured, and fully documented dataset in hand, the surrogate training stage can proceed on solid ground. The effort invested here — in sampling design, batch reliability, deterministic extraction, and auditable cleaning — is what separates a surrogate that generalizes from one that merely fits the runs it was given.