symmetric_graph
Symmetric graph framework for crystal structures.
This module provides the foundation for representing any graph structure (bonds, contacts, interactions) on a crystal with full symmetry awareness. The key insight is that the asymmetric unit of the graph completely determines the full periodic graph via the group action.
Core abstractions: - AlgebraicVertexRef: Universal vertex reference (asym_idx, symop_idx, cell) - AlgebraicEdge: Edge between two vertices with canonical form - CosetTable: Abstract interface for handling site symmetry
The group action on vertices uses the Cayley table from SpaceGroupTable
g(v) = AlgebraicVertexRef( asym_idx = v.asym_idx, # unchanged symop_idx = mult[v.symop_idx, g], # group multiplication cell = R_g @ v.cell # rotate lattice vector )
AlgebraicEdge
dataclass
Edge in a symmetric graph.
Stored in canonical form where: 1. src <= dst lexicographically 2. src.cell = (0, 0, 0) (normalized by lattice translation)
This ensures each unique edge has exactly one representation.
Attributes:
| Name | Type | Description |
|---|---|---|
src |
AlgebraicVertexRef
|
Source vertex reference (always <= dst after normalization) |
dst |
AlgebraicVertexRef
|
Destination vertex reference |
Source code in chmpy/crystal/symmetric_graph.py
create(v1, v2)
classmethod
Create an AlgebraicEdge with automatic canonical ordering.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
v1
|
AlgebraicVertexRef
|
First vertex |
required |
v2
|
AlgebraicVertexRef
|
Second vertex |
required |
Returns:
| Type | Description |
|---|---|
AlgebraicEdge
|
AlgebraicEdge with src <= dst |
Source code in chmpy/crystal/symmetric_graph.py
involves_vertex_type(asym_idx)
is_homo_edge()
AlgebraicVertexRef
dataclass
Universal vertex reference for any symmetric graph.
This generalizes AlgebraicMoleculeRef and AlgebraicAtomRef into a single abstraction. The actual vertex is: g_{symop_idx}(asym_vertex[asym_idx]) + cell
Attributes:
| Name | Type | Description |
|---|---|---|
asym_idx |
int
|
Index in the asymmetric unit (unique vertex type) |
symop_idx |
int
|
Index of generating space group operation |
cell |
tuple[int, int, int]
|
(h, k, l) lattice translation as a tuple of integers |
Source code in chmpy/crystal/symmetric_graph.py
__ge__(other)
__gt__(other)
__le__(other)
__lt__(other)
with_cell(new_cell)
Return a copy with a different cell offset.
CosetTable
Bases: ABC
Abstract interface for handling site symmetry (special positions).
When vertices lie on special positions (Wyckoff sites with non-trivial site symmetry), multiple symops can generate the same vertex. This table tracks which vertices each symop generates and provides canonical representatives.
Concrete implementations: - AtomicCosetTable: For atoms on special positions - MolecularCosetTable: For molecules on special positions (in dimer_index.py)
Source code in chmpy/crystal/symmetric_graph.py
n_symops
abstractmethod
property
Number of space group operations.
n_vertices
abstractmethod
property
Number of vertices in the unit cell.
normalize_symop(symop_idx)
abstractmethod
Normalize a symop index to (vertex_idx, canonical_symop_idx).
For vertices on special positions, multiple symops map to the same vertex. This returns the canonical (smallest index) symop that generates the vertex.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symop_idx
|
int
|
The symop index to normalize |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int]
|
Tuple of (vertex_idx, canonical_symop_idx) |
Source code in chmpy/crystal/symmetric_graph.py
site_symmetry_order(vertex_idx)
abstractmethod
Get the order of site symmetry for a vertex.
For general positions, this is 1. For special positions on a symmetry element of order k, this is k.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vertex_idx
|
int
|
Index of vertex in unit cell |
required |
Returns:
| Type | Description |
|---|---|
int
|
Order of site symmetry (number of symops that fix this vertex) |
Source code in chmpy/crystal/symmetric_graph.py
SymmetricGraph
dataclass
Base class for symmetric graphs on crystals.
A SymmetricGraph stores only the asymmetric unit representatives of edges. The full graph is implicitly defined via the space group action.
Attributes:
| Name | Type | Description |
|---|---|---|
sg_table |
SpaceGroupTable
|
SpaceGroupTable for the crystal's space group |
coset_table |
CosetTable | None
|
CosetTable for handling site symmetry (or None) |
n_asym_vertices |
int
|
Number of vertices in the asymmetric unit |
asym_edges |
set[AlgebraicEdge]
|
Set of canonical edge representatives |
Source code in chmpy/crystal/symmetric_graph.py
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 | |
add_edge(v1, v2)
Add an edge between v1 and v2 (and all equivalent edges).
Only the canonical representative is stored; all symmetry-equivalent edges are implicitly added.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
v1
|
AlgebraicVertexRef
|
First vertex |
required |
v2
|
AlgebraicVertexRef
|
Second vertex |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the edge was newly added, False if already present |
Source code in chmpy/crystal/symmetric_graph.py
all_edges()
Iterate over all edges (full orbit expansion).
Yields:
| Type | Description |
|---|---|
AlgebraicEdge
|
All edges in all orbits |
Source code in chmpy/crystal/symmetric_graph.py
edges_at_vertex(vertex)
Find all edges incident to a specific vertex.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vertex
|
AlgebraicVertexRef
|
The vertex to query |
required |
Returns:
| Type | Description |
|---|---|
list[AlgebraicEdge]
|
List of edges incident to this vertex |
Source code in chmpy/crystal/symmetric_graph.py
has_edge(v1, v2)
Check if an edge exists between v1 and v2.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
v1
|
AlgebraicVertexRef
|
First vertex |
required |
v2
|
AlgebraicVertexRef
|
Second vertex |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the edge exists |
Source code in chmpy/crystal/symmetric_graph.py
n_total_edges()
Return the total number of edges (sum of orbit sizes).
n_unique_edges()
remove_edge(v1, v2)
Remove the edge between v1 and v2 (and all equivalent edges).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
v1
|
AlgebraicVertexRef
|
First vertex |
required |
v2
|
AlgebraicVertexRef
|
Second vertex |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the edge was removed, False if not present |
Source code in chmpy/crystal/symmetric_graph.py
unique_edges_with_multiplicities()
Get unique edges with their multiplicities.
Returns:
| Type | Description |
|---|---|
list[tuple[AlgebraicEdge, int]]
|
List of (edge, multiplicity) tuples |
Source code in chmpy/crystal/symmetric_graph.py
apply_symop_to_edge(edge, symop_idx, sg_table, coset_table=None)
Apply a space group operation to an edge.
This transforms both vertices and returns the result in canonical form.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge
|
AlgebraicEdge
|
The edge to transform |
required |
symop_idx
|
int
|
Index of the symop to apply |
required |
sg_table
|
SpaceGroupTable
|
The precomputed space group table |
required |
coset_table
|
CosetTable | None
|
Optional coset table for symop normalization |
None
|
Returns:
| Type | Description |
|---|---|
AlgebraicEdge
|
Transformed AlgebraicEdge in canonical form |
Source code in chmpy/crystal/symmetric_graph.py
apply_symop_to_vertex(vertex, symop_idx, sg_table, coset_table=None)
Apply a space group operation to a vertex reference.
This is a purely algebraic operation using the group multiplication table: - The new symop index is computed via the Cayley table - The cell offset is transformed by the rotation part of the symop - If coset_table is provided, normalizes the symop to canonical
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vertex
|
AlgebraicVertexRef
|
The vertex to transform |
required |
symop_idx
|
int
|
Index of the symop to apply |
required |
sg_table
|
SpaceGroupTable
|
The precomputed space group table |
required |
coset_table
|
CosetTable | None
|
Optional coset table for symop normalization |
None
|
Returns:
| Type | Description |
|---|---|
AlgebraicVertexRef
|
Transformed AlgebraicVertexRef |
Source code in chmpy/crystal/symmetric_graph.py
canonical_edge_representative(edge, sg_table, coset_table=None)
Find the canonical representative of an edge under the group action.
The canonical representative is the lexicographically smallest element of the orbit of the edge under all space group operations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge
|
AlgebraicEdge
|
The edge to canonicalize |
required |
sg_table
|
SpaceGroupTable
|
SpaceGroupTable for the space group |
required |
coset_table
|
CosetTable | None
|
Optional coset table for symop normalization |
None
|
Returns:
| Type | Description |
|---|---|
AlgebraicEdge
|
The canonical representative (smallest in orbit) |
Source code in chmpy/crystal/symmetric_graph.py
compute_edge_orbit(edge, sg_table, coset_table=None)
Compute the full orbit of an edge under the space group action.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge
|
AlgebraicEdge
|
The edge to compute orbit for |
required |
sg_table
|
SpaceGroupTable
|
SpaceGroupTable for the space group |
required |
coset_table
|
CosetTable | None
|
Optional coset table for symop normalization |
None
|
Returns:
| Type | Description |
|---|---|
list[AlgebraicEdge]
|
List of all distinct edges in the orbit |
Source code in chmpy/crystal/symmetric_graph.py
compute_edge_orbit_size(edge, sg_table, coset_table=None)
Compute the orbit size of an edge under the space group action.
This is the number of distinct edges obtained by applying all space group operations. This represents the multiplicity - how many symmetry-equivalent copies of this edge exist in the crystal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge
|
AlgebraicEdge
|
The edge to compute orbit size for |
required |
sg_table
|
SpaceGroupTable
|
SpaceGroupTable for the space group |
required |
coset_table
|
CosetTable | None
|
Optional coset table for symop normalization |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Size of the orbit (number of distinct images) |
Source code in chmpy/crystal/symmetric_graph.py
edges_in_same_orbit(edge1, edge2, sg_table, coset_table=None)
Check if two edges are in the same symmetry orbit.
Two edges are equivalent if they have the same canonical representative.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge1
|
AlgebraicEdge
|
First edge |
required |
edge2
|
AlgebraicEdge
|
Second edge |
required |
sg_table
|
SpaceGroupTable
|
SpaceGroupTable for the space group |
required |
coset_table
|
CosetTable | None
|
Optional coset table for symop normalization |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
True if edges are symmetry-equivalent |
Source code in chmpy/crystal/symmetric_graph.py
normalize_edge(edge, sg_table)
Normalize an edge to canonical form.
Normalization ensures: 1. src <= dst (lexicographic ordering by asym_idx, symop_idx, then cell) 2. The "smaller" vertex is at cell (0, 0, 0)
This is necessary because edges that differ only by a lattice translation are equivalent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edge
|
AlgebraicEdge
|
The edge to normalize |
required |
sg_table
|
SpaceGroupTable
|
The precomputed space group table |
required |
Returns:
| Type | Description |
|---|---|
AlgebraicEdge
|
Normalized AlgebraicEdge |