Add atomistic polycrystal generation with curved (APD) grain boundaries#7
Open
ligerzero-ai wants to merge 2 commits into
Open
Add atomistic polycrystal generation with curved (APD) grain boundaries#7ligerzero-ai wants to merge 2 commits into
ligerzero-ai wants to merge 2 commits into
Conversation
Introduce an opt-in `periodic` flag on `apd_system`. When enabled, every seed-to-point distance uses the minimum-image convention across the rectilinear domain, so the anisotropic power diagram becomes periodic and grains may wrap across the domain boundary. - new `periodic=False` constructor flag (fully backward-compatible) - `_displacement(y, x)` helper computing the minimum-image displacement as a KeOps LazyTensor via `dy - L * round(dy / L)` - all four `D_ij` computations (assemble_apd, OT_dual_function, check_optimality, adjust_X) route through `_displacement` - new public `grain_of(points)` query returning the owning grain index for arbitrary points, periodic-aware - `adjust_X` (Lloyd step) wraps periodic centroids back into the box - CPU tests in tests/test_apds_periodic.py Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add PyAPD/polycrystal_atomistic.py, which turns a periodic anisotropic
power diagram into a space-filling, periodic atomistic polycrystal and
writes a LAMMPS atomic data file ready for MD relaxation. The generator is
crystal-agnostic: it takes an orthorhombic conventional cell plus a
fractional basis, so it works for cubic crystals (SC/BCC/FCC/diamond/B2/...)
and for tetragonal/orthorhombic/HCP (HCP via a C-centred orthorhombic cell).
Core: `generate_polycrystal(cell, basis, n_atoms_target, n_grains, ...)`:
- builds a periodic APD (apd_system(periodic=True)) over an orthorhombic box
- samples a uniform-random SO(3) rotation per grain (Shoemake's method)
- fills each grain by the lattice block that is the PREIMAGE of the box
under that grain's rotation, rotated forward WITHOUT wrapping. A naive
rotate-a-finite-box-and-wrap fill is not space-filling for a generic
rotation: it leaves paired overlaps and matching interior voids. The
preimage-block fill is dense everywhere; only true cross-grain overlaps
and periodic-seam artifacts are then culled (pbc_pair_cull via a cKDTree).
The cull cutoff defaults to 0.85x the lattice nearest-neighbour distance,
computed automatically from (cell, basis).
Convenience wrappers: generate_bcc/fcc/sc_polycrystal(a, ...) and
generate_hcp_polycrystal(a, c, ...). Also exposes bulk_lattice_positions,
bulk_bcc_positions, shoemake_uniform_so3, pbc_pair_cull,
min_interatomic_distance, write_lammps_data, and a
`python -m PyAPD.polycrystal_atomistic --crystal {sc,bcc,fcc,hcp}` CLI.
Includes unit tests (cubic + orthorhombic) and a tutorial notebook. Builds
on the periodic-APD support added in the preceding commit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Owner
|
Looks great, cheers, will get back to you on that when I have time! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add atomistic polycrystal generation with curved (APD) grain boundaries
Motivation
With periodic APDs available, an APD tessellation can be turned directly into a periodic atomistic polycrystal: each grain is a randomly oriented crystal lattice, and the grain boundaries follow the curved, anisotropy-aware APD interfaces rather than flat Voronoi planes. This produces ready-to-use periodic cells for generating MD input, with realistic curved boundaries and per-grain crystallographic orientations.
This PR adds a self-contained, crystal-agnostic generator module and an end-to-end driver that writes a LAMMPS data file.
Summary of changes
New module
PyAPD/polycrystal_atomistic.py(re-exported fromPyAPD/__init__.py):generate_polycrystal(cell, basis, n_atoms_target, n_grains, ...)— general driver. Takes an orthorhombic conventionalcell(a scalar for cubic, or(ax, ay, az)) plus a fractionalbasis, so it builds any lattice: cubic (SC/BCC/FCC/diamond/B2/…) and tetragonal/orthorhombic/HCP. Builds a periodic APD over the box, optionally runs Lloyd iterations, samples a uniform-random orientation per grain, fills each grain, culls overlaps, and returns a bundle (positions,grain_ids,box(3-vector),cells,cell,basis,rotations,seeds, and theapd_system).generate_bcc_polycrystal(a, …),generate_fcc_polycrystal(a, …),generate_sc_polycrystal(a, …), andgenerate_hcp_polycrystal(a, c, …)(HCP via a C-centred orthorhombic supercell).min_interatomic_distance(cell, basis)— nearest-neighbour spacing of the lattice, used to set the cull cutoff automatically (override viann_distance=).bulk_lattice_positions(cell, basis, counts)/bulk_bcc_positions(a, m)— un-rotated reference lattices.shoemake_uniform_so3(rng)— uniform-random SO(3) rotation (Shoemake's quaternion method).pbc_pair_cull(positions, grain_ids, cutoff, box, cull_same_grain=False)— removes one atom of every too-close pair under PBC (per-axis box) using acKDTree.write_lammps_data(...)—atomic-style LAMMPS writer (accepts a scalar or per-axis box).python -m PyAPD.polycrystal_atomistic --crystal {sc,bcc,fcc,hcp}CLI.Space-filling grain-fill design (the key part)
The naive approach — generate one box-sized block, rotate it about the grain seed, and wrap by the box — is not space-filling for a generic rotation. Rotating a finite block and wrapping leaves seam planes through each grain with paired overlaps and matching gaps, so culling the overlaps leaves interior voids (roughly the cull fraction) distributed through grain interiors.
Instead, each grain is filled by the preimage of the box under that grain's rotation: the 8 box corners are inverse-rotated about the seed to bound a lattice block large enough (with a small margin) to cover the box after forward rotation; the block is rotated forward without wrapping; in-box atoms are kept; and
apd.grain_of()(from the periodic-APD PR) assigns each atom to a grain so only atoms actually owned by graingare retained. This is dense everywhere inside each grain; only true cross-grain grain-boundary overlaps and the unavoidable periodic-seam duplicates are then removed bypbc_pair_cullatcull_factor · nn_distance. The result is a periodic, space-filling polycrystal with no interior voids.Backward compatibility
Additive only. This PR introduces a new module and new public names; it changes no existing behaviour or signatures.
How it was tested
New CPU-only test module
tests/test_polycrystal_atomistic.py:min_interatomic_distancereturns the exact NN spacing for SC (a), BCC (a√3/2), FCC (a/√2), and HCP (a), including orthorhombic cells.shoemake_uniform_so3returns proper rotations (RᵀR = I,det = +1) and is unbiased (Haar mean ≈ 0 over 1000 samples).pbc_pair_cullkeeps same-grain pairs, drops cross-grain overlaps, and respects PBC for both cubic and per-axis (orthorhombic) boxes.lammps-data,atomic), confirming atom count, per-axis cell lengths, and bounds.A tutorial notebook,
notebooks/tutorials/periodic_polycrystal_bcc_fe.ipynb, walks through generating and inspecting a periodic BCC-Fe polycrystal end-to-end, with a closing section showing the FCC/HCP/custom-lattice wrappers.Not included
cell+basisper call (one phase / Bravais lattice); multi-phase composites are out of scope.atomic-style data file; other writers/formats are out of scope.Dependencies
This PR depends on #5 (periodic boundary support + the public
grain_of()query) and is built on top of its branch. Please review/merge that first; until it merges, this PR's diff also contains those commits.