|
1 | | -# VirMat: Virtual Microstructure Generator |
| 1 | +# VirMat |
2 | 2 |
|
3 | | -**VirMat** is a high-performance 2D and 3D virtual microstructure generator written in Haskell, designed for metallurgical and materials science research. It creates synthetic polycrystalline microstructures with user-defined grain size distributions and crystallographic textures, producing output suitable for visualization in [ParaView](https://www.paraview.org/) and analysis with EBSD software. |
| 3 | +Virtual microstructure generator for 2D and 3D polycrystalline materials. |
4 | 4 |
|
5 | | -## Core Features |
| 5 | +## What is this? |
6 | 6 |
|
7 | | -- **2D and 3D generation** -- produce microstructures in either dimensionality from a single CLI. |
8 | | -- **Statistical grain size control** -- specify Log-Normal, Normal, Uniform, or custom grain diameter distributions; combine multiple distributions for multi-modal populations. |
9 | | -- **Sphere/circle packing** -- optional iterative packing (Verlet integration with damping) to obtain realistic, non-overlapping grain seed placement before tessellation. |
10 | | -- **Voronoi tessellation** -- Delaunay triangulation (DeWall algorithm) followed by dual Voronoi construction via `MicroGraph`. |
11 | | -- **Subdivision surfaces** -- Voronoi facets are converted to Loop subdivision surfaces (`SubZero`) so grain boundaries can be smoothly refined to arbitrary resolution. |
12 | | -- **Crystallographic texture** -- orientations sampled from a Bingham distribution are assigned per grain; IPF coloring is rendered into VTK attributes. |
13 | | -- **Phase transformation** -- a parent microstructure can be overlaid with a finer product microstructure and each product grain inherits the parent grain identity. |
14 | | -- **Export formats** |
15 | | - - VTK Unstructured Grid (`.vtu`) for 3D/2D visualization in ParaView. |
16 | | - - ANG (`.ang`) for 2D EBSD-like data analysis (rasterized from the subdivision mesh). |
| 7 | +VirMat generates synthetic polycrystalline microstructures -- the kind of grain structures you see when you look at a metal under a microscope. Given a statistical description of grain sizes (e.g., "log-normal distribution with mean 5 micrometers"), VirMat produces a realistic 3D (or 2D) arrangement of grains with smooth boundaries, crystallographic orientations, and morphological properties. |
17 | 8 |
|
18 | | -## Architecture Overview |
| 9 | +The output can be visualized in [ParaView](https://www.paraview.org/) (VTK format) or analyzed with EBSD software like OIM or MTEX (ANG format). |
19 | 10 |
|
20 | | -### Generation Pipeline |
| 11 | +## Why generate virtual microstructures? |
21 | 12 |
|
22 | | -``` |
23 | | -JobRequest (CLI) |
24 | | - | |
25 | | - v |
26 | | -Grain Size Sampling -- Core.Sampling + Distributions.GrainSize |
27 | | - | (inverse-CDF sampling from composed multi-distributions) |
28 | | - v |
29 | | -Weighted Point Cloud -- GrainDistributionGenerator |
30 | | - | (circles/spheres with diameter-derived radii) |
31 | | - v |
32 | | -[Optional] Sphere Packing -- Core.Packer (Verlet integration, N iterations) |
33 | | - | |
34 | | - v |
35 | | -Delaunay Triangulation -- DeUni (DeWall algorithm, 2D or 3D) |
36 | | - | |
37 | | - v |
38 | | -Voronoi Micro-graph -- Core.VoronoiMicro (dual of Delaunay -> MicroGraph) |
39 | | - | |
40 | | - v |
41 | | -FlexMicro (Subdivision) -- Core.FlexMicro (Loop subdivision surfaces via SubZero) |
42 | | - | |
43 | | - +---> Texture Assignment -- Distributions.Texture.ODFSampling (Bingham sampling) |
44 | | - | |
45 | | - +---> Morphology Query -- Distributions.GrainSize.GrainQuery (area, volume, neighbors) |
46 | | - | |
47 | | - +---> VTK Rendering -- FlexMicro.renderFlexMicro -> .vtu files |
48 | | - | |
49 | | - +---> ANG Rasterization -- IO.Export.ANG.RasterEngine -> .ang files |
50 | | - | |
51 | | - +---> Phase Transformation -- PhaseTrans (parent/product overlay) |
52 | | -``` |
53 | | - |
54 | | -### Data Flow Types |
55 | | - |
56 | | -| Type | Description | |
57 | | -|------|-------------| |
58 | | -| `JobRequest` | Parsed CLI parameters: dimension, grain count/box size, distribution, seed | |
59 | | -| `DistributedPoints v` | Bounding box + weighted point cloud (`SetPoint v`) | |
60 | | -| `Simulation v` | Full state: box, points, Delaunay triangulation, Voronoi micro-graph | |
61 | | -| `FlexMicro v a` | Subdivision-surface microstructure with per-grain property `a` | |
62 | | -| `GrainMorph v` | Computed morphological properties (center, length, area, volume, neighbor count) | |
63 | | - |
64 | | -## Packages |
65 | | - |
66 | | -VirMat is organized as a multi-package Haskell project. The root package orchestrates the generation pipeline, while specialized functionality is pulled from several core libraries via `cabal.project` (previously git submodules): |
67 | | - |
68 | | -| Package | Description | |
69 | | -|---------|-------------| |
70 | | -| [DeUni](https://github.com/lostbean/DeUni) | 3D Convex Hull and Delaunay triangulation using the Marriage-Before-Conquer (MBC) / DeWall algorithm | |
71 | | -| [hammer](https://github.com/lostbean/hammer) | Metallurgical utilities: `MicroGraph` topology, grain finding, sparse matrices, and VTK generation | |
72 | | -| [sledge](https://github.com/lostbean/sledge) | Crystallographic orientations, symmetries, Bingham distributions, IPF coloring, and EBSD file formats (ANG, CTF) | |
73 | | -| [linear-vect](https://github.com/lostbean/linear-vect) | Low-dimensional linear algebra: `Vec2`, `Vec3`, `Vec4`, matrices, quaternions | |
74 | | -| [queryforest](https://github.com/lostbean/queryforest) | Spatial indexing and nearest-neighbor search (KD-trees, VP-trees) | |
75 | | -| [SubZero](https://github.com/lostbean/SubZero) | Subdivision surfaces for 1D (lines/curves) and 2D (triangular meshes, Loop scheme) | |
76 | | -| [VTK](https://github.com/lostbean/VTK) | Library for generating VTK XML files (`.vtu`, `.vti`, etc.) | |
77 | | -| [mcl](https://github.com/lostbean/mcl) | Markov Cluster Algorithm (MCL) for graph clustering | |
78 | | - |
79 | | -## Key Modules and Source Files |
80 | | - |
81 | | -### Entry Point |
82 | | - |
83 | | -| File | Module | Role | |
84 | | -|------|--------|------| |
85 | | -| `src/Main.hs` | `Main` | CLI entry point; dispatches to `go2D` or `go3D` based on `--2d`/`--3d` flag | |
86 | | - |
87 | | -### Core Library (`VirMat.*`) |
88 | | - |
89 | | -| File | Module | Role | |
90 | | -|------|--------|------| |
91 | | -| `src/VirMat/Types.hs` | `VirMat.Types` | `Simulation` record: box, point set, triangulation, grain set | |
92 | | -| `src/VirMat/Run2D.hs` | `VirMat.Run2D` | 2D pipeline: sample points, optional packing, Delaunay, Voronoi | |
93 | | -| `src/VirMat/Run3D.hs` | `VirMat.Run3D` | 3D pipeline: same stages for 3D | |
94 | | -| `src/VirMat/Core/Sampling.hs` | `VirMat.Core.Sampling` | Statistical distributions (LogNormal, Normal, Uniform, Custom), inverse-CDF sampling | |
95 | | -| `src/VirMat/Core/Packer.hs` | `VirMat.Core.Packer` | Iterative sphere/circle packing via Verlet integration with force model and damping | |
96 | | -| `src/VirMat/Core/VoronoiMicro.hs` | `VirMat.Core.VoronoiMicro` | Converts Delaunay simplices to Voronoi `MicroGraph` (dual construction) | |
97 | | -| `src/VirMat/Core/FlexMicro.hs` | `VirMat.Core.FlexMicro` | Converts Voronoi polygons/polyhedra to Loop subdivision surfaces; VTK rendering | |
98 | | - |
99 | | -### Distributions |
100 | | - |
101 | | -| File | Module | Role | |
102 | | -|------|--------|------| |
103 | | -| `src/VirMat/Distributions/GrainSize/GrainDistributionGenerator.hs` | `...GrainDistributionGenerator` | Generates weighted point clouds by grain count or bounding box volume | |
104 | | -| `src/VirMat/Distributions/GrainSize/GrainQuery.hs` | `...GrainQuery` | Computes per-grain morphological properties from subdivision meshes | |
105 | | -| `src/VirMat/Distributions/Texture/ODFSampling.hs` | `...ODFSampling` | Assigns Bingham-sampled crystallographic orientations to grains; IPF RGB coloring | |
106 | | - |
107 | | -### I/O |
108 | | - |
109 | | -| File | Module | Role | |
110 | | -|------|--------|------| |
111 | | -| `src/VirMat/IO/Import/CommandLine.hs` | `...CommandLine` | CLI parser (optparse-applicative) | |
112 | | -| `src/VirMat/IO/Import/Types.hs` | `...Import.Types` | `JobRequest`, `Dimension`, `StructureSize`, `DistributionType`, `Output` | |
113 | | -| `src/VirMat/IO/Export/ANG/RasterEngine.hs` | `...ANG.RasterEngine` | Triangle rasterization engine that converts `FlexMicro` grains to an ANG grid | |
114 | | -| `src/VirMat/IO/Export/VTK/VTKODFRender.hs` | `...VTK.VTKODFRender` | Renders a discrete ODF to a VTK ImageData (`.vti`) file | |
115 | | - |
116 | | -### Other |
117 | | - |
118 | | -| File | Module | Role | |
119 | | -|------|--------|------| |
120 | | -| `src/VirMat/PhaseTrans.hs` | `VirMat.PhaseTrans` | Phase transformation simulation: parent/product microstructure overlay | |
121 | | - |
122 | | -## Building |
123 | | - |
124 | | -### Prerequisites |
125 | | - |
126 | | -- [Cabal](https://www.haskell.org/cabal/) or [Stack](https://docs.haskellstack.org/en/stable/) |
127 | | -- GHC 9.10.x (recommended) |
128 | | - |
129 | | -### With Cabal |
130 | | - |
131 | | -```bash |
132 | | -git clone <repo-url> |
133 | | -cd VirMat |
134 | | - |
135 | | -# Build the entire project and dependencies |
136 | | -cabal build |
137 | | - |
138 | | -# Run the executable |
139 | | -cabal run virmatgen -- --help |
140 | | -``` |
141 | | - |
142 | | -### With Stack |
| 13 | +Real microstructure characterization is expensive and limited: EBSD scans are 2D slices, serial sectioning is destructive, and 3D EBSD is still slow and costly. Virtual microstructures provide: |
143 | 14 |
|
144 | | -```bash |
145 | | -git clone <repo-url> |
146 | | -cd VirMat |
| 15 | +- **Input for simulations** -- finite element models, crystal plasticity simulations, and phase-field models need realistic starting microstructures |
| 16 | +- **Statistical validation** -- compare simulated grain size distributions, neighbor counts, and morphological properties against experimental data |
| 17 | +- **Parametric studies** -- vary grain size, texture, or packing without needing new experiments |
| 18 | +- **3D structure from 2D statistics** -- generate full 3D microstructures from grain size distributions measured on 2D cross-sections |
147 | 19 |
|
148 | | -# Build the entire project |
149 | | -stack build |
| 20 | +## The generation pipeline |
150 | 21 |
|
151 | | -# Run the executable |
152 | | -stack exec virmatgen -- --help |
153 | | -``` |
| 22 | +### 1. Grain size sampling |
154 | 23 |
|
155 | | -### With Nix (development shell) |
| 24 | +Grain sizes are drawn from user-specified statistical distributions. Supported distributions: |
156 | 25 |
|
157 | | -The project provides a Nix flake for a reproducible development environment: |
| 26 | +- **Log-normal** -- the most common grain size distribution in real materials |
| 27 | +- **Normal** -- symmetric distribution |
| 28 | +- **Uniform** -- constant probability within bounds |
| 29 | +- **Custom** -- arbitrary histogram |
| 30 | +- **Composed** -- combine multiple distributions for multi-modal populations (e.g., bimodal grain sizes after partial recrystallization) |
158 | 31 |
|
159 | | -```bash |
160 | | -# Enter the dev shell (provides GHC, Stack, Cabal, HLS, zlib, clang, treefmt) |
161 | | -nix develop |
| 32 | +Sampling uses inverse-CDF (cumulative distribution function) interpolation. |
162 | 33 |
|
163 | | -# Then build with Cabal or Stack as usual |
164 | | -cabal build |
165 | | -``` |
| 34 | +### 2. Sphere packing |
166 | 35 |
|
167 | | -## Testing |
| 36 | +Grain seed points are placed as spheres/circles with diameters corresponding to the sampled grain sizes. An optional iterative packing step uses Verlet integration with a force model (quadratic repulsion for overlaps, attraction for free space) to arrange grains into a realistic, non-overlapping configuration. |
168 | 37 |
|
169 | | -VirMat includes a comprehensive test suite using `hspec` and `QuickCheck`. |
| 38 | +### 3. Voronoi tessellation |
170 | 39 |
|
171 | | -```bash |
172 | | -# Run all tests |
173 | | -cabal test |
| 40 | +The packed seed points are triangulated using Delaunay triangulation (via `DeUni`), then the geometric dual -- the Voronoi tessellation -- is extracted. Each Voronoi cell becomes a grain. The Voronoi dual is stored as a microstructure graph (via `hammer`) encoding grains, grain boundaries (faces), triple lines (edges), and quadruple points (vertices). |
174 | 41 |
|
175 | | -# Run tests with coverage report |
176 | | -cabal test --enable-coverage |
177 | | -``` |
| 42 | +### 4. Subdivision smoothing |
178 | 43 |
|
179 | | -The test suite covers: |
180 | | -- **Core.Packer**: Force models and bounding box constraints. |
181 | | -- **Core.Sampling**: Statistical distribution area, mean, and composition. |
182 | | -- **Distributions.GrainSize**: Bounding box geometry and volumetric consistency. |
183 | | -- **GrainQuery**: Geometric primitives (triangle area, tetrahedron volume). |
| 44 | +The flat-faceted Voronoi polyhedra are refined using Loop subdivision surfaces (via `SubZero`). A few levels of subdivision produce smooth, realistic grain boundaries suitable for visualization and analysis. |
184 | 45 |
|
185 | | -## CLI Usage |
| 46 | +### 5. Texture assignment |
186 | 47 |
|
187 | | -The primary executable is `virmatgen`. It generates microstructures based on command-line parameters. |
| 48 | +Each grain is assigned a crystallographic orientation sampled from a Bingham distribution (via `sledge`). Inverse Pole Figure (IPF) colors are computed and attached as VTK attributes for visualization. |
188 | 49 |
|
189 | | -``` |
190 | | -virmatgen - Virtual microstructure generator in 3D/2D. |
191 | | -
|
192 | | -Usage: virmatgen [--3d | --2d] |
193 | | - [--n2d INT | --n2d (DOUBLE,DOUBLE)] |
194 | | - [--packed-n INT | --packed | --random] |
195 | | - [--lnorm (k,mu,mode,o) | --norm (k,mu,s) | --uniform (k,mu,s)] ... |
196 | | - [--seed INT] |
197 | | - -d FILEPATH -s STR |
198 | | - [--showvoronoi] [--showbox] [--showhull] |
199 | | - [--showpoints] [--showsimplex] [--showforces] |
200 | | -``` |
| 50 | +### 6. Export |
201 | 51 |
|
202 | | -### Key Options |
| 52 | +- **VTK** (`.vtu`) -- 3D and 2D microstructures with grain ID, volume, area, neighbor count, and IPF coloring |
| 53 | +- **ANG** (`.ang`) -- 2D orientation map rasterized from the subdivision mesh, compatible with EBSD analysis tools |
203 | 54 |
|
204 | | -| Flag | Description | Default | |
205 | | -|------|-------------|---------| |
206 | | -| `--3d` / `--2d` | Dimensionality of the microstructure | `--3d` | |
207 | | -| `--n2d INT` | Number of grains | `500` | |
208 | | -| `--packed` | Enable sphere packing (60 iterations) | enabled | |
209 | | -| `--packed-n INT` | Sphere packing with custom iteration count | -- | |
210 | | -| `--random` | Random (non-packed) grain placement | -- | |
211 | | -| `--lnorm (k,mu,mode,o)` | Log-Normal grain size distribution | -- | |
212 | | -| `--norm (k,mu,s)` | Normal grain size distribution | -- | |
213 | | -| `--uniform (k,mu,s)` | Uniform grain size distribution | -- | |
214 | | -| `--seed INT` | Random seed for reproducibility | system random | |
215 | | -| `-d FILEPATH` | Output directory | required | |
216 | | -| `-s STR` | Sample name | required | |
217 | | - |
218 | | -Distribution parameters: `k` = scaling factor, `mu` = average/mean, `s` = variance, `mode` = distribution mode, `o` = offset. Multiple `--lnorm`, `--norm`, and `--uniform` flags can be combined for multi-modal distributions. |
| 55 | +## Ecosystem packages |
219 | 56 |
|
220 | | -### Output Files |
| 57 | +VirMat orchestrates several specialized libraries: |
221 | 58 |
|
222 | | -| File | Format | Content | |
223 | | -|------|--------|---------| |
224 | | -| `virmat-3d.vtu` | VTK Unstructured Grid | 3D microstructure with grain ID, volume, area, neighbor count, and IPF-ND coloring | |
225 | | -| `virmat-2d.vtu` | VTK Unstructured Grid | 2D microstructure with grain ID, area, boundary length, and neighbor count | |
226 | | -| `virmat-2d.ang` | ANG (EBSD) | Rasterized 2D orientation map for EBSD analysis tools (OIM, MTEX, etc.) | |
| 59 | +| Package | Role | |
| 60 | +|---------|------| |
| 61 | +| [DeUni](https://github.com/lostbean/DeUni) | Delaunay triangulation (Marriage Before Conquer algorithm) | |
| 62 | +| [hammer](https://github.com/lostbean/hammer) | Microstructure graph, grain finding, VTK export | |
| 63 | +| [sledge](https://github.com/lostbean/sledge) | Crystallographic orientations, Bingham distributions, EBSD I/O | |
| 64 | +| [linear-vect](https://github.com/lostbean/linear-vect) | Low-dimensional linear algebra (vectors, matrices) | |
| 65 | +| [queryforest](https://github.com/lostbean/queryforest) | Spatial indexing (VP-trees, KD-trees) | |
| 66 | +| [SubZero](https://github.com/lostbean/SubZero) | Subdivision surfaces (Loop scheme) | |
| 67 | +| [VTK](https://github.com/lostbean/VTK) | VTK XML file generation | |
| 68 | +| [mcl](https://github.com/lostbean/mcl) | Markov Cluster Algorithm for graph clustering | |
227 | 69 |
|
228 | | -### Example |
| 70 | +## Example |
229 | 71 |
|
230 | 72 | ```bash |
231 | | -# Generate a 3D microstructure with 200 grains, log-normal size distribution, packed |
232 | | -stack exec virmatgen -- --3d --n2d 200 --packed \ |
| 73 | +# 3D microstructure, 200 grains, log-normal distribution, packed |
| 74 | +virmatgen --3d --n2d 200 --packed \ |
233 | 75 | --lnorm '(1.0, 5.0, 3.0, 0.0)' \ |
234 | 76 | --seed 42 \ |
235 | 77 | -d ./output -s mysample |
236 | 78 |
|
237 | | -# Generate a 2D microstructure with normal distribution, 100 grains |
238 | | -stack exec virmatgen -- --2d --n2d 100 --packed \ |
| 79 | +# 2D microstructure, 100 grains, normal distribution |
| 80 | +virmatgen --2d --n2d 100 --packed \ |
239 | 81 | --norm '(1.0, 5.0, 1.0)' \ |
240 | 82 | --seed 42 \ |
241 | 83 | -d ./output -s mysample2d |
242 | 84 | ``` |
243 | 85 |
|
244 | | -## Dependencies |
| 86 | +### Key CLI options |
245 | 87 |
|
246 | | -### Haskell (from Hackage) |
| 88 | +| Flag | Description | Default | |
| 89 | +|------|-------------|---------| |
| 90 | +| `--3d` / `--2d` | Dimensionality | 3D | |
| 91 | +| `--n2d INT` | Number of grains | 500 | |
| 92 | +| `--packed` / `--packed-n INT` | Enable packing (with optional iteration count) | 60 iterations | |
| 93 | +| `--random` | Random placement (no packing) | -- | |
| 94 | +| `--lnorm (k,mu,mode,o)` | Log-normal distribution | -- | |
| 95 | +| `--norm (k,mu,s)` | Normal distribution | -- | |
| 96 | +| `--uniform (k,mu,s)` | Uniform distribution | -- | |
| 97 | +| `--seed INT` | Random seed | system random | |
| 98 | +| `-d FILEPATH` | Output directory | required | |
| 99 | +| `-s STR` | Sample name | required | |
247 | 100 |
|
248 | | -`base`, `containers`, `mersenne-random-pure64`, `mtl`, `optparse-applicative`, `random`, `random-fu`, `transformers`, `unordered-containers`, `vector` |
| 101 | +Multiple distribution flags can be combined for multi-modal grain size populations. |
249 | 102 |
|
250 | | -### Internal Packages |
| 103 | +## How to build |
251 | 104 |
|
252 | | -These are managed via `cabal.project` and `stack.yaml` as source-repository-packages: |
253 | | -`DeUni`, `hammer`, `sledge`, `linear-vect`, `SubZero`, `queryforest`, `VTK`, `mcl` |
| 105 | +```bash |
| 106 | +# With Nix (recommended) |
| 107 | +nix develop |
| 108 | +cabal build |
254 | 109 |
|
255 | | -## Author |
| 110 | +# With Stack |
| 111 | +stack build |
256 | 112 |
|
257 | | -Edgar Gomes de Araujo (<talktoedgar@gmail.com>) |
| 113 | +# Run the executable |
| 114 | +cabal run virmatgen -- --help |
| 115 | + |
| 116 | +# Run tests |
| 117 | +cabal test |
| 118 | +``` |
258 | 119 |
|
259 | 120 | ## License |
260 | 121 |
|
|
0 commit comments