2. Audit Input Deck and Material Calibration Traceability

Why Traceability Is the First Real Validation Gate

An injury-prediction CAE model is only as defensible as the weakest input it contains. Before any solver run can be trusted, every material parameter, boundary condition, and contact definition must be answerable to a source: a coupon test, a calibration record, a supplier datasheet, a regulatory reference, or an explicit engineering assumption. This case builds a traceability matrix that maps each input to its provenance and classifies it as validated, assumed, or unsupported. The output is not a report for its own sake — it is the audit trail that later cases (mesh convergence, solver verification, correlation) will lean on.

The distinction that matters throughout is between three provenance states:

  • Validated — the value is traceable to a test or calibration record with a documented method, specimen, and date, and the value used in the deck matches that record within a stated tolerance.
  • Assumed — the value is a deliberate engineering estimate (literature default, conservative bound, or expert judgment) with a stated rationale and a sensitivity note. Assumed inputs are acceptable if flagged and bounded.
  • Unsupported — the value has no identifiable source, or the deck value disagrees with the cited source beyond tolerance. Unsupported inputs block validation sign-off until resolved.

The Traceability Matrix Structure

A workable matrix has one row per input instance, not one row per material. The same material used in two body regions with different strain rates is two rows. Each row carries the fields below; the granularity is what makes the audit reproducible.

Field Content Example
Input ID Stable identifier referenced by the deck MAT-LIVER-01
Deck location Keyword, part, or set where the value appears *MAT_ELASTIC, part 1042
Parameter Named quantity and units Young's modulus, MPa
Deck value Value as written in the input deck 12.5
Source record Test/calibration ID, report, or datasheet CAL-2023-07, Table 3
Source value Value in the source, converted to deck units 12.8
Delta / tolerance Absolute and relative difference vs. allowed tolerance −0.3 MPa, 2.3% (tol 5%)
Status Validated / Assumed / Unsupported Validated
Rationale / action Why assumed, or what resolves an unsupported flag —

The delta / tolerance column is the audit's teeth. A value that matches its source to within tolerance is validated; a value that drifts beyond tolerance is unsupported even if a source exists, because the deck no longer represents the test. Tolerances should be set per parameter class — modulus and density are typically tight (2–5%), while rate-dependent failure strains may legitimately carry 10–15% scatter from the underlying test.

Extracting Inputs from the Deck

The audit starts by enumerating every parameter the deck actually consumes, not by trusting a material summary someone wrote earlier. For a typical LS-DYNA injury model, the relevant keyword blocks are *MAT_* (material), *BOUNDARY_* (constraints and prescribed motion), and *CONTACT_* (contact definitions). A minimal extraction pass can be scripted so the matrix is regenerated whenever the deck changes:

import re, csv

DECK = "injury_model_v3.k"
KEYWORDS = ("*MAT_", "*BOUNDARY_", "*CONTACT_")

def extract_blocks(path):
    blocks, current = [], None
    with open(path) as f:
        for line in f:
            s = line.rstrip("\n")
            if s.startswith("*"):
                if current:
                    blocks.append(current)
                current = {"keyword": s.strip(), "lines": []}
            elif current is not None and s.strip():
                current["lines"].append(s)
    if current:
        blocks.append(current)
    return [b for b in blocks if b["keyword"].upper().startswith(KEYWORDS)]

def to_rows(blocks):
    rows = []
    for b in blocks:
        kw = b["keyword"].split()[0].upper()
        for i, ln in enumerate(b["lines"]):
            rows.append({"keyword": kw, "line_no": i + 1, "raw": ln.strip()})
    return rows

if __name__ == "__main__":
    rows = to_rows(extract_blocks(DECK))
    with open("deck_inputs.csv", "w", newline="") as f:
        w = csv.DictWriter(f, fieldnames=["keyword", "line_no", "raw"])
        w.writeheader()
        w.writerows(rows)
    print(f"extracted {len(rows)} input lines from {DECK}")

This produces deck_inputs.csv — a flat, reviewable list of every material, boundary, and contact line. The script does not interpret values; it guarantees completeness so nothing is silently skipped. Interpretation (which field is modulus, which is density) is done by the auditor against the keyword manual, and the resulting parameter rows are appended to the traceability matrix. Running the script on a revised deck and diffing the CSV against the previous run is the fastest way to catch an input that changed without a corresponding source update.

