materialsproject / pymatgen

Python Materials Genomics (pymatgen) is a robust materials analysis code that defines classes for structures and molecules with support for many electronic structure codes. It powers the Materials Project.
https://pymatgen.org
Other
1.52k stars 864 forks source link

Crash when using pymatgen.analysis.defects.point_defects.Interstitial #1135

Closed breathe closed 1 year ago

breathe commented 6 years ago

System

Summary

Attempting to use pymatgen to find Interstitials via Zeo++ Voronoi analysis. I followed installation/setup directions from here http://pymatgen.org/installation.html#zeo -- and am encountering a crash when running the test script.

Error message

<... snip ...>
Finding channels and pockets in Dijkstra network of 928 node(s). 928 are expected to compose pores.
Analyzed and assigned 928 nodes.
Identified 1 channels and 0 pockets.
928 nodes assigned to pores.
Traceback (most recent call last):
  File "test_script.py", line 19, in <module>
    interstitial = Interstitial(structure, radii=radii, valences=valences, oxi_state=True)
  File "/Users/bcohen/anaconda3/envs/suzytest/lib/python3.6/site-packages/pymatgen/analysis/defects/point_defects.py", line 512, in __init__
    coord_no, coord_sites, chrg = self._get_coord_no_sites_chrg(site)
  File "/Users/bcohen/anaconda3/envs/suzytest/lib/python3.6/site-packages/pymatgen/analysis/defects/point_defects.py", line 547, in _get_coord_no_sites_chrg
    if not site.specie.symbol == 'X':
AttributeError: 'int' object has no attribute 'specie'

Suggested solution (if any)

Is it possible that the intention is for _get_coord_no_sites_chrg to call get_nn_info (which internally calls get_voronoi_polyhedra) rather than calling get_voronoi_polyhedra directly?

Making this modification causes code to run -- however not sure if capturing the correct physics ... I believe the polyhedra property used to calculate weight by default will be the polyhedral 'solid_angle' ... is that the correct 'weight' property for this purpose ... ?

    def _get_coord_no_sites_chrg(self, site):
        """
        Compute the coordination number and coordination charge

        Args:
            site:
                pymatgen.core.sites.Site
        """
        struct = self._structure.copy()
        struct.append(site.specie.symbol, site.frac_coords)
        vnn = VoronoiNN()
        coord_no = vnn.get_cn(struct, -1, use_weights=True)
        coord_sites = vnn.get_nn(struct, -1)

        # In some cases coordination sites to interstitials include
        # interstitials also. Filtering them.
        def no_inter(site):
            return not site.specie.symbol == 'X'

        coord_sites = filter(no_inter, coord_sites)

        coord_chrg = 0
        if self._valence_dict:
            for params in vnn.get_nn_info(struct, -1):
                site = params['site']
                weight = params['weight']
                if not site.specie.symbol == 'X':
                    coord_chrg += weight * self._valence_dict[
                        site.species_string]

        return coord_no, coord_sites, coord_chrg

Files (if any)

The error reproduces for me with any POSCAR file tried -- but here is the one I'm interested in using ...

POSCAR.txt

And for completeness -- minimal test script I use (same as linked from installation instructions)

import os
from pymatgen.analysis.defects.point_defects import Interstitial
from pymatgen.core.structure import Structure

structure = Structure.from_file(os.path.abspath('./POSCAR.txt'))

radii, valences = {}, {}

for element in structure.composition.elements:
    radii[element.symbol] = element.atomic_radius
    valence = element.group  # Just a first guess..
    if element.group > 12:
        valence -= 10
    valences[element.symbol] = valence

interstitial = Interstitial(structure, radii=radii, valences=valences, oxi_state=True)
interstitial._defect_sites

For some more context (if it helps) -- here is the actual computation wanting to run ...

from pymatgen.core.structure import Structure #For reading in structure files
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer #For checking tolerance to recognise correct spacegroup of supercell
from pymatgen.analysis.defects.point_defects import Interstitial, ValenceIonicRadiusEvaluator #For generating interstitials

# Load perfect supercell (in POSCAR format)
structure = Structure.from_file("./POSCAR.txt") 

# Check pymatgen recognises the correct spacegroup for the input supercell at given tolerance
precision=0.01
spacegroup = SpacegroupAnalyzer(structure, symprec=precision, angle_tolerance=5)
print("")
print("The spacegroup of enargite should be 31")
print("What does pymatgen recognise the symmetry of the supercell as with a symmetry precision of "+str(precision)+"...?")
print(spacegroup.get_space_group_number())
print("")

print("May need to ensure interstitial finder uses the same tolerance..? (Default value is 1e-1?)")
print("")

### CHECK - need to make symprec equal to above???
# Use Voronoi analysis from pymatgen class 'Interstitial(Defect)' to identify all symmetrically distinct interstitial sites?
### Inputs for valences and radii redudnant when oxi_state=False, if allowing ValenceIonicRadiusEvaluator to analyse it
valences = {"As" : 5, "Cu" : 1, "S" : -2} #Set manually because evaluator gave Cu+ and Cu2+
#valences = {}
# Google search for ionic radii of above elements, taken from: http://abulafia.mt.ic.ac.uk/shannon/ptable.php
radii = {"As" : 0.335, "Cu" : 0.6, "S" : 1.84}
#radii = []

#evaluator = ValenceIonicRadiusEvaluator(structure)
find_interstitials = Interstitial(structure, radii=radii, valences=valences, site_type='voronoi_vertex', accuracy='Normal', symmetry_flag=True, oxi_state=True)
#find_interstitials = Interstitial(structure, radii=evaluator.radii, valences=evaluator.valences, site_type='voronoi_vertex', accuracy='Normal', symmetry_flag=True, oxi_state=False)

scaling_matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] #Identity matrix, don't actually want to make supercell of my supercell
#print(find_interstitials.make_supercells_with_defects(scaling_matrix, "Cu"))
interstitial_supercells = find_interstitials.make_supercells_with_defects(scaling_matrix, "Cu")
print("Number of symmetrically unique interstitial sites is %s" %(len(interstitial_supercells)))

i = 0
for supercell in interstitial_supercells:
    i = i + 1
    filename = "supercell_POSCAR_"+str(i)+".vasp"
    structure = supercell
    structure.to(filename=filename)

@skw32

Many thanks! Let us know if we can provide more info to help track this down!

shyuep commented 1 year ago

Seems like this issue has been defunct for many years. Closing.... Feel free to reopen if still valid.