|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +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. |
| 8 | + |
| 9 | +## Build & Development |
| 10 | + |
| 11 | +**Prerequisites:** Nix (provides GHC 9.6.x, Stack, Cabal, HLS, Lefthook, formatters). |
| 12 | + |
| 13 | +```bash |
| 14 | +nix develop # Enter dev shell |
| 15 | +stack build # Build entire monorepo |
| 16 | +stack build <package> # Build single package (e.g. stack build sledge) |
| 17 | +stack exec virmatgen -- --help # Run the CLI executable |
| 18 | +``` |
| 19 | + |
| 20 | +CI runs: `nix fmt -- --ci` (format check) then `nix develop --command stack build --system-ghc`. |
| 21 | + |
| 22 | +## Testing |
| 23 | + |
| 24 | +Tests are gated behind cabal flags (default: off). To run: |
| 25 | + |
| 26 | +```bash |
| 27 | +stack test sledge --flag sledge:tests # sledge test suite (tasty + QuickCheck) |
| 28 | +stack test queryforest --flag queryforest:test # queryforest tests |
| 29 | +stack build DeUni --flag DeUni:test # DeUni test executables (not a test-suite, uses diagrams/SVG) |
| 30 | +stack build hammer --flag hammer:test # hammer benchmark/profile executables |
| 31 | +``` |
| 32 | + |
| 33 | +## Formatting |
| 34 | + |
| 35 | +Formatting is enforced by Lefthook pre-commit hooks and CI. Three formatters via treefmt.nix: |
| 36 | +- **Fourmolu** — Haskell (.hs) |
| 37 | +- **cabal-fmt** — Cabal files (.cabal) |
| 38 | +- **nixpkgs-fmt** — Nix files (.nix) |
| 39 | + |
| 40 | +```bash |
| 41 | +nix fmt # Format all files |
| 42 | +nix fmt -- --ci # Check formatting without modifying (CI mode) |
| 43 | +``` |
| 44 | + |
| 45 | +## Monorepo Structure |
| 46 | + |
| 47 | +All packages are git submodules under `packages/`. The root `stack.yaml` (resolver: lts-22.11, `allow-newer: true`) ties them together. |
| 48 | + |
| 49 | +### Package Dependency Graph |
| 50 | + |
| 51 | +``` |
| 52 | +VirMat (root executable + library) |
| 53 | +├── DeUni — Delaunay triangulation (DeWall/MBC algorithm) |
| 54 | +├── SubZero — Subdivision surfaces (Loop scheme) |
| 55 | +│ ├── hammer |
| 56 | +│ └── linear-vect |
| 57 | +├── hammer — Microstructure graph, grain topology, sparse matrices |
| 58 | +│ ├── linear-vect |
| 59 | +│ ├── mcl |
| 60 | +│ └── VTK |
| 61 | +├── sledge — Crystallography: rotations, Bingham distributions, EBSD I/O |
| 62 | +│ ├── hammer |
| 63 | +│ ├── linear-vect |
| 64 | +│ └── queryforest |
| 65 | +├── queryforest — Spatial indexing: KD-trees, VP-trees |
| 66 | +├── linear-vect — Vec2/3/4, Mat2/3/4, quaternions (BSD-3-Clause fork) |
| 67 | +├── mcl — Markov Cluster Algorithm |
| 68 | +└── VTK — VTK XML file generation |
| 69 | +``` |
| 70 | + |
| 71 | +### Generation Pipeline (root library) |
| 72 | + |
| 73 | +The `virmatgen` executable dispatches to `VirMat.Run2D` or `VirMat.Run3D` based on `--2d`/`--3d` flags. The pipeline is: |
| 74 | + |
| 75 | +1. **Sampling** (`Core.Sampling`) — Draw grain sizes from LogNormal/Normal/Uniform/Custom distributions via inverse-CDF |
| 76 | +2. **Packing** (`Core.Packer`) — Pack spheres/circles using Verlet integration |
| 77 | +3. **Voronoi** (`Core.VoronoiMicro`) — Build Delaunay triangulation (DeUni), extract Voronoi dual |
| 78 | +4. **Subdivision** (`Core.FlexMicro`) — Apply Loop subdivision surfaces (SubZero) for smooth grain boundaries |
| 79 | +5. **Texture** (`Distributions.Texture.ODFSampling`) — Sample crystallographic orientations via Bingham distributions (sledge) |
| 80 | +6. **Export** (`IO.Export`) — Write VTK files and ANG grids with rasterized triangle data |
| 81 | + |
| 82 | +## Development Approach |
| 83 | + |
| 84 | +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. |
| 85 | + |
| 86 | +## Git Conventions |
| 87 | + |
| 88 | +- **No footer on commit messages.** Do not add `Co-Authored-By` or any other footer lines. |
| 89 | +- Keep commit messages concise and descriptive. |
| 90 | + |
| 91 | +## Submodule Workflow |
| 92 | + |
| 93 | +Packages are git submodules under `packages/`. Submodules are typically in **detached HEAD** state after checkout. |
| 94 | + |
| 95 | +### Committing changes to a submodule |
| 96 | + |
| 97 | +1. `cd packages/<name>` |
| 98 | +2. Stage and commit your changes (this creates a commit on the detached HEAD) |
| 99 | +3. Update the local master branch to include your commit: `git branch -f master HEAD` |
| 100 | +4. Return to root and commit the updated submodule ref |
| 101 | + |
| 102 | +### Pushing |
| 103 | + |
| 104 | +Push submodules **before** the root, since the root records submodule commit refs: |
| 105 | + |
| 106 | +```bash |
| 107 | +# For each changed submodule: |
| 108 | +cd packages/<name> |
| 109 | +git branch -f master HEAD # Point master at the detached HEAD commit |
| 110 | +git push origin master |
| 111 | +cd ../.. |
| 112 | + |
| 113 | +# Then push root: |
| 114 | +git push origin master |
| 115 | +``` |
| 116 | + |
| 117 | +### Pulling |
| 118 | + |
| 119 | +```bash |
| 120 | +git pull --recurse-submodules |
| 121 | +git submodule update --init --recursive |
| 122 | +``` |
| 123 | + |
| 124 | +## Licensing |
| 125 | + |
| 126 | +All packages are MIT except `linear-vect` which is BSD-3-Clause (fork with upstream copyright holders). |
0 commit comments