nvalchemi.data.AtomicData#
- pydantic model nvalchemi.data.AtomicData[source]#
Graph-structured container for a single atomic system.
AtomicDatais the core input/output record throughout nvalchemi: a molecule, cluster, or periodic cell represented as a graph whose nodes are atoms and whose (optional) edges encode pairwise interactions. It is apydantic.BaseModel, so every tensor field is type- and shape-validated on construction, and it mixes inDataMixinfor graph conveniences (indexing, device movement, property grouping, serialization).The only required fields are
positions([V, 3]) andatomic_numbers([V]); everything else — neighbor lists, cell/PBC, labels such asenergy/forces/stress, velocities — is optional and defaults toNone. Fields are organized into node-, edge-, and system-level groups (seenode_properties,edge_properties,system_properties), and custom keys can be attached at runtime viaadd_node_property(),add_edge_property(), andadd_system_property()(extra="allow"on the model config permits these). To collate many systems into one GPU-friendly graph, pass a list ofAtomicDatatoBatch.Beyond the plain constructor, build instances from common toolkits with the
from_atoms()(ASEAtoms) andfrom_structure()(pymatgenStructure/Molecule) classmethods. Severalmodel_validatorhooks run after construction and shape the resulting object: node/edge tensor counts are checked for consistency againstatomic_numbers/neighbor_list; all floating-point tensors are cast to the dtype ofpositions(emitting aUserWarningwhen a cast happens);atomic_massesare auto-filled fromperiodictablewhen omitted; and all tensors are moved onto a single consistent device.Each field below is validated by its type. Field shapes use jaxtyping axis labels:
Vatoms/nodes,Eedges,Bgraphs (batch),Hfeatures.Examples
Minimal construction requires only positions and atomic numbers:
>>> import torch >>> from nvalchemi.data import AtomicData >>> positions = torch.randn(4, 3) >>> atomic_numbers = torch.tensor([1, 6, 6, 1], dtype=torch.long) >>> data = AtomicData(positions=positions, atomic_numbers=atomic_numbers) >>> data.num_nodes 4
Attach edges (a neighbor list of
[source, target]pairs) and system-level labels for a periodic cell:>>> neighbor_list = torch.tensor([[0, 1], [1, 0], [1, 2], [2, 1]]) >>> data = AtomicData( ... positions=positions, ... atomic_numbers=atomic_numbers, ... neighbor_list=neighbor_list, ... energy=torch.tensor([[0.5]]), ... cell=torch.eye(3).unsqueeze(0), ... pbc=torch.tensor([[True, True, True]]), ... ) >>> data.num_edges 4
Interoperate with ASE and batch several systems together:
>>> from ase.build import molecule >>> from nvalchemi.data import Batch >>> water = AtomicData.from_atoms(molecule("H2O")) >>> batch = Batch.from_data_list([data, water])
Notes
atomic_massesis optional but never staysNone: when omitted it is populated fromperiodictableusingatomic_numbers.Floating-point fields are coerced to the dtype of
positions; passing afloat64label alongsidefloat32positions triggers a cast and aUserWarning. Pass matching dtypes to silence it.validate_assignment=Truemeans re-assigning a field re-runs validation; useadd_node_property()and friends (not raw attribute assignment) to register new custom keys so they are tracked in the correct property group.
- field atomic_numbers: Integer[Tensor, 'V'] [Required]#
Atomic numbers for each node [n_nodes]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field positions: Float[Tensor, 'V 3'] [Required]#
Cartesian coordinates for each atom [n_nodes, 3]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field atomic_masses: Float[Tensor, 'V'] | None = None#
Atomic masses [n_nodes]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field atom_categories: list[AtomCategory] | Integer[Tensor, 'V'] | None = None#
Atom categorical index, based on _typing.AtomCategory Enum [n_nodes]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field neighbor_list: Integer[Tensor, 'E 2'] | None = None#
Neighbor list [n_edges, 2]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field shifts: Float[Tensor, 'E 3'] | None = None#
Cartesian displacement vectors for each edge (neighbor_list_shifts @ cell) [n_edges, 3]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field neighbor_list_shifts: Num[Tensor, 'E 3'] | None = None#
Integer lattice image indices for periodic edges [n_edges, 3]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field neighbor_matrix: Integer[Tensor, 'V K'] | None = None#
Dense neighbor matrix [n_nodes, max_neighbors]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field neighbor_matrix_shifts: Num[Tensor, 'V K 3'] | None = None#
Periodic shifts for the dense neighbor matrix [n_nodes, max_neighbors, 3]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field num_neighbors: Integer[Tensor, 'V'] | None = None#
Number of valid neighbors per atom [n_nodes]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field cell: Float[Tensor, 'B 3 3'] | None = None#
Unit cell vectors [3, 3]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field pbc: Bool[Tensor, 'B 3'] | None = None#
Boolean tensor indicating periodic boundary conditions along each dimension
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field forces: Float[Tensor, 'V 3'] | None = None#
Atomic forces [n_nodes, 3]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field energy: Float[Tensor, 'B 1'] | None = None#
Total energy [1, 1]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field stress: Float[Tensor, 'B 3 3'] | None = None#
Tensile-positive Cauchy stress (eV/A^3) [1, 3, 3]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field virial: Float[Tensor, 'B 3 3'] | None = None#
Virial tensor [1, 3, 3]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field dipole: Float[Tensor, 'B 3'] | None = None#
Dipole moment of the system.
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field charges: Float[Tensor, 'V'] | None = None#
Partial atomic charges [n_nodes]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field charge: Float[Tensor, 'B 1'] | None = None#
Total system charge [1, 1]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field node_attrs: Float[Tensor, 'V A'] | None = None#
Node attributes [n_nodes, n_node_attrs]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field node_alpha_spins: Float[Tensor, 'V 1'] | None = None#
Alpha spins for each atom, [n_nodes, 1]. Use this field for closed-shell spins.
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field node_beta_spins: Float[Tensor, 'V 1'] | None = None#
Beta spins for each atom, [n_nodes, 1]. For restricted spin, use
node_alpha_spinsinstead.- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field spin: Float[Tensor, 'B 1'] | None = None#
Spin or multiplicity value for the system, [1, 1]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field graph_alpha_spins: Float[Tensor, 'B 1'] | None = None#
Alpha spins for the entire graph, [1, 1]
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field node_embeddings: Float[Tensor, 'V H'] | None = None#
Embeddings for each node within the batch/graph.
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field edge_embeddings: Float[Tensor, 'E H'] | None = None#
Embeddings for each edge within the batch/graph.
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field graph_embeddings: Float[Tensor, 'B H'] | None = None#
Embeddings for the entire graph/graphs within a batch.
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field velocities: Float[Tensor, 'V 3'] | None = None#
Atomic velocities [n_nodes, 3], in units set by positions.
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field momenta: Float[Tensor, 'V 3'] | None = None#
Atomic momenta [n_nodes, 3], in units set by positions.
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json
- field kinetic_energies: Float[Tensor, 'V 1'] | None = None#
Per-atom kinetic energies [n_nodes, 1], with the same units as energy.
- Constraints:
func = <function _tensor_serialization at 0xeb0d9239b420>
return_type = PydanticUndefined
when_used = json