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 solverdecks/— Jinja2 or f-string templates that render solver input decksmaterials/— YAML or CSV material cards referenced by the templatespost/— extraction scripts and report generatorstests/— 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.
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 pushfeature/ls-dyna-interface— adds a new solver backendrelease/2024-crash— frozen deck set for a certification campaignhotfix/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.
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.
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.