2. Version control fundamentals for CAE automation

CAE automation assets are not ordinary source files. A single simulation workflow typically spans Python driver scripts, solver input decks (for example *.inp, *.key, *.jou), material libraries, mesh files, boundary-condition templates, and post-processing macros. These artifacts evolve at different rates, are edited by different specialists, and often must be reproduced months later for a certification or audit. Git gives you the machinery to track that evolution, but only if you understand what a repository, a commit, a branch, and a merge actually represent in this context.

Repositories: the unit of reproducibility

A Git repository is a directed acyclic graph of snapshots plus a set of references (branches, tags) pointing into that graph. For CAE automation, the practical question is what belongs in one repository. The rule of thumb: everything required to regenerate a result from a clean checkout should live together, and everything that can be regenerated deterministically should be excluded.

Consider a crashworthiness automation project. The repository might contain:

  • drivers/ — Python scripts that parameterize and launch the solver
  • decks/ — Jinja2 or f-string templates that render solver input decks
  • materials/ — YAML or CSV material cards referenced by the templates
  • post/ — extraction scripts and report generators
  • tests/ — smoke tests that run a reduced model in CI

Large binary artifacts — solver result files (*.odb, *.rst, *.d3plot), meshes above a few megabytes, and license-locked binaries — should not be committed. Use .gitignore to exclude them and store them in an artifact repository or object store keyed by commit SHA. A useful .gitignore fragment for a CAE automation repo:

# Solver outputs
*.odb
*.rst
*.d3plot
*.sta
*.msg

# Local run directories
runs/
scratch/

# License and machine-specific config
*.lic
env.local.yaml

The commit SHA then becomes the reproducibility key: given a SHA, a CI job can check out the exact scripts and templates, fetch the matching mesh from the object store, and rerun the deck.

Commits: atomic, meaningful, and reviewable

A commit is a snapshot of the tracked tree plus metadata (author, timestamp, message, parent SHA). In CAE automation, the most common failure mode is the "mega-commit" that bundles a template change, a material update, and a driver refactor. When a regression appears three weeks later, git bisect cannot isolate the cause because each commit changes too much.

Prefer small, single-purpose commits. A good commit for a deck template change looks like this:

git add decks/frontal_impact.j2 materials/steel_dp780.yaml
git commit -m "deck: add strain-rate scaling to DP780 card

- template now emits *MAT_PIECEWISE_LINEAR_PLASTICITY with
  rate-dependent table when material.rate_sensitive is true
- DP780 card updated with Cowper-Symonds C=40, p=5
- refs: JIRA-CAE-1421"

The message states what changed, why, and links to the tracking issue. This matters because solver decks are often reviewed by CAE engineers who are not Git experts; a clear message is the primary review artifact.

Commit granularity heuristic: if you cannot describe the change in one sentence without using "and", split it. If the change touches both a template and the material data it consumes, they may belong together — but a driver refactor does not.

Branches: isolating parallel simulation campaigns

A branch is a movable pointer to a commit. In CAE automation, branches map naturally onto parallel workstreams: a baseline branch, a feature branch for a new solver interface, and a release branch for a validated deck set.

A typical topology:

  • main — always runnable; CI executes smoke tests on every push
  • feature/ls-dyna-interface — adds a new solver backend
  • release/2024-crash — frozen deck set for a certification campaign
  • hotfix/deck-units — urgent fix to a unit-conversion bug in a released deck

Branch naming should encode intent, not author. feature/, release/, and hotfix/ prefixes let CI rules and reviewers route work automatically. Avoid long-lived branches that diverge for months; they turn merges into archaeology.

Merges: integrating changes without losing provenance

A merge combines two lines of history. Git offers two strategies that matter here: fast-forward (when the target branch has no new commits) and three-way merge (when both branches advanced). For CAE automation, the three-way merge is where conflicts appear — typically in generated decks, material tables, or shared utility modules.

When a conflict occurs in a rendered deck, do not resolve it by hand-editing the generated file. Resolve it in the template or the data, then re-render. This keeps the source of truth in version control and the generated artifact reproducible.

git checkout main
git merge feature/ls-dyna-interface
# CONFLICT in decks/frontal_impact.j2
# Edit the template, not the rendered deck
git add decks/frontal_impact.j2
git commit -m "merge: integrate LS-DYNA backend, resolve template conflict"

For release branches, prefer git merge --no-ff so the merge commit records the integration point. This makes it possible to answer "which feature commits are in release/2024-crash?" with git log --merges.

Do not rebase shared branches. Rebasing rewrites commit SHAs. If a colleague has already based a simulation campaign on a branch you rebase, their history diverges silently. Rebase only local, unshared work.

Putting it together: a reproducible CAE workflow

The diagram below shows how the four concepts connect in a typical CAE automation loop. A driver script reads a template and material data, renders a deck, launches the solver, and extracts results. Each stage is a tracked artifact; the commit SHA ties them together.

CAE Automation Artifacts and Git References Repository (tracked) drivers/run_sim.py decks/frontal_impact.j2 materials/steel_dp780.yaml post/extract_energy.py .gitignore (excludes *.odb, runs/) Commit Graph A B C D E M main feature/ls-dyna merge commit Commit SHA ties artifacts to results: a3f9c21 → deck + mesh + solver run snapshot

In practice, the loop is: edit a template or material card, commit with a descriptive message, push to a feature branch, open a merge request, let CI render the deck and run a reduced smoke test, then merge into main. The commit SHA recorded in the CI log is the reproducibility key for that simulation campaign.

Common pitfalls in CAE repositories

Symptom Root cause Fix
Repository grows to several GB Binary solver outputs committed Add .gitignore; use git filter-repo to purge history
Merge conflicts in rendered decks Generated files tracked alongside templates Track templates only; render in CI
Cannot reproduce an old result Mesh or material data stored outside Git Key external artifacts by commit SHA
Bisect finds nothing useful Mega-commits mixing unrelated changes Enforce single-purpose commits in review

The next step is to apply these fundamentals to a concrete automation repository: initialize it, define the ignore rules, and establish the branch and merge conventions that CI will enforce.