Reading the Audit at a Glance

The SVG below shows how the three input classes flow from deck extraction through provenance lookup to a status decision, and how the statuses aggregate into the sign-off gate. It is the mental model the matrix encodes.

Input Deck Audit: Provenance to Sign-off Gate Deck Inputs *MAT_* material params *BOUNDARY_* constraints / motion *CONTACT_* contact defs deck_inputs.csv one row per input line Source Lookup Coupon test record CAL-2023-07 Calibration report curve fit, rate data Supplier datasheet nominal properties Engineering assumption rationale required delta vs. tolerance check Status Validated source + within tol Assumed rationale + bound Unsupported no source / drift action logged in matrix Sign-off Gate unsupported = 0 required assumed flagged + sensitivity noted matrix frozen for validation

Worked Audit Example

Consider three representative rows from a liver-region model. The deck uses a linear-elastic material for the capsule, a rate-dependent failure strain for the parenchyma, and a tied contact between capsule and parenchyma.

Input ID Parameter Deck value Source Source value Delta Status
MAT-CAP-01 E, MPa 12.5 CAL-2023-07 T3 12.8 −2.3% (tol 5%) Validated
MAT-PAR-02 ε_fail @ 10 s⁻¹ 0.28 CAL-2023-11 T5 0.31 −9.7% (tol 15%) Validated
CNT-CAP-PAR-01 Tiebreak stress, MPa 0.9 none — — Unsupported

The first two rows pass because the deck value sits inside the parameter-class tolerance of its source. The third row is the audit's real product: a contact tiebreak stress of 0.9 MPa with no cited record. It may be a reasonable guess, but it is currently unsupported, and the sign-off gate cannot close while it remains so. The resolution is either to locate a peel or lap-shear test that bounds the tiebreak stress, or to reclassify it as assumed with an explicit rationale (e.g., "bounded by capsule tensile strength; sensitivity run at 0.5 and 1.5 MPa planned") and a sensitivity note. Only the second path is acceptable if no test exists — and it must be written down, not remembered.

A common failure mode is treating a supplier datasheet as validated. Datasheets give nominal properties at a single condition; if the deck uses a rate-dependent or failure value that the datasheet does not cover, the row is assumed at best. Marking it validated inflates the audit's apparent coverage and defeats the purpose of the gate.

Deliverable: Traceability Matrix and Sign-off Record

The audit closes with two artifacts. The first is the matrix itself, exported as CSV with the nine fields above, one row per input instance, sorted by status so unsupported rows surface first. The second is a short sign-off record that states the counts and the disposition of every non-validated row:

TRACEABILITY SIGN-OFF — injury_model_v3.k
Audit date: (fill)        Auditor: (fill)
Total input rows:        142
  Validated:             118
  Assumed:                21   (all with rationale + sensitivity note)
  Unsupported:             3   (blocking)

Blocking rows:
  CNT-CAP-PAR-01  tiebreak stress 0.9 MPa   -> locate peel test or reclassify assumed
  BND-IMP-04      prescribed velocity 7.2 m/s -> confirm against sled test S-2023-02
  MAT-PAR-07      damping 0.15              -> no source; propose assumed w/ bound

Gate status: OPEN — 3 unsupported rows must be resolved or reclassified.
Next action: re-run deck_inputs.csv diff after corrections; re-audit changed rows only.

Two practical habits keep the matrix alive. First, regenerate deck_inputs.csv on every deck revision and diff it against the audited version — only changed rows need re-auditing, which keeps the cost of maintaining traceability proportional to the change, not the model size. Second, never let the matrix live only in a spreadsheet on one engineer's machine; version it alongside the deck so that the validation cases that follow can cite a specific matrix revision. When the mesh convergence and solver verification cases run, they inherit a model whose inputs are already classified, and any correlation gap can be attributed to modeling rather than to an undocumented material guess.

Set tolerances per parameter class before auditing, not after seeing the deltas. Choosing a tolerance once you know a value is 9% off invites rationalization; a pre-declared 5% modulus tolerance and 15% failure-strain tolerance makes the validated/unsupported call mechanical and defensible.