-
Notifications
You must be signed in to change notification settings - Fork 61
Mixed Pbc Support #320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Mixed Pbc Support #320
Conversation
| if not all(all(at.pbc) == all(phonopy_atoms_lst[0].pbc) for at in phonopy_atoms_lst): | ||
| raise ValueError("All systems must have the same periodic boundary conditions") | ||
| """ | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unfamiliar with this "supercell" thing. but I deleted it because I think that phononpy always has periodic boundary conditions (https://github.com/phonopy/phonopy/blob/develop/phonopy/structure/atoms.py#L140)? Maybe I just revert this change and we can talk it out in a different PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Phonopy only makes sense for periodic crystal, although I can imagine that some people may want to that for some kind of 2D crystals with a small z-axis thickness. Sounds reasonable to me to keep that.
| cell=cell, | ||
| pbc=self.pbc, | ||
| cutoff=self.cutoff, | ||
| sorti=False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep. this is a spelling mistake
|
|
||
| # Fix: Ensure pbc has the correct shape [n_systems, 3] | ||
| pbc_tensor = torch.tensor([[pbc] * 3] * len(atoms_list), dtype=torch.bool) | ||
| pbc_tensor = torch.tensor(pbc).repeat(state.n_systems, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this repeat is needed since torch_nl_linked_cell accepts (num_systems, 3) for the pbc. it doens't just accept a tensor of shape (3,)
94065f9 to
88d8036
Compare
| assert trajectory.get_array("atomic_numbers").shape == (1, 10) | ||
| assert trajectory.get_array("cell").shape == (1, 3, 3) | ||
| assert trajectory.get_array("pbc").shape == (1,) | ||
| assert trajectory.get_array("pbc").shape == (1, 3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure this is the correct test. should it be shape (1,3) or just shape (3,)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think pbc should be system_attributes so I would argue for (1, 3)
| positions=system_positions, | ||
| types=system_atomic_numbers, | ||
| cell=system_cell, | ||
| pbc=system_pbc, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the simstate.pbc is a torch.Tensor by default now! so we don't need this
| @torch.jit.script | ||
| def primitive_neighbor_list( # noqa: C901, PLR0915 | ||
| quantities: str, | ||
| pbc: tuple[bool, bool, bool], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a breaking change. but I'm fine with this change because this will make pbc match all of the other params. if this param was bool originally, I'd probably want to make it a torch.Tensor | bool instead.
Another reason why I don't want to do torch.Tensor | bool is because I think that torch.jit.script will be slightly confused by union types (and I'll need to manually specify overrides)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems reasonable
| wrapped_frac = frac_coords.clone() | ||
| wrapped_frac[:, pbc[0]] = frac_coords[:, pbc[0]] % 1.0 | ||
| wrapped_frac[:, pbc[1]] = frac_coords[:, pbc[1]] % 1.0 | ||
| wrapped_frac[:, pbc[2]] = frac_coords[:, pbc[2]] % 1.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried wrapped_frac[:, pbc] = frac_coords[:, pbc] % 1.0 and it doesn't work :'(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure it doesn't work?
It's a deprecated method, we may not want to adapt it and use it.
If we do want to keep it, pbc needs to be a (d,) shape and so this method doesn't work (I'm actually surprise it would work here. It probably only does because you provide a (n_systems, 3) pbc tensor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So yes actually the answer is my last observation. But as you don't have a system_idx, you probably need to squeeze to account for (1, d) shape and if n_systems>1 raise an error
5aba8d7 to
fcf1d1a
Compare
|
there is an annoying bug with torch.jit that I'm trying to solve in a test (our nl function takes too long bc we are timing the compilation and the invocation of the function I believe) but the main API for this is pretty much done. So you can review if you want |
19029e5 to
4f77996
Compare
wrap only the pbc axis for each atom support init simstate with list of bools better test that uses itertools update vesin version fix pbc check in integrators fix more pytests more fixing more fixes VesinNeighborListTorch is slow fix metatensor for pbc more fixes wip fix pbc trajectory trajectory runs bump metatomic version or vesin will complain fix errors wip fix more trajectory issues make trajectory pass fix pbc in diff_sim fix ase atoms to state conversion for pbc fix neighbors.py assert the pymatgen pbc is valid proper conversion between pbc for atoms, and pymatgen do not pass in pbc to phononpy rm warning and add doc to github make consistent with prev implementation fix io tests lint minor simplification simplify test more simplification changes fix some tests satisfy prek but ruff check errors :/ we'll fix this later more cleanup rename renamove more diffs more changes wip fix rm init in md add type checking and fix pbc type in dataclass def cleanup state loosen test for nl
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some modifications are needed in ts.transforms. Otherwise looks correct to me.
I would also suggest using this PR to port pbc to system_attributes
| wrapped_frac = frac_coords.clone() | ||
| wrapped_frac[:, pbc[0]] = frac_coords[:, pbc[0]] % 1.0 | ||
| wrapped_frac[:, pbc[1]] = frac_coords[:, pbc[1]] % 1.0 | ||
| wrapped_frac[:, pbc[2]] = frac_coords[:, pbc[2]] % 1.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure it doesn't work?
It's a deprecated method, we may not want to adapt it and use it.
If we do want to keep it, pbc needs to be a (d,) shape and so this method doesn't work (I'm actually surprise it would work here. It probably only does because you provide a (n_systems, 3) pbc tensor.
| wrapped_frac = frac_coords.clone() | ||
| wrapped_frac[:, pbc[0]] = frac_coords[:, pbc[0]] % 1.0 | ||
| wrapped_frac[:, pbc[1]] = frac_coords[:, pbc[1]] % 1.0 | ||
| wrapped_frac[:, pbc[2]] = frac_coords[:, pbc[2]] % 1.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So yes actually the answer is my last observation. But as you don't have a system_idx, you probably need to squeeze to account for (1, d) shape and if n_systems>1 raise an error
| # Wrap to reference cell [0,1) using modulo | ||
| wrapped_frac = frac_coords % 1.0 | ||
| wrapped_frac = frac_coords.clone() | ||
| wrapped_frac[:, pbc[0]] = frac_coords[:, pbc[0]] % 1.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same remark, but now account for systems_idx:
wrapped_frac[pbc[system_idx]] should work
| if cell is None or not pbc.any(): | ||
| return dr | ||
|
|
||
| # Convert to fractional coordinates |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to adapt the rest of the function to account for mixed periodicity.
Chatgpt suggests this, which I think is correct:
dr_frac -= torch.where(pbc, torch.round(dr_frac), torch.zeros_like(dr_frac))
| A tensor containing the positions of atoms wrapped inside | ||
| their respective unit cells. | ||
| cell (torch.Tensor [3*n_structure, 3]): Unit cell vectors according to | ||
| cell (torch.Tensor [3*num_systems, 3]): Unit cell vectors according to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather use n_systems to be consistent with SimState
| @torch.jit.script | ||
| def primitive_neighbor_list( # noqa: C901, PLR0915 | ||
| quantities: str, | ||
| pbc: tuple[bool, bool, bool], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems reasonable
| if not all(all(at.pbc) == all(phonopy_atoms_lst[0].pbc) for at in phonopy_atoms_lst): | ||
| raise ValueError("All systems must have the same periodic boundary conditions") | ||
| """ | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Phonopy only makes sense for periodic crystal, although I can imagine that some people may want to that for some kind of 2D crystals with a small z-axis thickness. Sounds reasonable to me to keep that.
| assert trajectory.get_array("atomic_numbers").shape == (1, 10) | ||
| assert trajectory.get_array("cell").shape == (1, 3, 3) | ||
| assert trajectory.get_array("pbc").shape == (1,) | ||
| assert trajectory.get_array("pbc").shape == (1, 3) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think pbc should be system_attributes so I would argue for (1, 3)
Summary
Updates torchsim to use the latest version of Vesin which supports mixed PBC neighborlist calculations.
Checklist
Before a pull request can be merged, the following items must be checked:
We highly recommended installing the
prekhooks running in CI locally to speedup the development process. Simply runpip install prek && prek installto install the hooks which will check your code before each commit.