This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
VirMat is a Haskell monorepo for generating 2D/3D virtual microstructures for metallurgical research. It produces Voronoi-based grain structures with realistic size distributions and crystallographic textures, outputting VTK and ANG files.
Prerequisites: Nix (provides GHC 9.10.x, Stack, Cabal, HLS, Lefthook, formatters).
nix develop # Enter dev shell
stack build # Build entire monorepo
stack build <package> # Build single package (e.g. stack build sledge)
stack exec virmatgen -- --help # Run the CLI executableCI runs: nix fmt -- --ci (format check) then nix develop --command stack build --system-ghc.
bash scripts/ci.sh # Full CI: format check + build with -Wall -Werror + tests
bash scripts/pre-commit.sh # Apply formatting to all filesCI runs format check, compilation with -Wall -Werror (fail on warnings), and tests.
Local scripts use cabal-local.project which references sibling directories (../sledge, ../hammer, etc.). GitHub Actions CI uses the standard cabal.project which fetches deps from GitHub.
Tests are gated behind cabal flags (default: off). To run:
stack test sledge --flag sledge:tests # sledge test suite (tasty + QuickCheck)
stack test queryforest --flag queryforest:test # queryforest tests
stack build DeUni --flag DeUni:test # DeUni test executables (not a test-suite, uses diagrams/SVG)
stack build hammer --flag hammer:test # hammer benchmark/profile executablesFormatting is enforced by Lefthook pre-commit hooks and CI. Three formatters via treefmt.nix:
- Fourmolu — Haskell (.hs)
- cabal-fmt — Cabal files (.cabal)
- nixpkgs-fmt — Nix files (.nix)
nix fmt # Format all files
nix fmt -- --ci # Check formatting without modifying (CI mode)All packages are git submodules under packages/. The root stack.yaml (resolver: lts-24.34, allow-newer: true) ties them together.
VirMat (root executable + library)
├── DeUni — Delaunay triangulation (DeWall/MBC algorithm)
├── SubZero — Subdivision surfaces (Loop scheme)
│ ├── hammer
│ └── linear-vect
├── hammer — Microstructure graph, grain topology, sparse matrices
│ ├── linear-vect
│ ├── mcl
│ └── VTK
├── sledge — Crystallography: rotations, Bingham distributions, EBSD I/O
│ ├── hammer
│ ├── linear-vect
│ └── queryforest
├── queryforest — Spatial indexing: KD-trees, VP-trees
├── linear-vect — Vec2/3/4, Mat2/3/4, quaternions (BSD-3-Clause fork)
├── mcl — Markov Cluster Algorithm
└── VTK — VTK XML file generation
The virmatgen executable dispatches to VirMat.Run2D or VirMat.Run3D based on --2d/--3d flags. The pipeline is:
- Sampling (
Core.Sampling) — Draw grain sizes from LogNormal/Normal/Uniform/Custom distributions via inverse-CDF - Packing (
Core.Packer) — Pack spheres/circles using Verlet integration - Voronoi (
Core.VoronoiMicro) — Build Delaunay triangulation (DeUni), extract Voronoi dual - Subdivision (
Core.FlexMicro) — Apply Loop subdivision surfaces (SubZero) for smooth grain boundaries - Texture (
Distributions.Texture.ODFSampling) — Sample crystallographic orientations via Bingham distributions (sledge) - Export (
IO.Export) — Write VTK files and ANG grids with rasterized triangle data
Take a TDD (Test-Driven Development) approach: write or update tests first, verify they fail, then implement the change, then verify tests pass. When fixing bugs, first write a test that reproduces the bug before writing the fix.
- No footer on commit messages. Do not add
Co-Authored-Byor any other footer lines. - Keep commit messages concise and descriptive.
Packages are git submodules under packages/. Submodules are typically in detached HEAD state after checkout.
cd packages/<name>- Stage and commit your changes (this creates a commit on the detached HEAD)
- Update the local master branch to include your commit:
git branch -f master HEAD - Return to root and commit the updated submodule ref
Push submodules before the root, since the root records submodule commit refs:
# For each changed submodule:
cd packages/<name>
git branch -f master HEAD # Point master at the detached HEAD commit
git push origin master
cd ../..
# Then push root:
git push origin mastergit pull --recurse-submodules
git submodule update --init --recursiveAll packages are MIT except linear-vect which is BSD-3-Clause (fork with upstream copyright holders).