Improve O(3) transformations and Wigner-D evaluation - #293
Conversation
Recover ZYZ angles without amplifying roundoff at Euler poles and consume structured wigner_D_array results directly. Require wigners 0.4 or newer for the structured API.
Correct spherical parity, protect transformation state, defer Wigner caches, and batch trusted random construction. Preserve System and TensorMap metadata/autograd while validating component metadata, system assignments, and dtype/device contracts. Expand focused CPU/CUDA coverage for the released and corrected behavior.
Document component labels, parity, ownership, lazy Wigner construction, system assignment, and supported random dtypes. Record the observable API changes and correctness fixes in the unreleased changelog.
Luthaf
left a comment
There was a problem hiding this comment.
just a quick look at the API changes, I'll do a deeper pass for the implementation & tests after everything is converged
| @classmethod | ||
| def _create_from_internal_matrix( | ||
| cls, | ||
| matrix: torch.Tensor, | ||
| max_angular_momentum: int, | ||
| *, | ||
| is_improper: bool, | ||
| ) -> "O3Transformation": | ||
| """Create a transformation from an internally generated matrix.""" | ||
| transformation = cls.__new__(cls) | ||
| transformation._matrix = matrix | ||
| transformation._max_angular_momentum = max_angular_momentum | ||
| transformation._is_improper = is_improper | ||
| transformation._wigner_D_cache = None | ||
| return transformation |
There was a problem hiding this comment.
What's the point of this compared to the constructor above?
There was a problem hiding this comment.
This private path is used only after random_transformations has generated and validated all matrices as one batch and already knows which one is proper/improper and It avoids repeating the public constructor’s per-matrix validation, copy, and determinant calculation.
Exported model wrappers can store Cartesian and Wigner-D matrices as registered tensor buffers, while the existing transform_tensor interface accepts Python O3Transformation objects and can not be compiled by TorchScript. Add a private tensor-only transformation path that consumes precomputed matrix batches while reusing the O(3) component, parity, routing, gradient, and metadata conventions. Add a private query for the largest spherical component rank present in TensorMap values or gradients, allowing callers to validate their serialized Wigner-D coverage. Keep the public O(3) API unchanged, and compare the new path directly with transform_tensor for proper and improper operations on CPU and CUDA.
Luthaf
left a comment
There was a problem hiding this comment.
The tests are very sloppy, checking minute details and drowning relevant information in a lot of lines and cases. This makes the test suite takes longer than needed for no reason, and makes it harder to understand the intent behind each test.
I would remove most of the tests that just check one error message in a very rare misuse of the API (i.e. sigma = SomeRandomClass()), and try to consolidate/clearly explain for each test why it is needed/what it is testing
2b1a9fb to
4863f80
Compare
4863f80 to
d8c324f
Compare
Luthaf
left a comment
There was a problem hiding this comment.
Getting there, some of the tests can be made more useful by checking the actual full message instead of a substring
|
Thank @MichelangeloDomina and @ppegolo for your work here! |
This PR extracts and improves the O(3)-only part initially developed in #119.
What changes
o3_sigma * (-1) ** o3_lambdaand is applied only to the improper O(3) component.wigner_D_arrayAPI directly.O3Transformation, and construct the Wigner cache only when spherical data is first requested.wigners >= 0.4.0for the structured Wigner-D API.Compatibility decisions
This PR proposes renaming
O3Transformation.is_invertedproperty tois_improper, which describes the actual condition (det(matrix) < 0) more precisely.The following observable behaviors also become explicit:
O3Transformationconstructor are copied, whilematrixandwigner_D_matrixretain their released no-copy return behavior;random_transformationsaccepts the model-capability dtypestorch.float32andtorch.float64;Performance evidence
The retained optimizations were isolated from correctness changes:
max_angular_momentum=4, this reduced creation time by 72.9% and creation plus Cartesian-only use by 71.9%. The Wigner-D cost is just deferred as shown by the fact that, when a spherical transformation was requested immediately, total time was unchanged within 0.2%.random_transformationsgenerated 32 to 4096 transformations, replacing separate validation of every 3×3 matrix with one batched validation reduced creation time by 82.7–97.9% on CPU float64 and 90.8–99.6% on CUDA.The compared matrices, proper/improper classifications, and representative Wigner-D results were identical.
Validation
metatomic-torchPython suite passed;Contributor (creator of pull-request) checklist
Reviewer checklist