-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Hi,
I have two questions on the return value of determine_topology.
The first one concerns its length / the number of substructures with disjoint vertices.
Is it expected behaviour that this depends on the number of lattice points of the input structure provided?
Intuitively, I would expect different representations of the same crystal structure to yield the same determine_topology result but maybe I misunderstood the documentation there.
I appended 2 examples that compare the determine_topology output of (a) a structure and its 2x2x2 superstructure and (b) a centered structure and its primitive.
(CrystalNets.jl v1.1.1)
import juliacall
from pymatgen.core import Structure, Lattice
from pymatgen.analysis.local_env import NearNeighbors, JmolNN
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
jl = juliacall.newmodule("Topo")
jl.seval("using CrystalNets")
options_input = jl.CrystalNets.Options(bonding=jl.CrystalNets.Bonding.Input,
export_input=False,
export_subnets=False,
export_net=False)
def write_bonded_cif(nn: NearNeighbors, structure: Structure, file_name: str):
bonds = []
for site_id, site in enumerate(structure.sites):
nbs = nn.get_nn_info(structure=structure, n=site_id)
for nb in nbs:
site_str = f"{site.species_string}{site_id}"
site_to_str = f"{nb['site'].species_string}{nb['site_index']}"
length = nb["site"].nn_distance
bond_str = f"{site_str} {site_to_str} {length}"
reverse_bond_str = f"{site_to_str} {site_str} {length}"
if bond_str not in bonds and reverse_bond_str not in bonds:
bonds.append(bond_str)
topo_strings = ["loop_", "_geom_bond_atom_site_label_1", "_geom_bond_atom_site_label_2", "_geom_bond_distance"] +bonds
structure.to_file(file_name)
with open(file_name, "a") as file:
for line in topo_strings:
file.write(line + "\n")
# Example structure and 2x2x2 superstructure
structure = Structure.from_spacegroup(
"Pmmm", Lattice.orthorhombic(3.3, 7, 7), ["Po"], [[0, 0, 0],]
)
super_structure = structure.make_supercell(scaling_matrix=[2, 2, 2], in_place=False)
file_name_simple = "structure.cif"
write_bonded_cif(nn=JmolNN(), structure=structure, file_name=file_name_simple)
res = jl.determine_topology(file_name_simple, options_input
)
print("simple topo: ", len(res))
print(res)
file_name_super = "superstructure.cif"
write_bonded_cif(nn=JmolNN(), structure=super_structure, file_name=file_name_super)
super_res = jl.determine_topology(file_name_super, options_input
)
print("2x2x2 superstructure topo: ", len(super_res))
print(super_res)
Output:
simple topo: 1
1-rod (1 1 1 1)
2x2x2 superstructure topo: 4
4 interpenetrated substructures:
⋅ Subnet 1 → 1-rod (1 1 1 1)
⋅ Subnet 2 → 1-rod (1 1 1 1)
⋅ Subnet 3 → 1-rod (1 1 1 1)
⋅ Subnet 4 → 1-rod (1 1 1 1)
# Example with centered vs. primitive lattice
centered_structure = Structure.from_spacegroup(
"Cmmm", Lattice.orthorhombic(3.3, 9, 9), ["Po"], [[0, 0, 0]]
)
sga_centered = SpacegroupAnalyzer(structure=centered_structure)
primitive_structure = sga_centered.get_primitive_standard_structure()
file_name_centered = "centered_structure.cif"
write_bonded_cif(nn=JmolNN(), structure=centered_structure, file_name=file_name_centered)
centered_res = jl.determine_topology(file_name_centered, options_input
)
print("centered structure topo: ", len(centered_res))
print(centered_res)
file_name_primitive = "primitive_structure.cif"
write_bonded_cif(nn=JmolNN(), structure=primitive_structure, file_name=file_name_primitive)
primitive_res = jl.determine_topology(file_name_primitive, options_input
)
print("primitive structure topo: ", len(primitive_res))
print(primitive_res)
Output:
centered structure topo: 2
2 interpenetrated substructures:
⋅ Subnet 1 → 1-rod (1 1 1 1)
⋅ Subnet 2 → 1-rod (1 1 1 1)
primitive structure topo: 1
1-rod (1 1 1 1)
My second question is: is it possible to get the full topological genome of a crystal structure that has multiple substructures with disjoint vertices, not only the genomes of the substructures?
Thanks in advance!